Line data Source code
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 0 : Header()
36 0 : : mDataOffset(0)
37 : , mBIHSize(0)
38 : , mWidth(0)
39 : , mHeight(0)
40 : , mBpp(0)
41 : , mCompression(0)
42 : , mImageSize(0)
43 0 : , 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 0 : 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 0 : 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 : /// Obtains the internal output image buffer.
129 0 : uint32_t* GetImageData() { return reinterpret_cast<uint32_t*>(mImageData); }
130 :
131 : /// Obtains the length of the internal output image buffer.
132 0 : size_t GetImageDataLength() const { return mImageDataLength; }
133 :
134 : /// Obtains the size of the compressed image resource.
135 : int32_t GetCompressedImageSize() const;
136 :
137 : /// Mark this BMP as being within an ICO file. Only used for testing purposes
138 : /// because the ICO-specific constructor does this marking automatically.
139 0 : void SetIsWithinICO() { mIsWithinICO = true; }
140 :
141 : /// Did the BMP file have alpha data of any kind? (Only use this after the
142 : /// bitmap has been fully decoded.)
143 0 : bool HasTransparency() const { return mDoesHaveTransparency; }
144 :
145 : LexerResult DoDecode(SourceBufferIterator& aIterator,
146 : IResumable* aOnResume) override;
147 : nsresult BeforeFinishInternal() override;
148 : nsresult FinishInternal() override;
149 :
150 : private:
151 : friend class DecoderFactory;
152 :
153 : enum class State {
154 : FILE_HEADER,
155 : INFO_HEADER_SIZE,
156 : INFO_HEADER_REST,
157 : BITFIELDS,
158 : COLOR_TABLE,
159 : GAP,
160 : AFTER_GAP,
161 : PIXEL_ROW,
162 : RLE_SEGMENT,
163 : RLE_DELTA,
164 : RLE_ABSOLUTE
165 : };
166 :
167 : // This is the constructor used for normal BMP images.
168 : explicit nsBMPDecoder(RasterImage* aImage);
169 :
170 : // This is the constructor used for BMP resources in ICO images.
171 : nsBMPDecoder(RasterImage* aImage, uint32_t aDataOffset);
172 :
173 : // Helper constructor called by the other two.
174 : nsBMPDecoder(RasterImage* aImage, State aState, size_t aLength);
175 :
176 0 : int32_t AbsoluteHeight() const { return abs(mH.mHeight); }
177 :
178 : uint32_t* RowBuffer();
179 :
180 : void FinishRow();
181 :
182 : LexerTransition<State> ReadFileHeader(const char* aData, size_t aLength);
183 : LexerTransition<State> ReadInfoHeaderSize(const char* aData, size_t aLength);
184 : LexerTransition<State> ReadInfoHeaderRest(const char* aData, size_t aLength);
185 : LexerTransition<State> ReadBitfields(const char* aData, size_t aLength);
186 : LexerTransition<State> ReadColorTable(const char* aData, size_t aLength);
187 : LexerTransition<State> SkipGap();
188 : LexerTransition<State> AfterGap();
189 : LexerTransition<State> ReadPixelRow(const char* aData);
190 : LexerTransition<State> ReadRLESegment(const char* aData);
191 : LexerTransition<State> ReadRLEDelta(const char* aData);
192 : LexerTransition<State> ReadRLEAbsolute(const char* aData, size_t aLength);
193 :
194 : StreamingLexer<State> mLexer;
195 :
196 : bmp::Header mH;
197 :
198 : // If the BMP is within an ICO file our treatment of it differs slightly.
199 : bool mIsWithinICO;
200 :
201 : bmp::BitFields mBitFields;
202 :
203 : // Might the image have transparency? Determined from the headers during
204 : // metadata decode. (Does not guarantee the image actually has transparency.)
205 : bool mMayHaveTransparency;
206 :
207 : // Does the image have transparency? Determined during full decoding, so only
208 : // use this after that has been completed.
209 : bool mDoesHaveTransparency;
210 :
211 : uint32_t mNumColors; // The number of used colors, i.e. the number of
212 : // entries in mColors, if it's present.
213 : UniquePtr<bmp::ColorTableEntry[]> mColors; // The color table, if it's present.
214 : uint32_t mBytesPerColor; // 3 or 4, depending on the format
215 :
216 : // The number of bytes prior to the optional gap that have been read. This
217 : // is used to find the start of the pixel data.
218 : uint32_t mPreGapLength;
219 :
220 : uint32_t mPixelRowSize; // The number of bytes per pixel row.
221 :
222 : int32_t mCurrentRow; // Index of the row of the image that's currently
223 : // being decoded: [height,1].
224 : int32_t mCurrentPos; // Index into the current line. Used when
225 : // doing RLE decoding and when filling in pixels
226 : // for truncated files.
227 :
228 : // Only used in RLE_ABSOLUTE state: the number of pixels to read.
229 : uint32_t mAbsoluteModeNumPixels;
230 : };
231 :
232 : } // namespace image
233 : } // namespace mozilla
234 :
235 : #endif // mozilla_image_decoders_nsBMPDecoder_h
|