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