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/core/SkColorSpace.h" 12 #include "include/core/SkImageInfo.h" 13 #include "include/core/SkStream.h" 14 #include "include/core/SkTypes.h" 15 #include "src/codec/SkColorTable.h" 16 #include "src/codec/SkSwizzler.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 std::unique_ptr<SkCodec> MakeFromStream(std::unique_ptr<SkStream>, Result*); 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 std::unique_ptr<SkCodec> MakeFromIco(std::unique_ptr<SkStream>, Result*); 38 39 protected: 40 41 SkBmpCodec(SkEncodedInfo&& info, std::unique_ptr<SkStream>, 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. 48 * On kSuccess, if codecOut is not nullptr, it will be set to a new SkBmpCodec. 49 */ 50 static Result ReadHeader(SkStream*, bool inIco, std::unique_ptr<SkCodec>* codecOut); 51 52 bool onRewind() override; 53 54 /* 55 * Returns whether this BMP is part of an ICO image. 56 */ inIco()57 bool inIco() const { 58 return this->onInIco(); 59 } 60 onInIco()61 virtual bool onInIco() const { 62 return false; 63 } 64 65 /* 66 * Get the destination row number corresponding to the encoded row number. 67 * For kTopDown, we simply return y, but for kBottomUp, the rows will be 68 * decoded in reverse order. 69 * 70 * @param y Iterates from 0 to height, indicating the current row. 71 * @param height The height of the current subset of the image that we are 72 * decoding. This is generally equal to the full height 73 * when we want to decode the full or one when we are 74 * sampling. 75 */ 76 int32_t getDstRow(int32_t y, int32_t height) const; 77 78 /* 79 * Accessors used by subclasses 80 */ bitsPerPixel()81 uint16_t bitsPerPixel() const { return fBitsPerPixel; } onGetScanlineOrder()82 SkScanlineOrder onGetScanlineOrder() const override { return fRowOrder; } srcRowBytes()83 size_t srcRowBytes() const { return fSrcRowBytes; } 84 85 /* 86 * To be overriden by bmp subclasses, which provide unique implementations. 87 * Performs subclass specific setup. 88 * 89 * @param dstInfo Contains output information. Height specifies 90 * the total number of rows that will be decoded. 91 * @param options Additonal options to pass to the decoder. 92 */ 93 virtual SkCodec::Result onPrepareToDecode(const SkImageInfo& dstInfo, 94 const SkCodec::Options& options) = 0; 95 SkCodec::Result prepareToDecode(const SkImageInfo& dstInfo, 96 const SkCodec::Options& options); 97 xformBuffer()98 uint32_t* xformBuffer() const { return fXformBuffer.get(); } resetXformBuffer(int count)99 void resetXformBuffer(int count) { fXformBuffer.reset(new uint32_t[count]); } 100 101 /* 102 * BMPs are typically encoded as BGRA/BGR so this is a more efficient choice 103 * than RGBA. 104 */ 105 inline static constexpr SkColorType kXformSrcColorType = kBGRA_8888_SkColorType; 106 inline static constexpr auto kXformSrcColorFormat = skcms_PixelFormat_BGRA_8888; 107 108 private: 109 110 /* 111 * Creates a bmp decoder 112 * Reads enough of the stream to determine the image format 113 */ 114 static std::unique_ptr<SkCodec> MakeFromStream(std::unique_ptr<SkStream>, Result*, bool inIco); 115 116 /* 117 * Decodes the next dstInfo.height() lines. 118 * 119 * onGetPixels() uses this for full image decodes. 120 * SkScaledCodec::onGetPixels() uses the scanline decoder to call this with 121 * dstInfo.height() = 1, in order to implement sampling. 122 * A potential future use is to allow the caller to decode a subset of the 123 * lines in the image. 124 * 125 * @param dstInfo Contains output information. Height specifies the 126 * number of rows to decode at this time. 127 * @param dst Memory location to store output pixels 128 * @param dstRowBytes Bytes in a row of the destination 129 * @return Number of rows successfully decoded 130 */ 131 virtual int decodeRows(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, 132 const Options& opts) = 0; 133 134 virtual bool skipRows(int count); 135 136 Result onStartScanlineDecode(const SkImageInfo& dstInfo, 137 const SkCodec::Options&) override; 138 139 int onGetScanlines(void* dst, int count, size_t rowBytes) override; 140 141 bool onSkipScanlines(int count) override; 142 143 const uint16_t fBitsPerPixel; 144 const SkScanlineOrder fRowOrder; 145 const size_t fSrcRowBytes; 146 std::unique_ptr<uint32_t[]> fXformBuffer; 147 148 using INHERITED = SkCodec; 149 }; 150 151 #endif 152