/* * Copyright 2015 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef SkBmpRLECodec_DEFINED #define SkBmpRLECodec_DEFINED #include "SkBmpCodec.h" #include "SkColorTable.h" #include "SkImageInfo.h" #include "SkSampler.h" #include "SkTypes.h" /* * This class implements the decoding for bmp images that use an RLE encoding */ class SkBmpRLECodec : public SkBmpCodec { public: /* * Creates an instance of the decoder * * Called only by SkBmpCodec::MakeFromStream * There should be no other callers despite this being public * * @param info contains properties of the encoded data * @param stream the stream of encoded image data * @param bitsPerPixel the number of bits used to store each pixel * @param numColors the number of colors in the color table * @param bytesPerColor the number of bytes in the stream used to represent each color in the color table * @param offset the offset of the image pixel data from the end of the * headers * @param rowOrder indicates whether rows are ordered top-down or bottom-up */ SkBmpRLECodec(int width, int height, const SkEncodedInfo& info, std::unique_ptr<SkStream>, uint16_t bitsPerPixel, uint32_t numColors, uint32_t bytesPerColor, uint32_t offset, SkCodec::SkScanlineOrder rowOrder); int setSampleX(int); protected: Result onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, const Options&, int*) override; SkCodec::Result onPrepareToDecode(const SkImageInfo& dstInfo, const SkCodec::Options& options) override; private: /* * Creates the color table * Sets colorCount to the new color count if it is non-nullptr */ bool createColorTable(SkColorType dstColorType); bool initializeStreamBuffer(); /* * Before signalling kIncompleteInput, we should attempt to load the * stream buffer with additional data. * * @return the number of bytes remaining in the stream buffer after * attempting to read more bytes from the stream */ size_t checkForMoreData(); /* * Set an RLE pixel using the color table */ void setPixel(void* dst, size_t dstRowBytes, const SkImageInfo& dstInfo, uint32_t x, uint32_t y, uint8_t index); /* * Set an RLE24 pixel from R, G, B values */ void setRGBPixel(void* dst, size_t dstRowBytes, const SkImageInfo& dstInfo, uint32_t x, uint32_t y, uint8_t red, uint8_t green, uint8_t blue); /* * If dst is NULL, this is a signal to skip the rows. */ int decodeRows(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, const Options& opts) override; int decodeRLE(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes); bool skipRows(int count) override; SkSampler* getSampler(bool createIfNecessary) override; sk_sp<SkColorTable> fColorTable; // fNumColors is the number specified in the header, or 0 if not present in the header. const uint32_t fNumColors; const uint32_t fBytesPerColor; const uint32_t fOffset; static constexpr size_t kBufferSize = 4096; uint8_t fStreamBuffer[kBufferSize]; size_t fBytesBuffered; uint32_t fCurrRLEByte; int fSampleX; std::unique_ptr<SkSampler> fSampler; // Scanline decodes allow the client to ask for a single scanline at a time. // This can be tricky when the RLE encoding instructs the decoder to jump down // multiple lines. This field keeps track of lines that need to be skipped // on subsequent calls to decodeRows(). int fLinesToSkip; typedef SkBmpCodec INHERITED; }; #endif // SkBmpRLECodec_DEFINED