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