1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2015 Google Inc. 3*c8dee2aaSAndroid Build Coastguard Worker * 4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be 5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file. 6*c8dee2aaSAndroid Build Coastguard Worker */ 7*c8dee2aaSAndroid Build Coastguard Worker #ifndef SkBmpRLECodec_DEFINED 8*c8dee2aaSAndroid Build Coastguard Worker #define SkBmpRLECodec_DEFINED 9*c8dee2aaSAndroid Build Coastguard Worker 10*c8dee2aaSAndroid Build Coastguard Worker #include "include/codec/SkCodec.h" 11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h" 12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h" 13*c8dee2aaSAndroid Build Coastguard Worker #include "src/codec/SkBmpCodec.h" 14*c8dee2aaSAndroid Build Coastguard Worker #include "src/codec/SkColorPalette.h" 15*c8dee2aaSAndroid Build Coastguard Worker #include "src/codec/SkSampler.h" 16*c8dee2aaSAndroid Build Coastguard Worker 17*c8dee2aaSAndroid Build Coastguard Worker #include <cstddef> 18*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint> 19*c8dee2aaSAndroid Build Coastguard Worker #include <memory> 20*c8dee2aaSAndroid Build Coastguard Worker 21*c8dee2aaSAndroid Build Coastguard Worker class SkStream; 22*c8dee2aaSAndroid Build Coastguard Worker enum SkColorType : int; 23*c8dee2aaSAndroid Build Coastguard Worker struct SkEncodedInfo; 24*c8dee2aaSAndroid Build Coastguard Worker struct SkImageInfo; 25*c8dee2aaSAndroid Build Coastguard Worker 26*c8dee2aaSAndroid Build Coastguard Worker /* 27*c8dee2aaSAndroid Build Coastguard Worker * This class implements the decoding for bmp images that use an RLE encoding 28*c8dee2aaSAndroid Build Coastguard Worker */ 29*c8dee2aaSAndroid Build Coastguard Worker class SkBmpRLECodec : public SkBmpCodec { 30*c8dee2aaSAndroid Build Coastguard Worker public: 31*c8dee2aaSAndroid Build Coastguard Worker 32*c8dee2aaSAndroid Build Coastguard Worker /* 33*c8dee2aaSAndroid Build Coastguard Worker * Creates an instance of the decoder 34*c8dee2aaSAndroid Build Coastguard Worker * 35*c8dee2aaSAndroid Build Coastguard Worker * Called only by SkBmpCodec::MakeFromStream 36*c8dee2aaSAndroid Build Coastguard Worker * There should be no other callers despite this being public 37*c8dee2aaSAndroid Build Coastguard Worker * 38*c8dee2aaSAndroid Build Coastguard Worker * @param info contains properties of the encoded data 39*c8dee2aaSAndroid Build Coastguard Worker * @param stream the stream of encoded image data 40*c8dee2aaSAndroid Build Coastguard Worker * @param bitsPerPixel the number of bits used to store each pixel 41*c8dee2aaSAndroid Build Coastguard Worker * @param numColors the number of colors in the color table 42*c8dee2aaSAndroid Build Coastguard Worker * @param bytesPerColor the number of bytes in the stream used to represent 43*c8dee2aaSAndroid Build Coastguard Worker each color in the color table 44*c8dee2aaSAndroid Build Coastguard Worker * @param offset the offset of the image pixel data from the end of the 45*c8dee2aaSAndroid Build Coastguard Worker * headers 46*c8dee2aaSAndroid Build Coastguard Worker * @param rowOrder indicates whether rows are ordered top-down or bottom-up 47*c8dee2aaSAndroid Build Coastguard Worker */ 48*c8dee2aaSAndroid Build Coastguard Worker SkBmpRLECodec(SkEncodedInfo&& info, std::unique_ptr<SkStream>, 49*c8dee2aaSAndroid Build Coastguard Worker uint16_t bitsPerPixel, uint32_t numColors, uint32_t bytesPerColor, 50*c8dee2aaSAndroid Build Coastguard Worker uint32_t offset, SkCodec::SkScanlineOrder rowOrder); 51*c8dee2aaSAndroid Build Coastguard Worker 52*c8dee2aaSAndroid Build Coastguard Worker int setSampleX(int); 53*c8dee2aaSAndroid Build Coastguard Worker 54*c8dee2aaSAndroid Build Coastguard Worker int fillWidth() const; 55*c8dee2aaSAndroid Build Coastguard Worker 56*c8dee2aaSAndroid Build Coastguard Worker protected: 57*c8dee2aaSAndroid Build Coastguard Worker 58*c8dee2aaSAndroid Build Coastguard Worker Result onGetPixels(const SkImageInfo& dstInfo, void* dst, 59*c8dee2aaSAndroid Build Coastguard Worker size_t dstRowBytes, const Options&, 60*c8dee2aaSAndroid Build Coastguard Worker int*) override; 61*c8dee2aaSAndroid Build Coastguard Worker 62*c8dee2aaSAndroid Build Coastguard Worker SkCodec::Result onPrepareToDecode(const SkImageInfo& dstInfo, 63*c8dee2aaSAndroid Build Coastguard Worker const SkCodec::Options& options) override; 64*c8dee2aaSAndroid Build Coastguard Worker 65*c8dee2aaSAndroid Build Coastguard Worker private: 66*c8dee2aaSAndroid Build Coastguard Worker 67*c8dee2aaSAndroid Build Coastguard Worker /* 68*c8dee2aaSAndroid Build Coastguard Worker * Creates the color table 69*c8dee2aaSAndroid Build Coastguard Worker * Sets colorCount to the new color count if it is non-nullptr 70*c8dee2aaSAndroid Build Coastguard Worker */ 71*c8dee2aaSAndroid Build Coastguard Worker bool createColorTable(SkColorType dstColorType); 72*c8dee2aaSAndroid Build Coastguard Worker 73*c8dee2aaSAndroid Build Coastguard Worker bool initializeStreamBuffer(); 74*c8dee2aaSAndroid Build Coastguard Worker 75*c8dee2aaSAndroid Build Coastguard Worker /* 76*c8dee2aaSAndroid Build Coastguard Worker * Before signalling kIncompleteInput, we should attempt to load the 77*c8dee2aaSAndroid Build Coastguard Worker * stream buffer with additional data. 78*c8dee2aaSAndroid Build Coastguard Worker * 79*c8dee2aaSAndroid Build Coastguard Worker * @return the number of bytes remaining in the stream buffer after 80*c8dee2aaSAndroid Build Coastguard Worker * attempting to read more bytes from the stream 81*c8dee2aaSAndroid Build Coastguard Worker */ 82*c8dee2aaSAndroid Build Coastguard Worker size_t checkForMoreData(); 83*c8dee2aaSAndroid Build Coastguard Worker 84*c8dee2aaSAndroid Build Coastguard Worker /* 85*c8dee2aaSAndroid Build Coastguard Worker * Set an RLE pixel using the color table 86*c8dee2aaSAndroid Build Coastguard Worker */ 87*c8dee2aaSAndroid Build Coastguard Worker void setPixel(void* dst, size_t dstRowBytes, 88*c8dee2aaSAndroid Build Coastguard Worker const SkImageInfo& dstInfo, uint32_t x, uint32_t y, 89*c8dee2aaSAndroid Build Coastguard Worker uint8_t index); 90*c8dee2aaSAndroid Build Coastguard Worker /* 91*c8dee2aaSAndroid Build Coastguard Worker * Set an RLE24 pixel from R, G, B values 92*c8dee2aaSAndroid Build Coastguard Worker */ 93*c8dee2aaSAndroid Build Coastguard Worker void setRGBPixel(void* dst, size_t dstRowBytes, 94*c8dee2aaSAndroid Build Coastguard Worker const SkImageInfo& dstInfo, uint32_t x, uint32_t y, 95*c8dee2aaSAndroid Build Coastguard Worker uint8_t red, uint8_t green, uint8_t blue); 96*c8dee2aaSAndroid Build Coastguard Worker 97*c8dee2aaSAndroid Build Coastguard Worker /* 98*c8dee2aaSAndroid Build Coastguard Worker * If dst is NULL, this is a signal to skip the rows. 99*c8dee2aaSAndroid Build Coastguard Worker */ 100*c8dee2aaSAndroid Build Coastguard Worker int decodeRows(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, 101*c8dee2aaSAndroid Build Coastguard Worker const Options& opts) override; 102*c8dee2aaSAndroid Build Coastguard Worker int decodeRLE(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes); 103*c8dee2aaSAndroid Build Coastguard Worker 104*c8dee2aaSAndroid Build Coastguard Worker bool skipRows(int count) override; 105*c8dee2aaSAndroid Build Coastguard Worker 106*c8dee2aaSAndroid Build Coastguard Worker SkSampler* getSampler(bool createIfNecessary) override; 107*c8dee2aaSAndroid Build Coastguard Worker 108*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkColorPalette> fColorTable; 109*c8dee2aaSAndroid Build Coastguard Worker // fNumColors is the number specified in the header, or 0 if not present in the header. 110*c8dee2aaSAndroid Build Coastguard Worker const uint32_t fNumColors; 111*c8dee2aaSAndroid Build Coastguard Worker const uint32_t fBytesPerColor; 112*c8dee2aaSAndroid Build Coastguard Worker const uint32_t fOffset; 113*c8dee2aaSAndroid Build Coastguard Worker 114*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr size_t kBufferSize = 4096; 115*c8dee2aaSAndroid Build Coastguard Worker uint8_t fStreamBuffer[kBufferSize]; 116*c8dee2aaSAndroid Build Coastguard Worker size_t fBytesBuffered; 117*c8dee2aaSAndroid Build Coastguard Worker 118*c8dee2aaSAndroid Build Coastguard Worker uint32_t fCurrRLEByte; 119*c8dee2aaSAndroid Build Coastguard Worker int fSampleX; 120*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<SkSampler> fSampler; 121*c8dee2aaSAndroid Build Coastguard Worker 122*c8dee2aaSAndroid Build Coastguard Worker // Scanline decodes allow the client to ask for a single scanline at a time. 123*c8dee2aaSAndroid Build Coastguard Worker // This can be tricky when the RLE encoding instructs the decoder to jump down 124*c8dee2aaSAndroid Build Coastguard Worker // multiple lines. This field keeps track of lines that need to be skipped 125*c8dee2aaSAndroid Build Coastguard Worker // on subsequent calls to decodeRows(). 126*c8dee2aaSAndroid Build Coastguard Worker int fLinesToSkip; 127*c8dee2aaSAndroid Build Coastguard Worker 128*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = SkBmpCodec; 129*c8dee2aaSAndroid Build Coastguard Worker }; 130*c8dee2aaSAndroid Build Coastguard Worker #endif // SkBmpRLECodec_DEFINED 131