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 "SkBmpCodec.h"
11 #include "SkColorTable.h"
12 #include "SkImageInfo.h"
13 #include "SkSampler.h"
14 #include "SkTypes.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(int width, int height, const 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 protected:
45 
46     Result onGetPixels(const SkImageInfo& dstInfo, void* dst,
47                        size_t dstRowBytes, const Options&,
48                        int*) override;
49 
50     SkCodec::Result onPrepareToDecode(const SkImageInfo& dstInfo,
51             const SkCodec::Options& options) override;
52 
53 private:
54 
55     /*
56      * Creates the color table
57      * Sets colorCount to the new color count if it is non-nullptr
58      */
59     bool createColorTable(SkColorType dstColorType);
60 
61     bool initializeStreamBuffer();
62 
63     /*
64      * Before signalling kIncompleteInput, we should attempt to load the
65      * stream buffer with additional data.
66      *
67      * @return the number of bytes remaining in the stream buffer after
68      *         attempting to read more bytes from the stream
69      */
70     size_t checkForMoreData();
71 
72     /*
73      * Set an RLE pixel using the color table
74      */
75     void setPixel(void* dst, size_t dstRowBytes,
76                   const SkImageInfo& dstInfo, uint32_t x, uint32_t y,
77                   uint8_t index);
78     /*
79      * Set an RLE24 pixel from R, G, B values
80      */
81     void setRGBPixel(void* dst, size_t dstRowBytes,
82                      const SkImageInfo& dstInfo, uint32_t x, uint32_t y,
83                      uint8_t red, uint8_t green, uint8_t blue);
84 
85     /*
86      * If dst is NULL, this is a signal to skip the rows.
87      */
88     int decodeRows(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes,
89             const Options& opts) override;
90     int decodeRLE(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes);
91 
92     bool skipRows(int count) override;
93 
94     SkSampler* getSampler(bool createIfNecessary) override;
95 
96     sk_sp<SkColorTable>        fColorTable;
97     // fNumColors is the number specified in the header, or 0 if not present in the header.
98     const uint32_t             fNumColors;
99     const uint32_t             fBytesPerColor;
100     const uint32_t             fOffset;
101 
102     static constexpr size_t    kBufferSize = 4096;
103     uint8_t                    fStreamBuffer[kBufferSize];
104     size_t                     fBytesBuffered;
105 
106     uint32_t                   fCurrRLEByte;
107     int                        fSampleX;
108     std::unique_ptr<SkSampler> fSampler;
109 
110     // Scanline decodes allow the client to ask for a single scanline at a time.
111     // This can be tricky when the RLE encoding instructs the decoder to jump down
112     // multiple lines.  This field keeps track of lines that need to be skipped
113     // on subsequent calls to decodeRows().
114     int                        fLinesToSkip;
115 
116     typedef SkBmpCodec INHERITED;
117 };
118 #endif  // SkBmpRLECodec_DEFINED
119