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 
8 #include "SkBmpCodec.h"
9 #include "SkColorTable.h"
10 #include "SkImageInfo.h"
11 #include "SkSampler.h"
12 #include "SkTypes.h"
13 
14 /*
15  * This class implements the decoding for bmp images that use an RLE encoding
16  */
17 class SkBmpRLECodec : public SkBmpCodec {
18 public:
19 
20     /*
21      * Creates an instance of the decoder
22      *
23      * Called only by SkBmpCodec::NewFromStream
24      * There should be no other callers despite this being public
25      *
26      * @param srcInfo contains the source width and height
27      * @param stream the stream of encoded image data
28      * @param bitsPerPixel the number of bits used to store each pixel
29      * @param numColors the number of colors in the color table
30      * @param bytesPerColor the number of bytes in the stream used to represent
31                             each color in the color table
32      * @param offset the offset of the image pixel data from the end of the
33      *               headers
34      * @param rowOrder indicates whether rows are ordered top-down or bottom-up
35      * @param RLEBytes indicates the amount of data left in the stream
36      *                 after decoding the headers
37      */
38     SkBmpRLECodec(const SkImageInfo& srcInfo, SkStream* stream,
39             uint16_t bitsPerPixel, uint32_t numColors, uint32_t bytesPerColor,
40             uint32_t offset, SkCodec::SkScanlineOrder rowOrder,
41             size_t RLEBytes);
42 
43     int setSampleX(int);
44 
45 protected:
46 
47     Result onGetPixels(const SkImageInfo& dstInfo, void* dst,
48                        size_t dstRowBytes, const Options&, SkPMColor*,
49                        int*, int*) override;
50 
51     SkCodec::Result prepareToDecode(const SkImageInfo& dstInfo,
52             const SkCodec::Options& options, SkPMColor inputColorPtr[],
53             int* inputColorCount) 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(int* colorCount);
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 
93     bool skipRows(int count) override;
94 
95     SkSampler* getSampler(bool createIfNecessary) override;
96 
97     SkAutoTUnref<SkColorTable>          fColorTable;    // owned
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     SkAutoTDeleteArray<uint8_t>         fStreamBuffer;
103     size_t                              fRLEBytes;
104     const size_t                        fOrigRLEBytes;
105     uint32_t                            fCurrRLEByte;
106     int                                 fSampleX;
107     SkAutoTDelete<SkSampler>            fSampler;
108 
109     // Scanline decodes allow the client to ask for a single scanline at a time.
110     // This can be tricky when the RLE encoding instructs the decoder to jump down
111     // multiple lines.  This field keeps track of lines that need to be skipped
112     // on subsequent calls to decodeRows().
113     int                                 fLinesToSkip;
114 
115     typedef SkBmpCodec INHERITED;
116 };
117