1 /* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 #ifndef SkBmpCodec_DEFINED 8 #define SkBmpCodec_DEFINED 9 10 #include "include/codec/SkCodec.h" 11 #include "include/codec/SkEncodedImageFormat.h" 12 #include "include/core/SkColorType.h" 13 #include "include/core/SkTypes.h" 14 #include "modules/skcms/skcms.h" 15 16 #include <cstddef> 17 #include <cstdint> 18 #include <memory> 19 20 class SkStream; 21 struct SkEncodedInfo; 22 struct SkImageInfo; 23 24 /* 25 * This class enables code sharing between its bmp codec subclasses. The 26 * subclasses actually do the work. 27 */ 28 class SkBmpCodec : public SkCodec { 29 public: 30 static bool IsBmp(const void*, size_t); 31 32 /* 33 * Assumes IsBmp was called and returned true 34 * Creates a bmp decoder 35 * Reads enough of the stream to determine the image format 36 */ 37 static std::unique_ptr<SkCodec> MakeFromStream(std::unique_ptr<SkStream>, Result*); 38 39 /* 40 * Creates a bmp decoder for a bmp embedded in ico 41 * Reads enough of the stream to determine the image format 42 */ 43 static std::unique_ptr<SkCodec> MakeFromIco(std::unique_ptr<SkStream>, Result*); 44 45 protected: 46 47 SkBmpCodec(SkEncodedInfo&& info, std::unique_ptr<SkStream>, 48 uint16_t bitsPerPixel, SkCodec::SkScanlineOrder rowOrder); 49 onGetEncodedFormat()50 SkEncodedImageFormat onGetEncodedFormat() const override { return SkEncodedImageFormat::kBMP; } 51 52 /* 53 * Read enough of the stream to initialize the SkBmpCodec. 54 * On kSuccess, if codecOut is not nullptr, it will be set to a new SkBmpCodec. 55 */ 56 static Result ReadHeader(SkStream*, bool inIco, std::unique_ptr<SkCodec>* codecOut); 57 58 bool onRewind() override; 59 60 /* 61 * Returns whether this BMP is part of an ICO image. 62 */ inIco()63 bool inIco() const { 64 return this->onInIco(); 65 } 66 onInIco()67 virtual bool onInIco() const { 68 return false; 69 } 70 71 /* 72 * Get the destination row number corresponding to the encoded row number. 73 * For kTopDown, we simply return y, but for kBottomUp, the rows will be 74 * decoded in reverse order. 75 * 76 * @param y Iterates from 0 to height, indicating the current row. 77 * @param height The height of the current subset of the image that we are 78 * decoding. This is generally equal to the full height 79 * when we want to decode the full or one when we are 80 * sampling. 81 */ 82 int32_t getDstRow(int32_t y, int32_t height) const; 83 84 /* 85 * Accessors used by subclasses 86 */ bitsPerPixel()87 uint16_t bitsPerPixel() const { return fBitsPerPixel; } onGetScanlineOrder()88 SkScanlineOrder onGetScanlineOrder() const override { return fRowOrder; } srcRowBytes()89 size_t srcRowBytes() const { return fSrcRowBytes; } 90 91 /* 92 * To be overriden by bmp subclasses, which provide unique implementations. 93 * Performs subclass specific setup. 94 * 95 * @param dstInfo Contains output information. Height specifies 96 * the total number of rows that will be decoded. 97 * @param options Additonal options to pass to the decoder. 98 */ 99 virtual SkCodec::Result onPrepareToDecode(const SkImageInfo& dstInfo, 100 const SkCodec::Options& options) = 0; 101 SkCodec::Result prepareToDecode(const SkImageInfo& dstInfo, 102 const SkCodec::Options& options); 103 xformBuffer()104 uint32_t* xformBuffer() const { return fXformBuffer.get(); } resetXformBuffer(int count)105 void resetXformBuffer(int count) { fXformBuffer.reset(new uint32_t[count]); } 106 107 /* 108 * BMPs are typically encoded as BGRA/BGR so this is a more efficient choice 109 * than RGBA. 110 */ 111 inline static constexpr SkColorType kXformSrcColorType = kBGRA_8888_SkColorType; 112 inline static constexpr auto kXformSrcColorFormat = skcms_PixelFormat_BGRA_8888; 113 114 private: 115 116 /* 117 * Creates a bmp decoder 118 * Reads enough of the stream to determine the image format 119 */ 120 static std::unique_ptr<SkCodec> MakeFromStream(std::unique_ptr<SkStream>, Result*, bool inIco); 121 122 /* 123 * Decodes the next dstInfo.height() lines. 124 * 125 * onGetPixels() uses this for full image decodes. 126 * SkScaledCodec::onGetPixels() uses the scanline decoder to call this with 127 * dstInfo.height() = 1, in order to implement sampling. 128 * A potential future use is to allow the caller to decode a subset of the 129 * lines in the image. 130 * 131 * @param dstInfo Contains output information. Height specifies the 132 * number of rows to decode at this time. 133 * @param dst Memory location to store output pixels 134 * @param dstRowBytes Bytes in a row of the destination 135 * @return Number of rows successfully decoded 136 */ 137 virtual int decodeRows(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, 138 const Options& opts) = 0; 139 140 virtual bool skipRows(int count); 141 142 Result onStartScanlineDecode(const SkImageInfo& dstInfo, 143 const SkCodec::Options&) override; 144 145 int onGetScanlines(void* dst, int count, size_t rowBytes) override; 146 147 bool onSkipScanlines(int count) override; 148 149 const uint16_t fBitsPerPixel; 150 const SkScanlineOrder fRowOrder; 151 const size_t fSrcRowBytes; 152 std::unique_ptr<uint32_t[]> fXformBuffer; 153 154 using INHERITED = SkCodec; 155 }; 156 157 #endif 158