1 | /* |
2 | * Copyright (c) 2008, 2009, Google Inc. All rights reserved. |
3 | * |
4 | * Redistribution and use in source and binary forms, with or without |
5 | * modification, are permitted provided that the following conditions are |
6 | * met: |
7 | * |
8 | * * Redistributions of source code must retain the above copyright |
9 | * notice, this list of conditions and the following disclaimer. |
10 | * * Redistributions in binary form must reproduce the above |
11 | * copyright notice, this list of conditions and the following disclaimer |
12 | * in the documentation and/or other materials provided with the |
13 | * distribution. |
14 | * * Neither the name of Google Inc. nor the names of its |
15 | * contributors may be used to endorse or promote products derived from |
16 | * this software without specific prior written permission. |
17 | * |
18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
19 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
20 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
21 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
22 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
23 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
24 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
28 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 | */ |
30 | |
31 | #pragma once |
32 | |
33 | #include "ScalableImageDecoder.h" |
34 | #include <stdint.h> |
35 | |
36 | namespace WebCore { |
37 | |
38 | // This class decodes a BMP image. It is used in the BMP and ICO decoders, |
39 | // which wrap it in the appropriate code to read file headers, etc. |
40 | class BMPImageReader { |
41 | WTF_MAKE_FAST_ALLOCATED; |
42 | public: |
43 | // Read a value from |data[offset]|, converting from little to native |
44 | // endianness. |
45 | static inline uint16_t readUint16(SharedBuffer* data, int offset) |
46 | { |
47 | uint16_t result; |
48 | memcpy(&result, &data->data()[offset], 2); |
49 | #if CPU(BIG_ENDIAN) |
50 | result = ((result & 0xff) << 8) | ((result & 0xff00) >> 8); |
51 | #endif |
52 | return result; |
53 | } |
54 | |
55 | static inline uint32_t readUint32(SharedBuffer* data, int offset) |
56 | { |
57 | uint32_t result; |
58 | memcpy(&result, &data->data()[offset], 4); |
59 | #if CPU(BIG_ENDIAN) |
60 | result = ((result & 0xff) << 24) | ((result & 0xff00) << 8) | ((result & 0xff0000) >> 8) | ((result & 0xff000000) >> 24); |
61 | #endif |
62 | return result; |
63 | } |
64 | |
65 | // |parent| is the decoder that owns us. |
66 | // |startOffset| points to the start of the BMP within the file. |
67 | // |buffer| points at an empty ScalableImageDecoderFrame that we'll initialize and |
68 | // fill with decoded data. |
69 | BMPImageReader(ScalableImageDecoder* parent, size_t decodedAndHeaderOffset, size_t imgDataOffset, bool usesAndMask); |
70 | |
71 | void setBuffer(ScalableImageDecoderFrame* buffer) { m_buffer = buffer; } |
72 | void setData(SharedBuffer* data) { m_data = data; } |
73 | |
74 | // Does the actual decoding. If |onlySize| is true, decoding only |
75 | // progresses as far as necessary to get the image size. Returns |
76 | // whether decoding succeeded. |
77 | bool decodeBMP(bool onlySize); |
78 | |
79 | private: |
80 | // The various BMP compression types. We don't currently decode all |
81 | // these. |
82 | enum CompressionType { |
83 | // Universal types |
84 | RGB = 0, |
85 | RLE8 = 1, |
86 | RLE4 = 2, |
87 | // Windows V3+ only |
88 | BITFIELDS = 3, |
89 | JPEG = 4, |
90 | PNG = 5, |
91 | // OS/2 2.x-only |
92 | HUFFMAN1D, // Stored in file as 3 |
93 | RLE24, // Stored in file as 4 |
94 | }; |
95 | enum AndMaskState { |
96 | None, |
97 | NotYetDecoded, |
98 | Decoding, |
99 | }; |
100 | enum ProcessingResult { |
101 | Success, |
102 | Failure, |
103 | InsufficientData, |
104 | }; |
105 | |
106 | // These are based on the Windows BITMAPINFOHEADER and RGBTRIPLE |
107 | // structs, but with unnecessary entries removed. |
108 | struct { |
109 | uint32_t ; |
110 | int32_t ; |
111 | int32_t ; |
112 | uint16_t ; |
113 | CompressionType ; |
114 | uint32_t ; |
115 | }; |
116 | struct RGBTriple { |
117 | uint8_t rgbBlue; |
118 | uint8_t rgbGreen; |
119 | uint8_t rgbRed; |
120 | }; |
121 | |
122 | inline uint16_t readUint16(int offset) const |
123 | { |
124 | return readUint16(m_data.get(), m_decodedOffset + offset); |
125 | } |
126 | |
127 | inline uint32_t readUint32(int offset) const |
128 | { |
129 | return readUint32(m_data.get(), m_decodedOffset + offset); |
130 | } |
131 | |
132 | // Determines the size of the BMP info header. Returns true if the size |
133 | // is valid. |
134 | bool (); |
135 | |
136 | // Processes the BMP info header. Returns true if the info header could |
137 | // be decoded. |
138 | bool (); |
139 | |
140 | // Helper function for processInfoHeader() which does the actual reading |
141 | // of header values from the byte stream. Returns false on error. |
142 | bool (); |
143 | |
144 | // Returns true if this is a Windows V4+ BMP. |
145 | inline bool isWindowsV4Plus() const |
146 | { |
147 | // Windows V4 info header is 108 bytes. V5 is 124 bytes. |
148 | return (m_infoHeader.biSize == 108) || (m_infoHeader.biSize == 124); |
149 | } |
150 | |
151 | // Returns false if consistency errors are found in the info header. |
152 | bool () const; |
153 | |
154 | // For BI_BITFIELDS images, initializes the m_bitMasks[] and |
155 | // m_bitOffsets[] arrays. processInfoHeader() will initialize these for |
156 | // other compression types where needed. |
157 | bool processBitmasks(); |
158 | |
159 | // For paletted images, allocates and initializes the m_colorTable[] |
160 | // array. |
161 | bool processColorTable(); |
162 | |
163 | // Processes an RLE-encoded image. Returns true if the entire image was |
164 | // decoded. |
165 | bool processRLEData(); |
166 | |
167 | // Processes a set of non-RLE-compressed pixels. Two cases: |
168 | // * inRLE = true: the data is inside an RLE-encoded bitmap. Tries to |
169 | // process |numPixels| pixels on the current row. |
170 | // * inRLE = false: the data is inside a non-RLE-encoded bitmap. |
171 | // |numPixels| is ignored. Expects |m_coord| to point at the |
172 | // beginning of the next row to be decoded. Tries to process as |
173 | // many complete rows as possible. Returns InsufficientData if |
174 | // there wasn't enough data to decode the whole image. |
175 | // |
176 | // This function returns a ProcessingResult instead of a bool so that it |
177 | // can avoid calling m_parent->setFailed(), which could lead to memory |
178 | // corruption since that will delete |this| but some callers still want |
179 | // to access member variables after this returns. |
180 | ProcessingResult processNonRLEData(bool inRLE, int numPixels); |
181 | |
182 | // Returns true if the current y-coordinate plus |numRows| would be past |
183 | // the end of the image. Here "plus" means "toward the end of the |
184 | // image", so downwards for m_isTopDown images and upwards otherwise. |
185 | inline bool pastEndOfImage(int numRows) |
186 | { |
187 | return m_isTopDown ? ((m_coord.y() + numRows) >= m_parent->size().height()) : ((m_coord.y() - numRows) < 0); |
188 | } |
189 | |
190 | // Returns the pixel data for the current X coordinate in a uint32_t. |
191 | // Assumes m_decodedOffset has been set to the beginning of the current |
192 | // row. |
193 | // NOTE: Only as many bytes of the return value as are needed to hold |
194 | // the pixel data will actually be set. |
195 | inline uint32_t readCurrentPixel(int bytesPerPixel) const |
196 | { |
197 | const int offset = m_coord.x() * bytesPerPixel; |
198 | switch (bytesPerPixel) { |
199 | case 2: |
200 | return readUint16(offset); |
201 | |
202 | case 3: { |
203 | // It doesn't matter that we never set the most significant byte |
204 | // of the return value here in little-endian mode, the caller |
205 | // won't read it. |
206 | uint32_t pixel; |
207 | memcpy(&pixel, &m_data->data()[m_decodedOffset + offset], 3); |
208 | #if CPU(BIG_ENDIAN) |
209 | pixel = ((pixel & 0xff00) << 8) | ((pixel & 0xff0000) >> 8) | ((pixel & 0xff000000) >> 24); |
210 | #endif |
211 | return pixel; |
212 | } |
213 | |
214 | case 4: |
215 | return readUint32(offset); |
216 | |
217 | default: |
218 | ASSERT_NOT_REACHED(); |
219 | return 0; |
220 | } |
221 | } |
222 | |
223 | // Returns the value of the desired component (0, 1, 2, 3 == R, G, B, A) |
224 | // in the given pixel data. |
225 | inline unsigned getComponent(uint32_t pixel, int component) const |
226 | { |
227 | return ((pixel & m_bitMasks[component]) >> m_bitShiftsRight[component]) << m_bitShiftsLeft[component]; |
228 | } |
229 | |
230 | inline unsigned getAlpha(uint32_t pixel) const |
231 | { |
232 | // For images without alpha, return alpha of 0xff. |
233 | return m_bitMasks[3] ? getComponent(pixel, 3) : 0xff; |
234 | } |
235 | |
236 | // Sets the current pixel to the color given by |colorIndex|. This also |
237 | // increments the relevant local variables to move the current pixel |
238 | // right by one. |
239 | inline void setI(size_t colorIndex) |
240 | { |
241 | setPixel(m_colorTable[colorIndex].rgbRed, m_colorTable[colorIndex].rgbGreen, m_colorTable[colorIndex].rgbBlue, 0xff); |
242 | } |
243 | |
244 | // Like setI(), but with the individual component values specified. |
245 | inline void setPixel(unsigned red, unsigned green, unsigned blue, unsigned alpha) |
246 | { |
247 | m_buffer->backingStore()->setPixel(m_coord.x(), m_coord.y(), red, green, blue, alpha); |
248 | m_coord.move(1, 0); |
249 | } |
250 | |
251 | // Fills pixels from the current X-coordinate up to, but not including, |
252 | // |endCoord| with the color given by the individual components. This |
253 | // also increments the relevant local variables to move the current |
254 | // pixel right to |endCoord|. |
255 | inline void fillRGBA(int endCoord, unsigned red, unsigned green, unsigned blue, unsigned alpha) |
256 | { |
257 | if (endCoord <= m_coord.x()) |
258 | return; |
259 | m_buffer->backingStore()->fillRect(IntRect(m_coord.x(), m_coord.y(), endCoord - m_coord.x(), 1), red, green, blue, alpha); |
260 | m_coord.setX(endCoord); |
261 | } |
262 | |
263 | // Resets the relevant local variables to start drawing at the left edge |
264 | // of the "next" row, where "next" is above or below the current row |
265 | // depending on the value of |m_isTopDown|. |
266 | void moveBufferToNextRow(); |
267 | |
268 | // The decoder that owns us. |
269 | ScalableImageDecoder* m_parent; |
270 | |
271 | // The destination for the pixel data. |
272 | ScalableImageDecoderFrame* m_buffer; |
273 | |
274 | // The file to decode. |
275 | RefPtr<SharedBuffer> m_data; |
276 | |
277 | // An index into |m_data| representing how much we've already decoded. |
278 | size_t m_decodedOffset; |
279 | |
280 | // The file offset at which the BMP info header starts. |
281 | size_t ; |
282 | |
283 | // The file offset at which the actual image bits start. When decoding |
284 | // ICO files, this is set to 0, since it's not stored anywhere in a |
285 | // header; the reader functions expect the image data to start |
286 | // immediately after the header and (if necessary) color table. |
287 | size_t m_imgDataOffset; |
288 | |
289 | // The BMP info header. |
290 | BitmapInfoHeader ; |
291 | |
292 | // True if this is an OS/2 1.x (aka Windows 2.x) BMP. The struct |
293 | // layouts for this type of BMP are slightly different from the later, |
294 | // more common formats. |
295 | bool m_isOS21x; |
296 | |
297 | // True if this is an OS/2 2.x BMP. The meanings of compression types 3 |
298 | // and 4 for this type of BMP differ from Windows V3+ BMPs. |
299 | // |
300 | // This will be falsely negative in some cases, but only ones where the |
301 | // way we misinterpret the data is irrelevant. |
302 | bool m_isOS22x; |
303 | |
304 | // True if the BMP is not vertically flipped, that is, the first line of |
305 | // raster data in the file is the top line of the image. |
306 | bool m_isTopDown; |
307 | |
308 | // These flags get set to false as we finish each processing stage. |
309 | bool m_needToProcessBitmasks; |
310 | bool m_needToProcessColorTable; |
311 | |
312 | // Masks/offsets for the color values for non-palette formats. These |
313 | // are bitwise, with array entries 0, 1, 2, 3 corresponding to R, G, B, |
314 | // A. |
315 | // |
316 | // The right/left shift values are meant to be applied after the masks. |
317 | // We need to right shift to compensate for the bitfields' offsets into |
318 | // the 32 bits of pixel data, and left shift to scale the color values |
319 | // up for fields with less than 8 bits of precision. Sadly, we can't |
320 | // just combine these into one shift value because the net shift amount |
321 | // could go either direction. (If only "<< -x" were equivalent to |
322 | // ">> x"...) |
323 | uint32_t m_bitMasks[4]; |
324 | int m_bitShiftsRight[4]; |
325 | int m_bitShiftsLeft[4]; |
326 | |
327 | // The color palette, for paletted formats. |
328 | size_t m_tableSizeInBytes; |
329 | Vector<RGBTriple> m_colorTable; |
330 | |
331 | // The coordinate to which we've decoded the image. |
332 | IntPoint m_coord; |
333 | |
334 | // Variables that track whether we've seen pixels with alpha values != 0 |
335 | // and == 0, respectively. See comments in processNonRLEData() on how |
336 | // these are used. |
337 | bool m_seenNonZeroAlphaPixel; |
338 | bool m_seenZeroAlphaPixel; |
339 | |
340 | // ICOs store a 1bpp "mask" immediately after the main bitmap image data |
341 | // (and, confusingly, add its height to the biHeight value in the info |
342 | // header, thus doubling it). This variable tracks whether we have such |
343 | // a mask and if we've started decoding it yet. |
344 | AndMaskState m_andMaskState; |
345 | }; |
346 | |
347 | } // namespace WebCore |
348 | |