Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(180)

Side by Side Diff: Source/platform/image-decoders/bmp/BMPImageReader.h

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

Powered by Google App Engine
This is Rietveld 408576698