• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef BMPImageReader_h
32 #define BMPImageReader_h
33 
34 #include <stdint.h>
35 #include "ImageDecoder.h"
36 
37 namespace WebCore {
38 
39     // This class decodes a BMP image.  It is used in the BMP and ICO decoders,
40     // which wrap it in the appropriate code to read file headers, etc.
41     class BMPImageReader {
42     public:
43         // Read a value from |data[offset]|, converting from little to native
44         // endianness.
readUint16(SharedBuffer * data,int offset)45         static inline uint16_t readUint16(SharedBuffer* data, int offset)
46         {
47             uint16_t result;
48             memcpy(&result, &data->data()[offset], 2);
49         #if PLATFORM(BIG_ENDIAN)
50             result = ((result & 0xff) << 8) | ((result & 0xff00) >> 8);
51         #endif
52             return result;
53         }
54 
readUint32(SharedBuffer * data,int offset)55         static inline uint32_t readUint32(SharedBuffer* data, int offset)
56         {
57             uint32_t result;
58             memcpy(&result, &data->data()[offset], 4);
59         #if PLATFORM(BIG_ENDIAN)
60             result = ((result & 0xff) << 24) | ((result & 0xff00) << 8) |
61                 ((result & 0xff0000) >> 8) | ((result & 0xff000000) >> 24);
62         #endif
63             return result;
64         }
65 
66         // |parent| is the decoder that owns us.
67         // |startOffset| points to the start of the BMP within the file.
68         // |buffer| points at an empty RGBA32Buffer that we'll initialize and
69         // fill with decoded data.
70         BMPImageReader(ImageDecoder* parent,
71                        size_t decodedAndHeaderOffset,
72                        size_t imgDataOffset,
73                        bool usesAndMask);
74 
setBuffer(RGBA32Buffer * buffer)75         void setBuffer(RGBA32Buffer* buffer) { m_buffer = buffer; }
setData(SharedBuffer * data)76         void setData(SharedBuffer* data) { m_data = data; }
77 
78         // Does the actual decoding.  If |onlySize| is true, decoding only
79         // progresses as far as necessary to get the image size.  Returns
80         // whether decoding succeeded.
81         bool decodeBMP(bool onlySize);
82 
83     private:
84         // The various BMP compression types.  We don't currently decode all
85         // these.
86         enum CompressionType {
87             // Universal types
88             RGB = 0,
89             RLE8 = 1,
90             RLE4 = 2,
91             // Windows V3+ only
92             BITFIELDS = 3,
93             JPEG = 4,
94             PNG = 5,
95             // OS/2 2.x-only
96             HUFFMAN1D,  // Stored in file as 3
97             RLE24,      // Stored in file as 4
98         };
99         enum AndMaskState {
100             None,
101             NotYetDecoded,
102             Decoding,
103         };
104 
105         // These are based on the Windows BITMAPINFOHEADER and RGBTRIPLE
106         // structs, but with unnecessary entries removed.
107         struct BitmapInfoHeader {
108             uint32_t biSize;
109             int32_t biWidth;
110             int32_t biHeight;
111             uint16_t biBitCount;
112             CompressionType biCompression;
113             uint32_t biClrUsed;
114         };
115         struct RGBTriple {
116             uint8_t rgbBlue;
117             uint8_t rgbGreen;
118             uint8_t rgbRed;
119         };
120 
readUint16(int offset)121         inline uint16_t readUint16(int offset) const
122         {
123             return readUint16(m_data.get(), m_decodedOffset + offset);
124         }
125 
readUint32(int offset)126         inline uint32_t readUint32(int offset) const
127         {
128             return readUint32(m_data.get(), m_decodedOffset + offset);
129         }
130 
131         // Determines the size of the BMP info header.  Returns true if the size
132         // is valid.
133         bool readInfoHeaderSize();
134 
135         // Processes the BMP info header.  Returns true if the info header could
136         // be decoded.
137         bool processInfoHeader();
138 
139         // Helper function for processInfoHeader() which does the actual reading
140         // of header values from the byte stream.  Returns false on error.
141         bool readInfoHeader();
142 
143         // Returns true if this is a Windows V4+ BMP.
isWindowsV4Plus()144         inline bool isWindowsV4Plus() const
145         {
146             // Windows V4 info header is 108 bytes.  V5 is 124 bytes.
147             return (m_infoHeader.biSize == 108) || (m_infoHeader.biSize == 124);
148         }
149 
150         // Returns false if consistency errors are found in the info header.
151         bool isInfoHeaderValid() const;
152 
153         // For BI_BITFIELDS images, initializes the m_bitMasks[] and
154         // m_bitOffsets[] arrays.  processInfoHeader() will initialize these for
155         // other compression types where needed.
156         bool processBitmasks();
157 
158         // For paletted images, allocates and initializes the m_colorTable[]
159         // array.
160         bool processColorTable();
161 
162         // Processes an RLE-encoded image.  Returns true if the entire image was
163         // decoded.
164         bool processRLEData();
165 
166         // Processes a set of non-RLE-compressed pixels.  Two cases:
167         //   * inRLE = true: the data is inside an RLE-encoded bitmap.  Tries to
168         //     process |numPixels| pixels on the current row; returns true on
169         //     success.
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 true if the whole image
174         //     was decoded.
175         bool processNonRLEData(bool inRLE, int numPixels);
176 
177         // Returns true if the current y-coordinate plus |numRows| would be past
178         // the end of the image.  Here "plus" means "toward the end of the
179         // image", so downwards for m_isTopDown images and upwards otherwise.
pastEndOfImage(int numRows)180         inline bool pastEndOfImage(int numRows)
181         {
182             return m_isTopDown
183                 ? ((m_coord.y() + numRows) >= m_parent->size().height())
184                 : ((m_coord.y() - numRows) < 0);
185         }
186 
187         // Returns the pixel data for the current X coordinate in a uint32_t.
188         // Assumes m_decodedOffset has been set to the beginning of the current
189         // row.
190         // NOTE: Only as many bytes of the return value as are needed to hold
191         // the pixel data will actually be set.
readCurrentPixel(int bytesPerPixel)192         inline uint32_t readCurrentPixel(int bytesPerPixel) const
193         {
194             const int offset = m_coord.x() * bytesPerPixel;
195             switch (bytesPerPixel) {
196             case 2:
197                 return readUint16(offset);
198 
199             case 3: {
200                 // It doesn't matter that we never set the most significant byte
201                 // of the return value here in little-endian mode, the caller
202                 // won't read it.
203                 uint32_t pixel;
204                 memcpy(&pixel, &m_data->data()[m_decodedOffset + offset], 3);
205         #if PLATFORM(BIG_ENDIAN)
206                 pixel = ((pixel & 0xff00) << 8) | ((pixel & 0xff0000) >> 8) |
207                     ((pixel & 0xff000000) >> 24);
208         #endif
209                 return pixel;
210             }
211 
212             case 4:
213                 return readUint32(offset);
214 
215             default:
216                 ASSERT_NOT_REACHED();
217                 return 0;
218             }
219         }
220 
221         // Returns the value of the desired component (0, 1, 2, 3 == R, G, B, A)
222         // in the given pixel data.
getComponent(uint32_t pixel,int component)223         inline unsigned getComponent(uint32_t pixel, int component) const
224         {
225             return ((pixel & m_bitMasks[component]) >>
226                 m_bitShiftsRight[component]) << m_bitShiftsLeft[component];
227         }
228 
getAlpha(uint32_t pixel)229         inline unsigned getAlpha(uint32_t pixel) const
230         {
231             // For images without alpha, return alpha of 0xff.
232             if (m_bitMasks[3] == 0)
233                 return 0xff;
234 
235             return getComponent(pixel, 3);
236         }
237 
238         // Sets the current pixel to the color given by |colorIndex|.  This also
239         // increments the relevant local variables to move the current pixel
240         // right by one.
setI(size_t colorIndex)241         inline void setI(size_t colorIndex)
242         {
243             setRGBA(m_colorTable[colorIndex].rgbRed,
244                     m_colorTable[colorIndex].rgbGreen,
245                     m_colorTable[colorIndex].rgbBlue, 0xff);
246         }
247 
248         // Like setI(), but with the individual component values specified.
setRGBA(unsigned red,unsigned green,unsigned blue,unsigned alpha)249         inline void setRGBA(unsigned red,
250                             unsigned green,
251                             unsigned blue,
252                             unsigned alpha)
253         {
254             m_buffer->setRGBA(m_coord.x(), m_coord.y(), red, green, blue,
255                               alpha);
256             m_coord.move(1, 0);
257         }
258 
259         // Fills pixels from the current X-coordinate up to, but not including,
260         // |endCoord| with the color given by the individual components.  This
261         // also increments the relevant local variables to move the current
262         // pixel right to |endCoord|.
fillRGBA(int endCoord,unsigned red,unsigned green,unsigned blue,unsigned alpha)263         inline void fillRGBA(int endCoord,
264                              unsigned red,
265                              unsigned green,
266                              unsigned blue,
267                              unsigned alpha)
268         {
269             while (m_coord.x() < endCoord)
270                 setRGBA(red, green, blue, alpha);
271         }
272 
273         // Resets the relevant local variables to start drawing at the left edge
274         // of the "next" row, where "next" is above or below the current row
275         // depending on the value of |m_isTopDown|.
276         void moveBufferToNextRow();
277 
278         // Sets the "decode failure" flag and clears any local storage.  For
279         // caller convenience (since so many callers want to return false after
280         // calling this), returns false to enable easy tailcalling.
281         bool setFailed();
282 
283         // The decoder that owns us.
284         ImageDecoder* m_parent;
285 
286         // The destination for the pixel data.
287         RGBA32Buffer* m_buffer;
288 
289         // The file to decode.
290         RefPtr<SharedBuffer> m_data;
291 
292         // An index into |m_data| representing how much we've already decoded.
293         size_t m_decodedOffset;
294 
295         // The file offset at which the BMP info header starts.
296         size_t m_headerOffset;
297 
298         // The file offset at which the actual image bits start.  When decoding
299         // ICO files, this is set to 0, since it's not stored anywhere in a
300         // header; the reader functions expect the image data to start
301         // immediately after the header and (if necessary) color table.
302         size_t m_imgDataOffset;
303 
304         // The BMP info header.
305         BitmapInfoHeader m_infoHeader;
306 
307         // True if this is an OS/2 1.x (aka Windows 2.x) BMP.  The struct
308         // layouts for this type of BMP are slightly different from the later,
309         // more common formats.
310         bool m_isOS21x;
311 
312         // True if this is an OS/2 2.x BMP.  The meanings of compression types 3
313         // and 4 for this type of BMP differ from Windows V3+ BMPs.
314         //
315         // This will be falsely negative in some cases, but only ones where the
316         // way we misinterpret the data is irrelevant.
317         bool m_isOS22x;
318 
319         // True if the BMP is not vertically flipped, that is, the first line of
320         // raster data in the file is the top line of the image.
321         bool m_isTopDown;
322 
323         // These flags get set to false as we finish each processing stage.
324         bool m_needToProcessBitmasks;
325         bool m_needToProcessColorTable;
326 
327         // Masks/offsets for the color values for non-palette formats.  These
328         // are bitwise, with array entries 0, 1, 2, 3 corresponding to R, G, B,
329         // A.
330         //
331         // The right/left shift values are meant to be applied after the masks.
332         // We need to right shift to compensate for the bitfields' offsets into
333         // the 32 bits of pixel data, and left shift to scale the color values
334         // up for fields with less than 8 bits of precision.  Sadly, we can't
335         // just combine these into one shift value because the net shift amount
336         // could go either direction.  (If only "<< -x" were equivalent to
337         // ">> x"...)
338         uint32_t m_bitMasks[4];
339         int m_bitShiftsRight[4];
340         int m_bitShiftsLeft[4];
341 
342         // The color palette, for paletted formats.
343         size_t m_tableSizeInBytes;
344         Vector<RGBTriple> m_colorTable;
345 
346         // The coordinate to which we've decoded the image.
347         IntPoint m_coord;
348 
349         // Variables that track whether we've seen pixels with alpha values != 0
350         // and == 0, respectively.  See comments in processNonRLEData() on how
351         // these are used.
352         bool m_seenNonZeroAlphaPixel;
353         bool m_seenZeroAlphaPixel;
354 
355         // ICOs store a 1bpp "mask" immediately after the main bitmap image data
356         // (and, confusingly, add its height to the biHeight value in the info
357         // header, thus doubling it).  This variable tracks whether we have such
358         // a mask and if we've started decoding it yet.
359         AndMaskState m_andMaskState;
360     };
361 
362 } // namespace WebCore
363 
364 #endif
365