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 "SkCodec.h"
9 #include "SkColorTable.h"
10 #include "SkImageInfo.h"
11 #include "SkMaskSwizzler.h"
12 #include "SkStream.h"
13 #include "SkSwizzler.h"
14 #include "SkTypes.h"
15 
16 // TODO: rename SkCodec_libbmp files to SkBmpCodec
17 /*
18  *
19  * This class implements the decoding for bmp images
20  *
21  */
22 class SkBmpCodec : public SkCodec {
23 public:
24 
25     /*
26      *
27      * Describes if rows of the input start at the top or bottom of the image
28      *
29      */
30     enum RowOrder {
31         kTopDown_RowOrder,
32         kBottomUp_RowOrder
33     };
34 
35     /*
36      *
37      * Checks the start of the stream to see if the image is a bmp
38      *
39      */
40     static bool IsBmp(SkStream*);
41 
42     /*
43      *
44      * Assumes IsBmp was called and returned true
45      * Creates a bmp decoder
46      * Reads enough of the stream to determine the image format
47      *
48      */
49     static SkCodec* NewFromStream(SkStream*);
50 
51     /*
52      *
53      * Creates a bmp decoder for a bmp embedded in ico
54      * Reads enough of the stream to determine the image format
55      *
56      */
57     static SkCodec* NewFromIco(SkStream*);
58 
59 protected:
60 
61     /*
62      *
63      * Initiates the bmp decode
64      *
65      */
66     Result onGetPixels(const SkImageInfo& dstInfo, void* dst,
67                        size_t dstRowBytes, const Options&, SkPMColor*,
68                        int*) override;
69 
onGetEncodedFormat()70     SkEncodedFormat onGetEncodedFormat() const override { return kBMP_SkEncodedFormat; }
71 
72 private:
73 
74     /*
75      *
76      * Used to define the input format of the bmp
77      *
78      */
79     enum BitmapInputFormat {
80         kStandard_BitmapInputFormat,
81         kRLE_BitmapInputFormat,
82         kBitMask_BitmapInputFormat,
83         kUnknown_BitmapInputFormat
84     };
85 
86     /*
87      *
88      * Creates the color table
89      * Sets colorCount to the new color count if it is non-NULL
90      */
91      bool createColorTable(SkAlphaType alphaType, int* colorCount);
92 
93     /*
94      *
95      * Creates a bmp decoder
96      * Reads enough of the stream to determine the image format
97      *
98      */
99     static SkCodec* NewFromStream(SkStream*, bool isIco);
100 
101     /*
102      *
103      * Read enough of the stream to initialize the SkBmpCodec. Returns a bool
104      * representing success or failure. If it returned true, and codecOut was
105      * not NULL, it will be set to a new SkBmpCodec.
106      * Does *not* take ownership of the passed in SkStream.
107      *
108      */
109     static bool ReadHeader(SkStream*, bool isIco, SkCodec** codecOut);
110 
111     /*
112      *
113      * Performs the bitmap decoding for bit masks input format
114      *
115      */
116     Result decodeMask(const SkImageInfo& dstInfo, void* dst,
117                       size_t dstRowBytes, const Options& opts);
118 
119     /*
120      *
121      * Set an RLE pixel using the color table
122      *
123      */
124     void setRLEPixel(void* dst, size_t dstRowBytes,
125                      const SkImageInfo& dstInfo, uint32_t x, uint32_t y,
126                      uint8_t index);
127     /*
128      *
129      * Set an RLE24 pixel from R, G, B values
130      *
131      */
132     void setRLE24Pixel(void* dst, size_t dstRowBytes,
133                        const SkImageInfo& dstInfo, uint32_t x, uint32_t y,
134                        uint8_t red, uint8_t green, uint8_t blue);
135 
136     /*
137      *
138      * Performs the bitmap decoding for RLE input format
139      *
140      */
141     Result decodeRLE(const SkImageInfo& dstInfo, void* dst,
142                      size_t dstRowBytes, const Options& opts);
143 
144     /*
145      *
146      * Performs the bitmap decoding for standard input format
147      *
148      */
149     Result decode(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, const Options& opts);
150 
151     /*
152      *
153      * Creates an instance of the decoder
154      * Called only by NewFromStream
155      *
156      * @param srcInfo contains the source width and height
157      * @param stream the stream of image data
158      * @param bitsPerPixel the number of bits used to store each pixel
159      * @param format the format of the bmp file
160      * @param masks optional color masks for certain bmp formats, passes
161                     ownership to SkBmpCodec
162      * @param numColors the number of colors in the color table
163      * @param bytesPerColor the number of bytes in the stream used to represent
164                             each color in the color table
165      * @param offset the offset of the image pixel data from the end of the
166      *               headers
167      * @param rowOrder indicates whether rows are ordered top-down or bottom-up
168      * @param RLEBytes used only for RLE decodes, as we must decode all
169      *                  of the data at once rather than row by row
170      *                  it indicates the amount of data left in the stream
171      *                  after decoding the headers
172      *
173      */
174     SkBmpCodec(const SkImageInfo& srcInfo, SkStream* stream,
175                uint16_t bitsPerPixel, BitmapInputFormat format,
176                SkMasks* masks, uint32_t numColors, uint32_t bytesPerColor,
177                uint32_t offset, RowOrder rowOrder, size_t RLEBytes,
178                bool isIco);
179 
180     // Fields
181     const uint16_t                      fBitsPerPixel;
182     const BitmapInputFormat             fInputFormat;
183     SkAutoTDelete<SkMasks>              fMasks;          // owned
184     SkAutoTUnref<SkColorTable>          fColorTable;     // owned
185     uint32_t                            fNumColors;
186     const uint32_t                      fBytesPerColor;
187     const uint32_t                      fOffset;
188     const RowOrder                      fRowOrder;
189     const size_t                        fRLEBytes;
190     const bool                          fIsIco;
191 
192     typedef SkCodec INHERITED;
193 };
194