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

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

Issue 2930513004: [WIP] Move ImageDecoders to SkCodec
Patch Set: Adding check for decoder creation Created 3 years, 6 months 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
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/FastSharedBufferReader.h"
36 #include "platform/image-decoders/ImageDecoder.h"
37 #include "platform/wtf/Allocator.h"
38 #include "platform/wtf/CPU.h"
39 #include "platform/wtf/Noncopyable.h"
40
41 namespace blink {
42
43 // This class decodes a BMP image. It is used in the BMP and ICO decoders,
44 // which wrap it in the appropriate code to read file headers, etc.
45 class PLATFORM_EXPORT BMPImageReader final {
46 USING_FAST_MALLOC(BMPImageReader);
47 WTF_MAKE_NONCOPYABLE(BMPImageReader);
48
49 public:
50 // Read a value from |buffer|, converting to an int assuming little
51 // endianness
52 static inline uint16_t ReadUint16(const char* buffer) {
53 return *reinterpret_cast<const uint16_t*>(buffer);
54 }
55
56 static inline uint32_t ReadUint32(const char* buffer) {
57 return *reinterpret_cast<const uint32_t*>(buffer);
58 }
59
60 // |parent| is the decoder that owns us.
61 // |start_offset| points to the start of the BMP within the file.
62 // |buffer| points at an empty ImageFrame that we'll initialize and
63 // fill with decoded data.
64 BMPImageReader(ImageDecoder* parent,
65 size_t decoded_and_header_offset,
66 size_t img_data_offset,
67 bool is_in_ico);
68
69 void SetBuffer(ImageFrame* buffer) { buffer_ = buffer; }
70 void SetData(SegmentReader* data) {
71 data_ = data;
72 fast_reader_.SetData(data);
73 }
74
75 // Does the actual decoding. If |only_size| is true, decoding only
76 // progresses as far as necessary to get the image size. Returns
77 // whether decoding succeeded.
78 bool DecodeBMP(bool only_size);
79
80 private:
81 friend class PixelChangedScoper;
82
83 // Helper for DecodeBMP() which will call either ProcessRLEData() or
84 // ProcessNonRLEData(), depending on the value of |non_rle|, call any
85 // appropriate notifications to deal with the result, then return whether
86 // decoding succeeded.
87 bool DecodePixelData(bool non_rle);
88
89 // The various BMP compression types. We don't currently decode all
90 // these.
91 enum CompressionType {
92 // Universal types
93 RGB = 0,
94 RLE8 = 1,
95 RLE4 = 2,
96 // Windows V3+ only
97 BITFIELDS = 3,
98 JPEG = 4,
99 PNG = 5,
100 // OS/2 2.x-only
101 HUFFMAN1D, // Stored in file as 3
102 RLE24, // Stored in file as 4
103 };
104 enum ProcessingResult {
105 kSuccess,
106 kFailure,
107 kInsufficientData,
108 };
109
110 // These are based on the Windows BITMAPINFOHEADER and RGBTRIPLE
111 // structs, but with unnecessary entries removed.
112 struct BitmapInfoHeader {
113 DISALLOW_NEW();
114 uint32_t bi_size;
115 int32_t bi_width;
116 int32_t bi_height;
117 uint16_t bi_bit_count;
118 CompressionType bi_compression;
119 uint32_t bi_clr_used;
120 };
121 struct RGBTriple {
122 DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
123 uint8_t rgb_blue;
124 uint8_t rgb_green;
125 uint8_t rgb_red;
126 };
127
128 inline uint8_t ReadUint8(size_t offset) const {
129 return fast_reader_.GetOneByte(decoded_offset_ + offset);
130 }
131
132 inline uint16_t ReadUint16(int offset) const {
133 char buffer[2];
134 const char* data =
135 fast_reader_.GetConsecutiveData(decoded_offset_ + offset, 2, buffer);
136 return ReadUint16(data);
137 }
138
139 inline uint32_t ReadUint32(int offset) const {
140 char buffer[4];
141 const char* data =
142 fast_reader_.GetConsecutiveData(decoded_offset_ + offset, 4, buffer);
143 return ReadUint32(data);
144 }
145
146 // Determines the size of the BMP info header. Returns true if the size
147 // is valid.
148 bool ReadInfoHeaderSize();
149
150 // Processes the BMP info header. Returns true if the info header could
151 // be decoded.
152 bool ProcessInfoHeader();
153
154 // Helper function for ProcessInfoHeader() which does the actual reading
155 // of header values from the byte stream. Returns false on error.
156 bool ReadInfoHeader();
157
158 // Returns true if this is a Windows V4+ BMP.
159 inline bool IsWindowsV4Plus() const {
160 // Windows V4 info header is 108 bytes. V5 is 124 bytes.
161 return (info_header_.bi_size == 108) || (info_header_.bi_size == 124);
162 }
163
164 // Returns false if consistency errors are found in the info header.
165 bool IsInfoHeaderValid() const;
166
167 // For BI_BITFIELDS images, initializes the bit_masks_[] and
168 // bit_offsets_[] arrays. ProcessInfoHeader() will initialize these for
169 // other compression types where needed.
170 bool ProcessBitmasks();
171
172 // For paletted images, allocates and initializes the color_table_[]
173 // array.
174 bool ProcessColorTable();
175
176 // The next two functions return a ProcessingResult instead of a bool so
177 // they can avoid calling 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 they return.
180
181 // Processes an RLE-encoded image.
182 ProcessingResult ProcessRLEData();
183
184 // Processes a set of non-RLE-compressed pixels. Two cases:
185 // * in_rle = true: the data is inside an RLE-encoded bitmap. Tries to
186 // process |num_pixels| pixels on the current row.
187 // * in_rle = false: the data is inside a non-RLE-encoded bitmap.
188 // |num_pixels| is ignored. Expects |coord_| to point at the
189 // beginning of the next row to be decoded. Tries to process as
190 // many complete rows as possible. Returns InsufficientData if
191 // there wasn't enough data to decode the whole image.
192 ProcessingResult ProcessNonRLEData(bool in_rle, int num_pixels);
193
194 // Returns true if the current y-coordinate plus |num_rows| would be past
195 // the end of the image. Here "plus" means "toward the end of the
196 // image", so downwards for is_top_down_ images and upwards otherwise.
197 inline bool PastEndOfImage(int num_rows) {
198 return is_top_down_ ? ((coord_.Y() + num_rows) >= parent_->Size().Height())
199 : ((coord_.Y() - num_rows) < 0);
200 }
201
202 // Returns the pixel data for the current X coordinate in a uint32_t.
203 // Assumes decoded_offset has been set to the beginning of the current
204 // row.
205 // NOTE: Only as many bytes of the return value as are needed to hold
206 // the pixel data will actually be set.
207 inline uint32_t ReadCurrentPixel(int bytes_per_pixel) const {
208 // We need at most 4 bytes, starting at decoded_offset_ + offset.
209 char buffer[4];
210 const int offset = coord_.X() * bytes_per_pixel;
211 const char* encoded_pixel = fast_reader_.GetConsecutiveData(
212 decoded_offset_ + offset, bytes_per_pixel, buffer);
213 switch (bytes_per_pixel) {
214 case 2:
215 return ReadUint16(encoded_pixel);
216
217 case 3: {
218 // It doesn't matter that we never set the most significant byte
219 // of the return value, the caller won't read it.
220 uint32_t pixel;
221 memcpy(&pixel, encoded_pixel, 3);
222 return pixel;
223 }
224
225 case 4:
226 return ReadUint32(encoded_pixel);
227
228 default:
229 NOTREACHED();
230 return 0;
231 }
232 }
233
234 // Returns the value of the desired component (0, 1, 2, 3 == R, G, B, A)
235 // in the given pixel data.
236 inline unsigned GetComponent(uint32_t pixel, int component) const {
237 uint8_t value =
238 (pixel & bit_masks_[component]) >> bit_shifts_right_[component];
239 return lookup_table_addresses_[component]
240 ? lookup_table_addresses_[component][value]
241 : value;
242 }
243
244 inline unsigned GetAlpha(uint32_t pixel) const {
245 // For images without alpha, return alpha of 0xff.
246 return bit_masks_[3] ? GetComponent(pixel, 3) : 0xff;
247 }
248
249 // Sets the current pixel to the color given by |color_index|. This also
250 // increments the relevant local variables to move the current pixel
251 // right by one.
252 inline void SetI(size_t color_index) {
253 SetRGBA(color_table_[color_index].rgb_red,
254 color_table_[color_index].rgb_green,
255 color_table_[color_index].rgb_blue, 0xff);
256 }
257
258 // Like SetI(), but with the individual component values specified.
259 inline void SetRGBA(unsigned red,
260 unsigned green,
261 unsigned blue,
262 unsigned alpha) {
263 buffer_->SetRGBA(coord_.X(), coord_.Y(), red, green, blue, alpha);
264 coord_.Move(1, 0);
265 }
266
267 // Fills pixels from the current X-coordinate up to, but not including,
268 // |end_coord| with the color given by the individual components. This
269 // also increments the relevant local variables to move the current
270 // pixel right to |end_coord|.
271 inline void FillRGBA(int end_coord,
272 unsigned red,
273 unsigned green,
274 unsigned blue,
275 unsigned alpha) {
276 while (coord_.X() < end_coord)
277 SetRGBA(red, green, blue, alpha);
278 }
279
280 // Resets the relevant local variables to start drawing at the left edge
281 // of the "next" row, where "next" is above or below the current row
282 // depending on the value of |is_top_down_|.
283 void MoveBufferToNextRow();
284
285 // The decoder that owns us.
286 ImageDecoder* parent_;
287
288 // The destination for the pixel data.
289 ImageFrame* buffer_;
290
291 // The file to decode.
292 RefPtr<SegmentReader> data_;
293 FastSharedBufferReader fast_reader_;
294
295 // An index into |data_| representing how much we've already decoded.
296 size_t decoded_offset_;
297
298 // The file offset at which the BMP info header starts.
299 size_t header_offset_;
300
301 // The file offset at which the actual image bits start. When decoding
302 // ICO files, this is set to 0, since it's not stored anywhere in a
303 // header; the reader functions expect the image data to start
304 // immediately after the header and (if necessary) color table.
305 size_t img_data_offset_;
306
307 // The BMP info header.
308 BitmapInfoHeader info_header_;
309
310 // True if this is an OS/2 1.x (aka Windows 2.x) BMP. The struct
311 // layouts for this type of BMP are slightly different from the later,
312 // more common formats.
313 bool is_os21x_;
314
315 // True if this is an OS/2 2.x BMP. The meanings of compression types 3
316 // and 4 for this type of BMP differ from Windows V3+ BMPs.
317 //
318 // This will be falsely negative in some cases, but only ones where the
319 // way we misinterpret the data is irrelevant.
320 bool is_os22x_;
321
322 // True if the BMP is not vertically flipped, that is, the first line of
323 // raster data in the file is the top line of the image.
324 bool is_top_down_;
325
326 // These flags get set to false as we finish each processing stage.
327 bool need_to_process_bitmasks_;
328 bool need_to_process_color_table_;
329
330 // Masks/offsets for the color values for non-palette formats. These are
331 // bitwise, with array entries 0, 1, 2, 3 corresponding to R, G, B, A.
332 // These are uninitialized (and ignored) for images with less than 16bpp.
333 uint32_t bit_masks_[4];
334
335 // Right shift values, meant to be applied after the masks. We need to shift
336 // the bitfield values down from their offsets into the 32 bits of pixel
337 // data, as well as truncate the least significant bits of > 8-bit fields.
338 int bit_shifts_right_[4];
339
340 // We use a lookup table to convert < 8-bit values into 8-bit values. The
341 // values in the table are "round(val * 255.0 / ((1 << n) - 1))" for an
342 // n-bit source value. These elements are set to 0 for 8-bit sources.
343 const uint8_t* lookup_table_addresses_[4];
344
345 // The color palette, for paletted formats.
346 Vector<RGBTriple> color_table_;
347
348 // The coordinate to which we've decoded the image.
349 IntPoint coord_;
350
351 // Variables that track whether we've seen pixels with alpha values != 0
352 // and == 0, respectively. See comments in ProcessNonRLEData() on how
353 // these are used.
354 bool seen_non_zero_alpha_pixel_;
355 bool seen_zero_alpha_pixel_;
356
357 // BMPs-in-ICOs have a few differences from standalone BMPs, so we need to
358 // know if we're in an ICO container.
359 bool is_in_ico_;
360
361 // ICOs store a 1bpp "mask" immediately after the main bitmap image data
362 // (and, confusingly, add its height to the biHeight value in the info
363 // header, thus doubling it). If |is_in_ico_| is true, this variable tracks
364 // whether we've begun decoding this mask yet.
365 bool decoding_and_mask_;
366 };
367
368 } // namespace blink
369
370 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698