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