/src/mozilla-central/image/decoders/nsBMPDecoder.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #ifndef mozilla_image_decoders_nsBMPDecoder_h |
8 | | #define mozilla_image_decoders_nsBMPDecoder_h |
9 | | |
10 | | #include "BMPHeaders.h" |
11 | | #include "Decoder.h" |
12 | | #include "gfxColor.h" |
13 | | #include "StreamingLexer.h" |
14 | | #include "mozilla/UniquePtr.h" |
15 | | |
16 | | namespace mozilla { |
17 | | namespace image { |
18 | | |
19 | | namespace bmp { |
20 | | |
21 | | /// This struct contains the fields from the file header and info header that |
22 | | /// we use during decoding. (Excluding bitfields fields, which are kept in |
23 | | /// BitFields.) |
24 | | struct Header { |
25 | | uint32_t mDataOffset; // Offset to raster data. |
26 | | uint32_t mBIHSize; // Header size. |
27 | | int32_t mWidth; // Image width. |
28 | | int32_t mHeight; // Image height. |
29 | | uint16_t mBpp; // Bits per pixel. |
30 | | uint32_t mCompression; // See struct Compression for valid values. |
31 | | uint32_t mImageSize; // (compressed) image size. Can be 0 if |
32 | | // mCompression==0. |
33 | | uint32_t mNumColors; // Used colors. |
34 | | |
35 | | Header() |
36 | | : mDataOffset(0) |
37 | | , mBIHSize(0) |
38 | | , mWidth(0) |
39 | | , mHeight(0) |
40 | | , mBpp(0) |
41 | | , mCompression(0) |
42 | | , mImageSize(0) |
43 | | , mNumColors(0) |
44 | 0 | {} |
45 | | }; |
46 | | |
47 | | /// An entry in the color table. |
48 | | struct ColorTableEntry { |
49 | | uint8_t mRed; |
50 | | uint8_t mGreen; |
51 | | uint8_t mBlue; |
52 | | }; |
53 | | |
54 | | /// All the color-related bitfields for 16bpp and 32bpp images. We use this |
55 | | /// even for older format BMPs that don't have explicit bitfields. |
56 | | class BitFields { |
57 | | class Value { |
58 | | friend class BitFields; |
59 | | |
60 | | uint32_t mMask; // The mask for the value. |
61 | | uint8_t mRightShift; // The amount to right-shift after masking. |
62 | | uint8_t mBitWidth; // The width (in bits) of the value. |
63 | | |
64 | | /// Sets the mask (and thus the right-shift and bit-width as well). |
65 | | void Set(uint32_t aMask); |
66 | | |
67 | | public: |
68 | | Value() |
69 | 0 | { |
70 | 0 | mMask = 0; |
71 | 0 | mRightShift = 0; |
72 | 0 | mBitWidth = 0; |
73 | 0 | } |
74 | | |
75 | | /// Returns true if this channel is used. Only used for alpha. |
76 | 0 | bool IsPresent() const { return mMask != 0x0; } |
77 | | |
78 | | /// Extracts the single color value from the multi-color value. |
79 | | uint8_t Get(uint32_t aVal) const; |
80 | | |
81 | | /// Like Get(), but specially for alpha. |
82 | | uint8_t GetAlpha(uint32_t aVal, bool& aHasAlphaOut) const; |
83 | | |
84 | | /// Specialized versions of Get() for when the bit-width is 5 or 8. |
85 | | /// (They will assert if called and the bit-width is not 5 or 8.) |
86 | | uint8_t Get5(uint32_t aVal) const; |
87 | | uint8_t Get8(uint32_t aVal) const; |
88 | | }; |
89 | | |
90 | | public: |
91 | | /// The individual color channels. |
92 | | Value mRed; |
93 | | Value mGreen; |
94 | | Value mBlue; |
95 | | Value mAlpha; |
96 | | |
97 | | /// Set bitfields to the standard 5-5-5 16bpp values. |
98 | | void SetR5G5B5(); |
99 | | |
100 | | /// Set bitfields to the standard 8-8-8 32bpp values. |
101 | | void SetR8G8B8(); |
102 | | |
103 | | /// Test if bitfields have the standard 5-5-5 16bpp values. |
104 | | bool IsR5G5B5() const; |
105 | | |
106 | | /// Test if bitfields have the standard 8-8-8 32bpp values. |
107 | | bool IsR8G8B8() const; |
108 | | |
109 | | /// Read the bitfields from a header. The reading of the alpha mask is |
110 | | /// optional. |
111 | | void ReadFromHeader(const char* aData, bool aReadAlpha); |
112 | | |
113 | | /// Length of the bitfields structure in the BMP file. |
114 | | static const size_t LENGTH = 12; |
115 | | }; |
116 | | |
117 | | } // namespace bmp |
118 | | |
119 | | class RasterImage; |
120 | | |
121 | | /// Decoder for BMP-Files, as used by Windows and OS/2. |
122 | | |
123 | | class nsBMPDecoder : public Decoder |
124 | | { |
125 | | public: |
126 | | ~nsBMPDecoder(); |
127 | | |
128 | 0 | DecoderType GetType() const override { return DecoderType::BMP; } |
129 | | |
130 | | /// @return true if this BMP is a valid ICO resource. |
131 | 0 | bool IsValidICOResource() const override { return true; } |
132 | | |
133 | | /// Obtains the internal output image buffer. |
134 | 0 | uint32_t* GetImageData() { return reinterpret_cast<uint32_t*>(mImageData); } |
135 | | |
136 | | /// Obtains the length of the internal output image buffer. |
137 | 0 | size_t GetImageDataLength() const { return mImageDataLength; } |
138 | | |
139 | | /// Obtains the size of the compressed image resource. |
140 | | int32_t GetCompressedImageSize() const; |
141 | | |
142 | | /// Mark this BMP as being within an ICO file. Only used for testing purposes |
143 | | /// because the ICO-specific constructor does this marking automatically. |
144 | 0 | void SetIsWithinICO() { mIsWithinICO = true; } |
145 | | |
146 | | /// Did the BMP file have alpha data of any kind? (Only use this after the |
147 | | /// bitmap has been fully decoded.) |
148 | 0 | bool HasTransparency() const { return mDoesHaveTransparency; } |
149 | | |
150 | | LexerResult DoDecode(SourceBufferIterator& aIterator, |
151 | | IResumable* aOnResume) override; |
152 | | nsresult BeforeFinishInternal() override; |
153 | | nsresult FinishInternal() override; |
154 | | |
155 | | private: |
156 | | friend class DecoderFactory; |
157 | | |
158 | | enum class State { |
159 | | FILE_HEADER, |
160 | | INFO_HEADER_SIZE, |
161 | | INFO_HEADER_REST, |
162 | | BITFIELDS, |
163 | | COLOR_TABLE, |
164 | | GAP, |
165 | | AFTER_GAP, |
166 | | PIXEL_ROW, |
167 | | RLE_SEGMENT, |
168 | | RLE_DELTA, |
169 | | RLE_ABSOLUTE |
170 | | }; |
171 | | |
172 | | // This is the constructor used for normal BMP images. |
173 | | explicit nsBMPDecoder(RasterImage* aImage); |
174 | | |
175 | | // This is the constructor used for BMP resources in ICO images. |
176 | | nsBMPDecoder(RasterImage* aImage, uint32_t aDataOffset); |
177 | | |
178 | | // Helper constructor called by the other two. |
179 | | nsBMPDecoder(RasterImage* aImage, State aState, size_t aLength); |
180 | | |
181 | 0 | int32_t AbsoluteHeight() const { return abs(mH.mHeight); } |
182 | | |
183 | | uint32_t* RowBuffer(); |
184 | | |
185 | | void FinishRow(); |
186 | | |
187 | | LexerTransition<State> ReadFileHeader(const char* aData, size_t aLength); |
188 | | LexerTransition<State> ReadInfoHeaderSize(const char* aData, size_t aLength); |
189 | | LexerTransition<State> ReadInfoHeaderRest(const char* aData, size_t aLength); |
190 | | LexerTransition<State> ReadBitfields(const char* aData, size_t aLength); |
191 | | LexerTransition<State> ReadColorTable(const char* aData, size_t aLength); |
192 | | LexerTransition<State> SkipGap(); |
193 | | LexerTransition<State> AfterGap(); |
194 | | LexerTransition<State> ReadPixelRow(const char* aData); |
195 | | LexerTransition<State> ReadRLESegment(const char* aData); |
196 | | LexerTransition<State> ReadRLEDelta(const char* aData); |
197 | | LexerTransition<State> ReadRLEAbsolute(const char* aData, size_t aLength); |
198 | | |
199 | | StreamingLexer<State> mLexer; |
200 | | |
201 | | bmp::Header mH; |
202 | | |
203 | | // If the BMP is within an ICO file our treatment of it differs slightly. |
204 | | bool mIsWithinICO; |
205 | | |
206 | | bmp::BitFields mBitFields; |
207 | | |
208 | | // Might the image have transparency? Determined from the headers during |
209 | | // metadata decode. (Does not guarantee the image actually has transparency.) |
210 | | bool mMayHaveTransparency; |
211 | | |
212 | | // Does the image have transparency? Determined during full decoding, so only |
213 | | // use this after that has been completed. |
214 | | bool mDoesHaveTransparency; |
215 | | |
216 | | uint32_t mNumColors; // The number of used colors, i.e. the number of |
217 | | // entries in mColors, if it's present. |
218 | | UniquePtr<bmp::ColorTableEntry[]> mColors; // The color table, if it's present. |
219 | | uint32_t mBytesPerColor; // 3 or 4, depending on the format |
220 | | |
221 | | // The number of bytes prior to the optional gap that have been read. This |
222 | | // is used to find the start of the pixel data. |
223 | | uint32_t mPreGapLength; |
224 | | |
225 | | uint32_t mPixelRowSize; // The number of bytes per pixel row. |
226 | | |
227 | | int32_t mCurrentRow; // Index of the row of the image that's currently |
228 | | // being decoded: [height,1]. |
229 | | int32_t mCurrentPos; // Index into the current line. Used when |
230 | | // doing RLE decoding and when filling in pixels |
231 | | // for truncated files. |
232 | | |
233 | | // Only used in RLE_ABSOLUTE state: the number of pixels to read. |
234 | | uint32_t mAbsoluteModeNumPixels; |
235 | | }; |
236 | | |
237 | | } // namespace image |
238 | | } // namespace mozilla |
239 | | |
240 | | #endif // mozilla_image_decoders_nsBMPDecoder_h |