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

Side by Side Diff: src/codec/SkCodec_libbmp.cpp

Issue 947283002: Bmp Image Decoding (Closed) Base URL: https://skia.googlesource.com/skia.git@decode-leon-3
Patch Set: Commented out the rare case until we demonstrate that we need it Created 5 years, 9 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
« no previous file with comments | « src/codec/SkCodec_libbmp.h ('k') | src/codec/SkCodec_libpng.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "SkCodec_libbmp.h"
9 #include "SkCodecPriv.h"
10 #include "SkColorPriv.h"
11 #include "SkStream.h"
12
13 /*
14 *
15 * Checks if the conversion between the input image and the requested output
16 * image has been implemented
17 *
18 */
19 static bool conversion_possible(const SkImageInfo& dst,
20 const SkImageInfo& src) {
21 // All of the swizzles convert to kN32
22 // TODO: Update this when more swizzles are supported
23 if (kN32_SkColorType != dst.colorType()) {
24 return false;
25 }
26 // Support the swizzle if the requested alpha type is the same as our guess
27 // for the input alpha type
28 if (src.alphaType() == dst.alphaType()) {
29 return true;
30 }
31 // Also support requests for premul in the unpremul case, despite the fact
32 // that all of the swizzles currently create an unpremul image
33 // TODO: Update the swizzles so this makes more sense
34 return premul_and_unpremul(dst.alphaType(), src.alphaType())
35 || premul_and_unpremul(dst.alphaType(), src.alphaType());
36 }
37
38 /*
39 *
40 * Defines the version and type of the second bitmap header
41 *
42 */
43 enum BitmapHeaderType {
44 kInfoV1_BitmapHeaderType,
45 kInfoV2_BitmapHeaderType,
46 kInfoV3_BitmapHeaderType,
47 kInfoV4_BitmapHeaderType,
48 kInfoV5_BitmapHeaderType,
49 kOS2V1_BitmapHeaderType,
50 kOS2VX_BitmapHeaderType,
51 kUnknown_BitmapHeaderType
52 };
53
54 /*
55 *
56 * Possible bitmap compression types
57 *
58 */
59 enum BitmapCompressionMethod {
60 kNone_BitmapCompressionMethod = 0,
61 k8BitRLE_BitmapCompressionMethod = 1,
62 k4BitRLE_BitmapCompressionMethod = 2,
63 kBitMasks_BitmapCompressionMethod = 3,
64 kJpeg_BitmapCompressionMethod = 4,
65 kPng_BitmapCompressionMethod = 5,
66 kAlphaBitMasks_BitmapCompressionMethod = 6,
67 kCMYK_BitmapCompressionMethod = 11,
68 kCMYK8BitRLE_BitmapCompressionMethod = 12,
69 kCMYK4BitRLE_BitmapCompressionMethod = 13
70 };
71
72 /*
73 *
74 * Checks the start of the stream to see if the image is a bitmap
75 *
76 */
77 bool SkBmpCodec::IsBmp(SkStream* stream) {
78 // TODO: Support "IC", "PT", "CI", "CP", "BA"
79 // TODO: ICO files may contain a BMP and need to use this decoder
80 const char bmpSig[] = { 'B', 'M' };
81 char buffer[sizeof(bmpSig)];
82 return stream->read(buffer, sizeof(bmpSig)) == sizeof(bmpSig) &&
83 !memcmp(buffer, bmpSig, sizeof(bmpSig));
84 }
85
86 /*
87 *
88 * Assumes IsBmp was called and returned true
89 * Creates a bitmap decoder
90 * Reads enough of the stream to determine the image format
91 *
92 */
93 SkCodec* SkBmpCodec::NewFromStream(SkStream* stream) {
94 // Header size constants
95 static const uint32_t kBmpHeaderBytes = 14;
96 static const uint32_t kBmpHeaderBytesPlusFour = kBmpHeaderBytes + 4;
97 static const uint32_t kBmpOS2V1Bytes = 12;
98 static const uint32_t kBmpOS2V2Bytes = 64;
99 static const uint32_t kBmpInfoBaseBytes = 16;
100 static const uint32_t kBmpInfoV1Bytes = 40;
101 static const uint32_t kBmpInfoV2Bytes = 52;
102 static const uint32_t kBmpInfoV3Bytes = 56;
103 static const uint32_t kBmpInfoV4Bytes = 108;
104 static const uint32_t kBmpInfoV5Bytes = 124;
105 static const uint32_t kBmpMaskBytes = 12;
106
107 // Read the first header and the size of the second header
108 SkAutoTDeleteArray<uint8_t> hBuffer(
109 SkNEW_ARRAY(uint8_t, kBmpHeaderBytesPlusFour));
110 if (stream->read(hBuffer.get(), kBmpHeaderBytesPlusFour) !=
111 kBmpHeaderBytesPlusFour) {
112 SkDebugf("Error: unable to read first bitmap header.\n");
113 return NULL;
114 }
115
116 // The total bytes in the bmp file
117 // We only need to use this value for RLE decoding, so we will only check
118 // that it is valid in the RLE case.
119 const uint32_t totalBytes = get_int(hBuffer.get(), 2);
120
121 // The offset from the start of the file where the pixel data begins
122 const uint32_t offset = get_int(hBuffer.get(), 10);
123 if (offset < kBmpHeaderBytes + kBmpOS2V1Bytes) {
124 SkDebugf("Error: invalid starting location for pixel data\n");
125 return NULL;
126 }
127
128 // The size of the second (info) header in bytes
129 // The size is the first field of the second header, so we have already
130 // read the first four infoBytes.
131 const uint32_t infoBytes = get_int(hBuffer.get(), 14);
132 if (infoBytes < kBmpOS2V1Bytes) {
133 SkDebugf("Error: invalid second header size.\n");
134 return NULL;
135 }
136 const uint32_t infoBytesRemaining = infoBytes - 4;
137 hBuffer.free();
138
139 // Read the second header
140 SkAutoTDeleteArray<uint8_t> iBuffer(
141 SkNEW_ARRAY(uint8_t, infoBytesRemaining));
142 if (stream->read(iBuffer.get(), infoBytesRemaining) != infoBytesRemaining) {
143 SkDebugf("Error: unable to read second bitmap header.\n");
144 return NULL;
145 }
146
147 // The number of bits used per pixel in the pixel data
148 uint16_t bitsPerPixel;
149
150 // The compression method for the pixel data
151 uint32_t compression = kNone_BitmapCompressionMethod;
152
153 // Number of colors in the color table, defaults to 0 or max (see below)
154 uint32_t numColors = 0;
155
156 // Bytes per color in the color table, early versions use 3, most use 4
157 uint32_t bytesPerColor;
158
159 // The image width and height
160 int width, height;
161
162 // Determine image information depending on second header format
163 BitmapHeaderType headerType;
164 if (infoBytes >= kBmpInfoBaseBytes) {
165 // Check the version of the header
166 switch (infoBytes) {
167 case kBmpInfoV1Bytes:
168 headerType = kInfoV1_BitmapHeaderType;
169 break;
170 case kBmpInfoV2Bytes:
171 headerType = kInfoV2_BitmapHeaderType;
172 break;
173 case kBmpInfoV3Bytes:
174 headerType = kInfoV3_BitmapHeaderType;
175 break;
176 case kBmpInfoV4Bytes:
177 headerType = kInfoV4_BitmapHeaderType;
178 break;
179 case kBmpInfoV5Bytes:
180 headerType = kInfoV5_BitmapHeaderType;
181 break;
182 case 16:
183 case 20:
184 case 24:
185 case 28:
186 case 32:
187 case 36:
188 case 42:
189 case 46:
190 case 48:
191 case 60:
192 case kBmpOS2V2Bytes:
193 headerType = kOS2VX_BitmapHeaderType;
194 break;
195 default:
196 // We do not signal an error here because there is the
197 // possibility of new or undocumented bmp header types. Most
198 // of the newer versions of bmp headers are similar to and
199 // build off of the older versions, so we may still be able to
200 // decode the bmp.
201 SkDebugf("Warning: unknown bmp header format.\n");
202 headerType = kUnknown_BitmapHeaderType;
203 break;
204 }
205 // We check the size of the header before entering the if statement.
206 // We should not reach this point unless the size is large enough for
207 // these required fields.
208 SkASSERT(infoBytesRemaining >= 12);
209 width = get_int(iBuffer.get(), 0);
210 height = get_int(iBuffer.get(), 4);
211 bitsPerPixel = get_short(iBuffer.get(), 10);
212
213 // Some versions do not have these fields, so we check before
214 // overwriting the default value.
215 if (infoBytesRemaining >= 16) {
216 compression = get_int(iBuffer.get(), 12);
217 if (infoBytesRemaining >= 32) {
218 numColors = get_int(iBuffer.get(), 28);
219 }
220 }
221
222 // All of the headers that reach this point, store color table entries
223 // using 4 bytes per pixel.
224 bytesPerColor = 4;
225 } else if (infoBytes >= kBmpOS2V1Bytes) {
226 // The OS2V1 is treated separately because it has a unique format
227 headerType = kOS2V1_BitmapHeaderType;
228 width = (int) get_short(iBuffer.get(), 0);
229 height = (int) get_short(iBuffer.get(), 2);
230 bitsPerPixel = get_short(iBuffer.get(), 6);
231 bytesPerColor = 3;
232 } else {
233 // There are no valid bmp headers
234 SkDebugf("Error: second bitmap header size is invalid.\n");
235 return NULL;
236 }
237
238 // Check for valid dimensions from header
239 RowOrder rowOrder = kBottomUp_RowOrder;
240 if (height < 0) {
241 height = -height;
242 rowOrder = kTopDown_RowOrder;
243 }
244 static const int kBmpMaxDim = 1 << 16;
245 if (width < 0 || width >= kBmpMaxDim || height >= kBmpMaxDim) {
246 // TODO: Decide if we want to support really large bmps.
247 SkDebugf("Error: invalid bitmap dimensions.\n");
248 return NULL;
249 }
250
251 // Create mask struct
252 SkMasks::InputMasks inputMasks;
253 memset(&inputMasks, 0, 4*sizeof(uint32_t));
254
255 // Determine the input compression format and set bit masks if necessary
256 uint32_t maskBytes = 0;
257 BitmapInputFormat inputFormat = kUnknown_BitmapInputFormat;
258 switch (compression) {
259 case kNone_BitmapCompressionMethod:
260 inputFormat = kStandard_BitmapInputFormat;
261 break;
262 case k8BitRLE_BitmapCompressionMethod:
263 if (bitsPerPixel != 8) {
264 SkDebugf("Warning: correcting invalid bitmap format.\n");
265 bitsPerPixel = 8;
266 }
267 inputFormat = kRLE_BitmapInputFormat;
268 break;
269 case k4BitRLE_BitmapCompressionMethod:
270 if (bitsPerPixel != 4) {
271 SkDebugf("Warning: correcting invalid bitmap format.\n");
272 bitsPerPixel = 4;
273 }
274 inputFormat = kRLE_BitmapInputFormat;
275 break;
276 case kAlphaBitMasks_BitmapCompressionMethod:
277 case kBitMasks_BitmapCompressionMethod:
278 // Load the masks
279 inputFormat = kBitMask_BitmapInputFormat;
280 switch (headerType) {
281 case kInfoV1_BitmapHeaderType: {
282 // The V1 header stores the bit masks after the header
283 SkAutoTDeleteArray<uint8_t> mBuffer(
284 SkNEW_ARRAY(uint8_t, kBmpMaskBytes));
285 if (stream->read(mBuffer.get(), kBmpMaskBytes) !=
286 kBmpMaskBytes) {
287 SkDebugf("Error: unable to read bit inputMasks.\n");
288 return NULL;
289 }
290 maskBytes = kBmpMaskBytes;
291 inputMasks.red = get_int(mBuffer.get(), 0);
292 inputMasks.green = get_int(mBuffer.get(), 4);
293 inputMasks.blue = get_int(mBuffer.get(), 8);
294 break;
295 }
296 case kInfoV2_BitmapHeaderType:
297 case kInfoV3_BitmapHeaderType:
298 case kInfoV4_BitmapHeaderType:
299 case kInfoV5_BitmapHeaderType:
300 // Header types are matched based on size. If the header
301 // is V2+, we are guaranteed to be able to read at least
302 // this size.
303 SkASSERT(infoBytesRemaining >= 48);
304 inputMasks.red = get_int(iBuffer.get(), 36);
305 inputMasks.green = get_int(iBuffer.get(), 40);
306 inputMasks.blue = get_int(iBuffer.get(), 44);
307 break;
308 case kOS2VX_BitmapHeaderType:
309 // TODO: Decide if we intend to support this.
310 // It is unsupported in the previous version and
311 // in chromium. I have not come across a test case
312 // that uses this format.
313 SkDebugf("Error: huffman format unsupported.\n");
314 return NULL;
315 default:
316 SkDebugf("Error: invalid bmp bit masks header.\n");
317 return NULL;
318 }
319 break;
320 case kJpeg_BitmapCompressionMethod:
321 if (24 == bitsPerPixel) {
322 inputFormat = kRLE_BitmapInputFormat;
323 break;
324 }
325 // Fall through
326 case kPng_BitmapCompressionMethod:
327 // TODO: Decide if we intend to support this.
328 // It is unsupported in the previous version and
329 // in chromium. I think it is used mostly for printers.
330 SkDebugf("Error: compression format not supported.\n");
331 return NULL;
332 case kCMYK_BitmapCompressionMethod:
333 case kCMYK8BitRLE_BitmapCompressionMethod:
334 case kCMYK4BitRLE_BitmapCompressionMethod:
335 // TODO: Same as above.
336 SkDebugf("Error: CMYK not supported for bitmap decoding.\n");
337 return NULL;
338 default:
339 SkDebugf("Error: invalid format for bitmap decoding.\n");
340 return NULL;
341 }
342
343 // Most versions of bmps should be rendered as opaque. Either they do
344 // not have an alpha channel, or they expect the alpha channel to be
345 // ignored. V4+ bmp files introduce an alpha mask and allow the creator
346 // of the image to use the alpha channels. However, many of these images
347 // leave the alpha channel blank and expect to be rendered as opaque. For
348 // this reason, we set the alpha type to kUnknown for V4+ bmps and figure
349 // out the alpha type during the decode.
350 SkAlphaType alphaType = kOpaque_SkAlphaType;
351 if (kInfoV4_BitmapHeaderType == headerType ||
352 kInfoV5_BitmapHeaderType == headerType) {
353 // Header types are matched based on size. If the header is
354 // V4+, we are guaranteed to be able to read at least this size.
355 SkASSERT(infoBytesRemaining > 52);
356 inputMasks.alpha = get_int(iBuffer.get(), 48);
357 if (inputMasks.alpha != 0) {
358 alphaType = kUnpremul_SkAlphaType;
359 }
360 }
361 iBuffer.free();
362
363 // Check for valid bits per pixel input
364 switch (bitsPerPixel) {
365 // In addition to more standard pixel compression formats, bmp supports
366 // the use of bit masks to determine pixel components. The standard
367 // format for representing 16-bit colors is 555 (XRRRRRGGGGGBBBBB),
368 // which does not map well to any Skia color formats. For this reason,
369 // we will always enable mask mode with 16 bits per pixel.
370 case 16:
371 if (kBitMask_BitmapInputFormat != inputFormat) {
372 inputMasks.red = 0x7C00;
373 inputMasks.green = 0x03E0;
374 inputMasks.blue = 0x001F;
375 inputFormat = kBitMask_BitmapInputFormat;
376 }
377 break;
378 case 1:
379 case 2:
380 case 4:
381 case 8:
382 case 24:
383 case 32:
384 break;
385 default:
386 SkDebugf("Error: invalid input value for bits per pixel.\n");
387 return NULL;
388 }
389
390 // Check that input bit masks are valid and create the masks object
391 SkAutoTDelete<SkMasks>
392 masks(SkMasks::CreateMasks(inputMasks, bitsPerPixel));
393 if (NULL == masks) {
394 SkDebugf("Error: invalid input masks.\n");
395 return NULL;
396 }
397
398 // Process the color table
399 uint32_t colorBytes = 0;
400 SkPMColor* colorTable = NULL;
401 if (bitsPerPixel < 16) {
402 // Verify the number of colors for the color table
403 const uint32_t maxColors = 1 << bitsPerPixel;
404 // Zero is a default for maxColors
405 // Also set numColors to maxColors when input is too large
406 if (numColors <= 0 || numColors > maxColors) {
407 numColors = maxColors;
408 }
409 colorTable = SkNEW_ARRAY(SkPMColor, maxColors);
410
411 // Construct the color table
412 colorBytes = numColors * bytesPerColor;
413 SkAutoTDeleteArray<uint8_t> cBuffer(SkNEW_ARRAY(uint8_t, colorBytes));
414 if (stream->read(cBuffer.get(), colorBytes) != colorBytes) {
415 SkDebugf("Error: unable to read color table.\n");
416 return NULL;
417 }
418
419 // Fill in the color table (colors are stored unpremultiplied)
420 uint32_t i = 0;
421 for (; i < numColors; i++) {
422 uint8_t blue = get_byte(cBuffer.get(), i*bytesPerColor);
423 uint8_t green = get_byte(cBuffer.get(), i*bytesPerColor + 1);
424 uint8_t red = get_byte(cBuffer.get(), i*bytesPerColor + 2);
425 uint8_t alpha = 0xFF;
426 if (kOpaque_SkAlphaType != alphaType) {
427 alpha = (inputMasks.alpha >> 24) &
428 get_byte(cBuffer.get(), i*bytesPerColor + 3);
429 }
430 // Store the unpremultiplied color
431 colorTable[i] = SkPackARGB32NoCheck(alpha, red, green, blue);
432 }
433
434 // To avoid segmentation faults on bad pixel data, fill the end of the
435 // color table with black. This is the same the behavior as the
436 // chromium decoder.
437 for (; i < maxColors; i++) {
438 colorTable[i] = SkPackARGB32NoCheck(0xFF, 0, 0, 0);
439 }
440 }
441
442 // Ensure that the stream now points to the start of the pixel array
443 uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes + colorBytes;
444
445 // Check that we have not read past the pixel array offset
446 if(bytesRead > offset) {
447 // This may occur on OS 2.1 and other old versions where the color
448 // table defaults to max size, and the bmp tries to use a smaller color
449 // table. This is invalid, and our decision is to indicate an error,
450 // rather than try to guess the intended size of the color table and
451 // rewind the stream to display the image.
452 SkDebugf("Error: pixel data offset less than header size.\n");
453 return NULL;
454 }
455
456 // Skip to the start of the pixel array
457 if (stream->skip(offset - bytesRead) != offset - bytesRead) {
458 SkDebugf("Error: unable to skip to image data.\n");
459 return NULL;
460 }
461
462 // Remaining bytes is only used for RLE
463 const int remainingBytes = totalBytes - offset;
464 if (remainingBytes <= 0 && kRLE_BitmapInputFormat == inputFormat) {
465 SkDebugf("Error: RLE requires valid input size.\n");
466 return NULL;
467 }
468
469 // Return the codec
470 // We will use ImageInfo to store width, height, and alpha type. We will
471 // choose kN32_SkColorType as the input color type because that is the
472 // expected choice for a destination color type. In reality, the input
473 // color type has many possible formats.
474 const SkImageInfo& imageInfo = SkImageInfo::Make(width, height,
475 kN32_SkColorType, alphaType);
476 return SkNEW_ARGS(SkBmpCodec, (imageInfo, stream, bitsPerPixel,
477 inputFormat, masks.detach(), colorTable,
478 rowOrder, remainingBytes));
479 }
480
481 /*
482 *
483 * Creates an instance of the decoder
484 * Called only by NewFromStream
485 *
486 */
487 SkBmpCodec::SkBmpCodec(const SkImageInfo& info, SkStream* stream,
488 uint16_t bitsPerPixel, BitmapInputFormat inputFormat,
489 SkMasks* masks, SkPMColor* colorTable,
490 RowOrder rowOrder,
491 const uint32_t remainingBytes)
492 : INHERITED(info, stream)
493 , fBitsPerPixel(bitsPerPixel)
494 , fInputFormat(inputFormat)
495 , fMasks(masks)
496 , fColorTable(colorTable)
497 , fRowOrder(rowOrder)
498 , fRemainingBytes(remainingBytes)
499 {}
500
501 /*
502 *
503 * Initiates the bitmap decode
504 *
505 */
506 SkCodec::Result SkBmpCodec::onGetPixels(const SkImageInfo& dstInfo,
507 void* dst, size_t dstRowBytes,
508 SkPMColor*, int*) {
509 if (!this->rewindIfNeeded()) {
510 return kCouldNotRewind;
511 }
512 if (dstInfo.dimensions() != this->getOriginalInfo().dimensions()) {
513 SkDebugf("Error: scaling not supported.\n");
514 return kInvalidScale;
515 }
516 if (!conversion_possible(dstInfo, this->getOriginalInfo())) {
517 SkDebugf("Error: cannot convert input type to output type.\n");
518 return kInvalidConversion;
519 }
520
521 switch (fInputFormat) {
522 case kBitMask_BitmapInputFormat:
523 return decodeMask(dstInfo, dst, dstRowBytes);
524 case kRLE_BitmapInputFormat:
525 return decodeRLE(dstInfo, dst, dstRowBytes);
526 case kStandard_BitmapInputFormat:
527 return decode(dstInfo, dst, dstRowBytes);
528 default:
529 SkASSERT(false);
530 return kInvalidInput;
531 }
532 }
533
534 /*
535 *
536 * Performs the bitmap decoding for bit masks input format
537 *
538 */
539 SkCodec::Result SkBmpCodec::decodeMask(const SkImageInfo& dstInfo,
540 void* dst, uint32_t dstRowBytes) {
541 // Set constant values
542 const int width = dstInfo.width();
543 const int height = dstInfo.height();
544 const size_t rowBytes = SkAlign4(compute_row_bytes(width, fBitsPerPixel));
545
546 // Allocate space for a row buffer and a source for the swizzler
547 SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, rowBytes));
548
549 // Get the destination start row and delta
550 SkPMColor* dstRow;
551 int32_t delta;
552 if (kTopDown_RowOrder == fRowOrder) {
553 dstRow = (SkPMColor*) dst;
554 delta = dstRowBytes;
555 } else {
556 dstRow = (SkPMColor*) SkTAddOffset<void>(dst, (height-1) * dstRowBytes);
557 delta = -dstRowBytes;
558 }
559
560 // Create the swizzler
561 SkMaskSwizzler* swizzler = SkMaskSwizzler::CreateMaskSwizzler(
562 dstInfo, fMasks, fBitsPerPixel);
563
564 // Iterate over rows of the image
565 // FIXME: bool transparent = true;
566 for (int y = 0; y < height; y++) {
567 // Read a row of the input
568 if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) {
569 SkDebugf("Warning: incomplete input stream.\n");
570 return kIncompleteInput;
571 }
572
573 // Decode the row in destination format
574 swizzler->next(dstRow, srcBuffer.get());
575 // FIXME: SkSwizzler::ResultAlpha r =
576 // swizzler->next(dstRow, srcBuffer.get());
577 // FIXME: transparent &= SkSwizzler::IsTransparent(r);
scroggo 2015/03/13 15:04:46 Are we still using IsTransparent anywhere?
msarett 2015/03/13 15:21:15 It works and it's necessary for one of the test im
578
579 // Move to the next row
580 dstRow = SkTAddOffset<SkPMColor>(dstRow, delta);
581 }
582
583 // FIXME: This code exists to match the behavior in the chromium decoder
584 // and to correct for images with questionable formats. We have one test
585 // image that will wrongly be displayed fully transparent without this
586 // code.
587 // The image is called "32 bit 888 bitfield version 4" and is located at
588 // http://pxd.me/dompdf/www/test/image_bmp.html.
scroggo 2015/03/13 15:04:46 nit: I'm wary of posting links to the websites we'
msarett 2015/03/13 15:21:16 Good to know in the future. Since we are in fact
589
590 // Some fully transparent bmp images are intended to be opaque. Here, we
591 // correct for this possibility.
592 /*
593 dstRow = (SkPMColor*) dst;
594 if (transparent) {
595 for (int y = 0; y < height; y++) {
596 for (int x = 0; x < width; x++) {
597 dstRow[x] |= 0xFF000000;
598 }
599 dstRow = SkTAddOffset<SkPMColor>(dstRow, dstRowBytes);
600 }
601 }
602 */
603
604 // Finished decoding the entire image
605 return kSuccess;
606 }
607
608 /*
609 *
610 * Set an RLE pixel using the color table
611 *
612 */
613 void SkBmpCodec::setRLEPixel(SkPMColor* dst, uint32_t dstRowBytes, int height,
614 uint32_t x, uint32_t y, uint8_t index) {
615 if (kBottomUp_RowOrder == fRowOrder) {
616 y = height - y - 1;
617 }
618 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, y * dstRowBytes);
619 dstRow[x] = fColorTable.get()[index];
620 }
621
622 /*
623 *
624 * Performs the bitmap decoding for RLE input format
625 * RLE decoding is performed all at once, rather than a one row at a time
626 *
627 */
628 SkCodec::Result SkBmpCodec::decodeRLE(const SkImageInfo& dstInfo,
629 void* dst, uint32_t dstRowBytes) {
630 // Set RLE flags
631 static const uint8_t RLE_ESCAPE = 0;
632 static const uint8_t RLE_EOL = 0;
633 static const uint8_t RLE_EOF = 1;
634 static const uint8_t RLE_DELTA = 2;
635
636 // Set constant values
637 const int width = dstInfo.width();
638 const int height = dstInfo.height();
639
640 // Input buffer parameters
641 uint32_t currByte = 0;
642 SkAutoTDeleteArray<uint8_t> buffer(SkNEW_ARRAY(uint8_t, fRemainingBytes));
643 uint32_t totalBytes = stream()->read(buffer.get(), fRemainingBytes);
644 if (totalBytes < fRemainingBytes) {
645 SkDebugf("Warning: incomplete RLE file.\n");
646 } else if (totalBytes <= 0) {
647 SkDebugf("Error: could not read RLE image data.\n");
648 return kInvalidInput;
649 }
650
651 // Destination parameters
652 int x = 0;
653 int y = 0;
654 // If the code skips pixels, remaining pixels are transparent or black
655 // TODO: Skip this if memory was already zeroed.
656 memset(dst, 0, dstRowBytes * height);
657 SkPMColor* dstPtr = (SkPMColor*) dst;
658
659 while (true) {
660 // Every entry takes at least two bytes
661 if (totalBytes - currByte < 2) {
662 SkDebugf("Warning: incomplete RLE input.\n");
663 return kIncompleteInput;
664 }
665
666 // Read the next two bytes. These bytes have different meanings
667 // depending on their values. In the first interpretation, the first
668 // byte is an escape flag and the second byte indicates what special
669 // task to perform.
670 const uint8_t flag = buffer.get()[currByte++];
671 const uint8_t task = buffer.get()[currByte++];
672
673 // If we have reached a row that is beyond the image size, and the RLE
674 // code does not indicate end of file, abort and signal a warning.
675 if (y >= height && (flag != RLE_ESCAPE || (task != RLE_EOF))) {
676 SkDebugf("Warning: invalid RLE input.\n");
677 return kIncompleteInput;
678 }
679
680 // Perform decoding
681 if (RLE_ESCAPE == flag) {
682 switch (task) {
683 case RLE_EOL:
684 x = 0;
685 y++;
686 break;
687 case RLE_EOF:
688 return kSuccess;
689 case RLE_DELTA: {
690 // Two bytes are needed to specify delta
691 if (totalBytes - currByte < 2) {
692 SkDebugf("Warning: incomplete RLE input\n");
693 return kIncompleteInput;
694 }
695 // Modify x and y
696 const uint8_t dx = buffer.get()[currByte++];
697 const uint8_t dy = buffer.get()[currByte++];
698 x += dx;
699 y += dy;
700 if (x > width || y > height) {
701 SkDebugf("Warning: invalid RLE input.\n");
702 return kIncompleteInput;
703 }
704 break;
705 }
706 default: {
707 // If task does not match any of the above signals, it
708 // indicates that we have a sequence of non-RLE pixels.
709 // Furthermore, the value of task is equal to the number
710 // of pixels to interpret.
711 uint8_t numPixels = task;
712 const size_t rowBytes = compute_row_bytes(numPixels,
713 fBitsPerPixel);
714 // Abort if setting numPixels moves us off the edge of the
715 // image. Also abort if there are not enough bytes
716 // remaining in the stream to set numPixels.
717 if (x + numPixels > width ||
718 totalBytes - currByte < SkAlign2(rowBytes)) {
719 SkDebugf("Warning: invalid RLE input.\n");
720 return kIncompleteInput;
721 }
722 // Set numPixels number of pixels
723 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(
724 dstPtr, y * dstRowBytes);
725 while (numPixels > 0) {
726 switch(fBitsPerPixel) {
727 case 4: {
728 SkASSERT(currByte < totalBytes);
729 uint8_t val = buffer.get()[currByte++];
730 setRLEPixel(dstPtr, dstRowBytes, height, x++, y,
731 val >> 4);
732 numPixels--;
733 if (numPixels != 0) {
734 setRLEPixel(dstPtr, dstRowBytes, height,
735 x++, y, val & 0xF);
736 numPixels--;
737 }
738 break;
739 }
740 case 8:
741 SkASSERT(currByte < totalBytes);
742 setRLEPixel(dstPtr, dstRowBytes, height, x++, y,
743 buffer.get()[currByte++]);
744 numPixels--;
745 break;
746 case 24: {
747 SkASSERT(currByte + 2 < totalBytes);
748 uint8_t blue = buffer.get()[currByte++];
749 uint8_t green = buffer.get()[currByte++];
750 uint8_t red = buffer.get()[currByte++];
751 SkPMColor color = SkPackARGB32NoCheck(
752 0xFF, red, green, blue);
753 dstRow[x++] = color;
754 numPixels--;
755 }
756 default:
757 SkASSERT(false);
758 return kInvalidInput;
759 }
760 }
761 // Skip a byte if necessary to maintain alignment
762 if (!SkIsAlign2(rowBytes)) {
763 currByte++;
764 }
765 break;
766 }
767 }
768 } else {
769 // If the first byte read is not a flag, it indicates the number of
770 // pixels to set in RLE mode.
771 const uint8_t numPixels = flag;
772 const int endX = SkTMin<int>(x + numPixels, width);
773
774 if (24 == fBitsPerPixel) {
775 // In RLE24, the second byte read is part of the pixel color.
776 // There are two more required bytes to finish encoding the
777 // color.
778 if (totalBytes - currByte < 2) {
779 SkDebugf("Warning: incomplete RLE input\n");
780 return kIncompleteInput;
781 }
782
783 // Fill the pixels up to endX with the specified color
784 uint8_t blue = task;
785 uint8_t green = buffer.get()[currByte++];
786 uint8_t red = buffer.get()[currByte++];
787 SkPMColor color = SkPackARGB32NoCheck(0xFF, red, green, blue);
788 SkPMColor* dstRow =
789 SkTAddOffset<SkPMColor>(dstPtr, y * dstRowBytes);
790 while (x < endX) {
791 dstRow[x++] = color;
792 }
793 } else {
794 // In RLE8 or RLE4, the second byte read gives the index in the
795 // color table to look up the pixel color.
796 // RLE8 has one color index that gets repeated
797 // RLE4 has two color indexes in the upper and lower 4 bits of
798 // the bytes, which are alternated
799 uint8_t indices[2] = { task, task };
800 if (4 == fBitsPerPixel) {
801 indices[0] >>= 4;
802 indices[1] &= 0xf;
803 }
804
805 // Set the indicated number of pixels
806 for (int which = 0; x < endX; x++) {
807 setRLEPixel(dstPtr, dstRowBytes, height, x, y,
808 indices[which]);
809 which = !which;
810 }
811 }
812 }
813 }
814 }
815
816 /*
817 *
818 * Performs the bitmap decoding for standard input format
819 *
820 */
821 SkCodec::Result SkBmpCodec::decode(const SkImageInfo& dstInfo,
822 void* dst, uint32_t dstRowBytes) {
823 // Set constant values
824 const int width = dstInfo.width();
825 const int height = dstInfo.height();
826 const size_t rowBytes = SkAlign4(compute_row_bytes(width, fBitsPerPixel));
827 const uint32_t alphaMask = fMasks->getAlphaMask();
828
829 // Get swizzler configuration
830 SkSwizzler::SrcConfig config;
831 switch (fBitsPerPixel) {
832 case 1:
833 config = SkSwizzler::kIndex1;
834 break;
835 case 2:
836 config = SkSwizzler::kIndex2;
837 break;
838 case 4:
839 config = SkSwizzler::kIndex4;
840 break;
841 case 8:
842 config = SkSwizzler::kIndex;
843 break;
844 case 24:
845 config = SkSwizzler::kBGR;
846 break;
847 case 32:
848 if (0 == alphaMask) {
849 config = SkSwizzler::kBGRX;
850 } else {
851 config = SkSwizzler::kBGRA;
852 }
853 break;
854 default:
855 SkASSERT(false);
856 return kInvalidInput;
857 }
858
859 // Create swizzler
860 SkSwizzler* swizzler = SkSwizzler::CreateSwizzler(config, fColorTable.get(),
861 dstInfo, dst, dstRowBytes, false);
862
863 // Allocate space for a row buffer and a source for the swizzler
864 SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, rowBytes));
865
866 // Iterate over rows of the image
867 // FIXME: bool transparent = true;
868 for (int y = 0; y < height; y++) {
869 // Read a row of the input
870 if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) {
871 SkDebugf("Warning: incomplete input stream.\n");
872 return kIncompleteInput;
873 }
874
875 // Decode the row in destination format
876 uint32_t row;
877 if (kTopDown_RowOrder == fRowOrder) {
878 row = y;
879 } else {
880 row = height - 1 - y;
881 }
882
883 swizzler->next(srcBuffer.get(), row);
884 // FIXME: SkSwizzler::ResultAlpha r =
885 // swizzler->next(srcBuffer.get(), row);
886 // FIXME: transparent &= SkSwizzler::IsTransparent(r);
887 }
888
889 // FIXME: This code exists to match the behavior in the chromium decoder
890 // and to follow the bmp specification as it relates to alpha masks. It is
891 // commented out because we have yet to discover a test image that provides
892 // an alpha mask and uses this decode mode.
893
894 // Now we adjust the output image with some additional behavior that
895 // SkSwizzler does not support. Firstly, all bmp images that contain
896 // alpha are masked by the alpha mask. Secondly, many fully transparent
897 // bmp images are intended to be opaque. Here, we make those corrections.
898 // Modifying alpha is safe because colors are stored unpremultiplied.
899 /*
900 SkPMColor* dstRow = (SkPMColor*) dst;
901 if (SkSwizzler::kBGRA == config) {
902 for (int y = 0; y < height; y++) {
903 for (int x = 0; x < width; x++) {
904 if (transparent) {
905 dstRow[x] |= 0xFF000000;
906 } else {
907 dstRow[x] &= alphaMask;
908 }
909 dstRow = SkTAddOffset<SkPMColor>(dstRow, dstRowBytes);
910 }
911 }
912 }
913 */
914
915 // Finished decoding the entire image
916 return kSuccess;
917 }
OLDNEW
« no previous file with comments | « src/codec/SkCodec_libbmp.h ('k') | src/codec/SkCodec_libpng.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698