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