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