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

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

Issue 1022843005: Revert of Enabling ico decoding with use of png and bmp decoders (Closed) Base URL: https://skia.googlesource.com/skia.git@swizzle
Patch Set: 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_libico.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2015 Google Inc. 2 * Copyright 2015 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkCodec_libbmp.h" 8 #include "SkCodec_libbmp.h"
9 #include "SkCodecPriv.h" 9 #include "SkCodecPriv.h"
10 #include "SkColorPriv.h" 10 #include "SkColorPriv.h"
(...skipping 11 matching lines...) Expand all
22 if (dst.profileType() != src.profileType()) { 22 if (dst.profileType() != src.profileType()) {
23 return false; 23 return false;
24 } 24 }
25 25
26 // Check for supported color and alpha types 26 // Check for supported color and alpha types
27 switch (dst.colorType()) { 27 switch (dst.colorType()) {
28 case kN32_SkColorType: 28 case kN32_SkColorType:
29 return src.alphaType() == dst.alphaType() || 29 return src.alphaType() == dst.alphaType() ||
30 (kPremul_SkAlphaType == dst.alphaType() && 30 (kPremul_SkAlphaType == dst.alphaType() &&
31 kUnpremul_SkAlphaType == src.alphaType()); 31 kUnpremul_SkAlphaType == src.alphaType());
32 case kRGB_565_SkColorType:
33 return src.alphaType() == dst.alphaType() &&
34 kOpaque_SkAlphaType == dst.alphaType();
32 default: 35 default:
33 return false; 36 return false;
34 } 37 }
35 } 38 }
36 39
37 /* 40 /*
38 * 41 *
39 * Defines the version and type of the second bitmap header 42 * Defines the version and type of the second bitmap header
40 * 43 *
41 */ 44 */
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 // TODO: ICO files may contain a BMP and need to use this decoder 81 // TODO: ICO files may contain a BMP and need to use this decoder
79 const char bmpSig[] = { 'B', 'M' }; 82 const char bmpSig[] = { 'B', 'M' };
80 char buffer[sizeof(bmpSig)]; 83 char buffer[sizeof(bmpSig)];
81 return stream->read(buffer, sizeof(bmpSig)) == sizeof(bmpSig) && 84 return stream->read(buffer, sizeof(bmpSig)) == sizeof(bmpSig) &&
82 !memcmp(buffer, bmpSig, sizeof(bmpSig)); 85 !memcmp(buffer, bmpSig, sizeof(bmpSig));
83 } 86 }
84 87
85 /* 88 /*
86 * 89 *
87 * Assumes IsBmp was called and returned true 90 * Assumes IsBmp was called and returned true
88 * Creates a bmp decoder 91 * Creates a bitmap decoder
89 * Reads enough of the stream to determine the image format 92 * Reads enough of the stream to determine the image format
90 * 93 *
91 */ 94 */
92 SkCodec* SkBmpCodec::NewFromStream(SkStream* stream) { 95 SkCodec* SkBmpCodec::NewFromStream(SkStream* stream) {
93 return SkBmpCodec::NewFromStream(stream, false);
94 }
95
96 /*
97 *
98 * Creates a bmp decoder for a bmp embedded in ico
99 * Reads enough of the stream to determine the image format
100 *
101 */
102 SkCodec* SkBmpCodec::NewFromIco(SkStream* stream) {
103 return SkBmpCodec::NewFromStream(stream, true);
104 }
105
106 /*
107 *
108 * Creates a bmp decoder
109 * Reads enough of the stream to determine the image format
110 *
111 */
112 SkCodec* SkBmpCodec::NewFromStream(SkStream* stream, bool isIco) {
113 // Header size constants 96 // Header size constants
114 static const uint32_t kBmpHeaderBytes = 14; 97 static const uint32_t kBmpHeaderBytes = 14;
115 static const uint32_t kBmpHeaderBytesPlusFour = kBmpHeaderBytes + 4; 98 static const uint32_t kBmpHeaderBytesPlusFour = kBmpHeaderBytes + 4;
116 static const uint32_t kBmpOS2V1Bytes = 12; 99 static const uint32_t kBmpOS2V1Bytes = 12;
117 static const uint32_t kBmpOS2V2Bytes = 64; 100 static const uint32_t kBmpOS2V2Bytes = 64;
118 static const uint32_t kBmpInfoBaseBytes = 16; 101 static const uint32_t kBmpInfoBaseBytes = 16;
119 static const uint32_t kBmpInfoV1Bytes = 40; 102 static const uint32_t kBmpInfoV1Bytes = 40;
120 static const uint32_t kBmpInfoV2Bytes = 52; 103 static const uint32_t kBmpInfoV2Bytes = 52;
121 static const uint32_t kBmpInfoV3Bytes = 56; 104 static const uint32_t kBmpInfoV3Bytes = 56;
122 static const uint32_t kBmpInfoV4Bytes = 108; 105 static const uint32_t kBmpInfoV4Bytes = 108;
123 static const uint32_t kBmpInfoV5Bytes = 124; 106 static const uint32_t kBmpInfoV5Bytes = 124;
124 static const uint32_t kBmpMaskBytes = 12; 107 static const uint32_t kBmpMaskBytes = 12;
125 108
126 // The total bytes in the bmp file 109 // Read the first header and the size of the second header
127 // We only need to use this value for RLE decoding, so we will only 110 SkAutoTDeleteArray<uint8_t> hBuffer(
128 // check that it is valid in the RLE case. 111 SkNEW_ARRAY(uint8_t, kBmpHeaderBytesPlusFour));
129 uint32_t totalBytes; 112 if (stream->read(hBuffer.get(), kBmpHeaderBytesPlusFour) !=
130 // The offset from the start of the file where the pixel data begins 113 kBmpHeaderBytesPlusFour) {
131 uint32_t offset; 114 SkDebugf("Error: unable to read first bitmap header.\n");
132 // The size of the second (info) header in bytes 115 return NULL;
133 uint32_t infoBytes;
134
135 // Bmps embedded in Icos skip the first Bmp header
136 if (!isIco) {
137 // Read the first header and the size of the second header
138 SkAutoTDeleteArray<uint8_t> hBuffer(
139 SkNEW_ARRAY(uint8_t, kBmpHeaderBytesPlusFour));
140 if (stream->read(hBuffer.get(), kBmpHeaderBytesPlusFour) !=
141 kBmpHeaderBytesPlusFour) {
142 SkDebugf("Error: unable to read first bitmap header.\n");
143 return NULL;
144 }
145
146 totalBytes = get_int(hBuffer.get(), 2);
147 offset = get_int(hBuffer.get(), 10);
148 if (offset < kBmpHeaderBytes + kBmpOS2V1Bytes) {
149 SkDebugf("Error: invalid starting location for pixel data\n");
150 return NULL;
151 }
152
153 // The size of the second (info) header in bytes
154 // The size is the first field of the second header, so we have already
155 // read the first four infoBytes.
156 infoBytes = get_int(hBuffer.get(), 14);
157 if (infoBytes < kBmpOS2V1Bytes) {
158 SkDebugf("Error: invalid second header size.\n");
159 return NULL;
160 }
161 } else {
162 // This value is only used by RLE compression. Bmp in Ico files do not
163 // use RLE. If the compression field is incorrectly signaled as RLE,
164 // we will catch this and signal an error below.
165 totalBytes = 0;
166
167 // Bmps in Ico cannot specify an offset. We will always assume that
168 // pixel data begins immediately after the color table. This value
169 // will be corrected below.
170 offset = 0;
171
172 // Read the size of the second header
173 SkAutoTDeleteArray<uint8_t> hBuffer(
174 SkNEW_ARRAY(uint8_t, 4));
175 if (stream->read(hBuffer.get(), 4) != 4) {
176 SkDebugf("Error: unable to read size of second bitmap header.\n");
177 return NULL;
178 }
179 infoBytes = get_int(hBuffer.get(), 0);
180 if (infoBytes < kBmpOS2V1Bytes) {
181 SkDebugf("Error: invalid second header size.\n");
182 return NULL;
183 }
184 } 116 }
185 117
186 // We already read the first four bytes of the info header to get the size 118 // The total bytes in the bmp file
119 // We only need to use this value for RLE decoding, so we will only check
120 // that it is valid in the RLE case.
121 const uint32_t totalBytes = get_int(hBuffer.get(), 2);
122
123 // The offset from the start of the file where the pixel data begins
124 const uint32_t offset = get_int(hBuffer.get(), 10);
125 if (offset < kBmpHeaderBytes + kBmpOS2V1Bytes) {
126 SkDebugf("Error: invalid starting location for pixel data\n");
127 return NULL;
128 }
129
130 // The size of the second (info) header in bytes
131 // The size is the first field of the second header, so we have already
132 // read the first four infoBytes.
133 const uint32_t infoBytes = get_int(hBuffer.get(), 14);
134 if (infoBytes < kBmpOS2V1Bytes) {
135 SkDebugf("Error: invalid second header size.\n");
136 return NULL;
137 }
187 const uint32_t infoBytesRemaining = infoBytes - 4; 138 const uint32_t infoBytesRemaining = infoBytes - 4;
139 hBuffer.free();
188 140
189 // Read the second header 141 // Read the second header
190 SkAutoTDeleteArray<uint8_t> iBuffer( 142 SkAutoTDeleteArray<uint8_t> iBuffer(
191 SkNEW_ARRAY(uint8_t, infoBytesRemaining)); 143 SkNEW_ARRAY(uint8_t, infoBytesRemaining));
192 if (stream->read(iBuffer.get(), infoBytesRemaining) != infoBytesRemaining) { 144 if (stream->read(iBuffer.get(), infoBytesRemaining) != infoBytesRemaining) {
193 SkDebugf("Error: unable to read second bitmap header.\n"); 145 SkDebugf("Error: unable to read second bitmap header.\n");
194 return NULL; 146 return NULL;
195 } 147 }
196 148
197 // The number of bits used per pixel in the pixel data 149 // The number of bits used per pixel in the pixel data
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
284 SkDebugf("Error: second bitmap header size is invalid.\n"); 236 SkDebugf("Error: second bitmap header size is invalid.\n");
285 return NULL; 237 return NULL;
286 } 238 }
287 239
288 // Check for valid dimensions from header 240 // Check for valid dimensions from header
289 RowOrder rowOrder = kBottomUp_RowOrder; 241 RowOrder rowOrder = kBottomUp_RowOrder;
290 if (height < 0) { 242 if (height < 0) {
291 height = -height; 243 height = -height;
292 rowOrder = kTopDown_RowOrder; 244 rowOrder = kTopDown_RowOrder;
293 } 245 }
294 // The height field for bmp in ico is double the actual height because they
295 // contain an XOR mask followed by an AND mask
296 if (isIco) {
297 height /= 2;
298 }
299 static const int kBmpMaxDim = 1 << 16; 246 static const int kBmpMaxDim = 1 << 16;
300 if (width < 0 || width >= kBmpMaxDim || height >= kBmpMaxDim) { 247 if (width < 0 || width >= kBmpMaxDim || height >= kBmpMaxDim) {
301 // TODO: Decide if we want to support really large bmps. 248 // TODO: Decide if we want to support really large bmps.
302 SkDebugf("Error: invalid bitmap dimensions.\n"); 249 SkDebugf("Error: invalid bitmap dimensions.\n");
303 return NULL; 250 return NULL;
304 } 251 }
305 252
306 // Create mask struct 253 // Create mask struct
307 SkMasks::InputMasks inputMasks; 254 SkMasks::InputMasks inputMasks;
308 memset(&inputMasks, 0, sizeof(SkMasks::InputMasks)); 255 memset(&inputMasks, 0, sizeof(SkMasks::InputMasks));
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
390 // TODO: Same as above. 337 // TODO: Same as above.
391 SkDebugf("Error: CMYK not supported for bitmap decoding.\n"); 338 SkDebugf("Error: CMYK not supported for bitmap decoding.\n");
392 return NULL; 339 return NULL;
393 default: 340 default:
394 SkDebugf("Error: invalid format for bitmap decoding.\n"); 341 SkDebugf("Error: invalid format for bitmap decoding.\n");
395 return NULL; 342 return NULL;
396 } 343 }
397 344
398 // Most versions of bmps should be rendered as opaque. Either they do 345 // Most versions of bmps should be rendered as opaque. Either they do
399 // not have an alpha channel, or they expect the alpha channel to be 346 // not have an alpha channel, or they expect the alpha channel to be
400 // ignored. V3+ bmp files introduce an alpha mask and allow the creator 347 // ignored. V4+ bmp files introduce an alpha mask and allow the creator
401 // of the image to use the alpha channels. However, many of these images 348 // of the image to use the alpha channels. However, many of these images
402 // leave the alpha channel blank and expect to be rendered as opaque. This 349 // leave the alpha channel blank and expect to be rendered as opaque. For
403 // is the case for almost all V3 images, so we render these as opaque. For 350 // this reason, we set the alpha type to kUnknown for V4+ bmps and figure
404 // V4+, we will use the alpha channel, and fix the image later if it turns 351 // out the alpha type during the decode.
405 // out to be fully transparent.
406 // As an exception, V3 bmp-in-ico may use an alpha mask.
407 SkAlphaType alphaType = kOpaque_SkAlphaType; 352 SkAlphaType alphaType = kOpaque_SkAlphaType;
408 if ((kInfoV3_BitmapHeaderType == headerType && isIco) || 353 if (kInfoV4_BitmapHeaderType == headerType ||
409 kInfoV4_BitmapHeaderType == headerType ||
410 kInfoV5_BitmapHeaderType == headerType) { 354 kInfoV5_BitmapHeaderType == headerType) {
411 // Header types are matched based on size. If the header is 355 // Header types are matched based on size. If the header is
412 // V3+, we are guaranteed to be able to read at least this size. 356 // V4+, we are guaranteed to be able to read at least this size.
413 SkASSERT(infoBytesRemaining > 52); 357 SkASSERT(infoBytesRemaining > 52);
414 inputMasks.alpha = get_int(iBuffer.get(), 48); 358 inputMasks.alpha = get_int(iBuffer.get(), 48);
415 if (inputMasks.alpha != 0) { 359 if (inputMasks.alpha != 0) {
416 alphaType = kUnpremul_SkAlphaType; 360 alphaType = kUnpremul_SkAlphaType;
417 } 361 }
418 } 362 }
419 iBuffer.free(); 363 iBuffer.free();
420 364
421 // Additionally, 32 bit bmp-in-icos use the alpha channel
422 if (isIco && 32 == bitsPerPixel) {
423 alphaType = kUnpremul_SkAlphaType;
424 }
425
426 // Check for valid bits per pixel input 365 // Check for valid bits per pixel input
427 switch (bitsPerPixel) { 366 switch (bitsPerPixel) {
428 // In addition to more standard pixel compression formats, bmp supports 367 // In addition to more standard pixel compression formats, bmp supports
429 // the use of bit masks to determine pixel components. The standard 368 // the use of bit masks to determine pixel components. The standard
430 // format for representing 16-bit colors is 555 (XRRRRRGGGGGBBBBB), 369 // format for representing 16-bit colors is 555 (XRRRRRGGGGGBBBBB),
431 // which does not map well to any Skia color formats. For this reason, 370 // which does not map well to any Skia color formats. For this reason,
432 // we will always enable mask mode with 16 bits per pixel. 371 // we will always enable mask mode with 16 bits per pixel.
433 case 16: 372 case 16:
434 if (kBitMask_BitmapInputFormat != inputFormat) { 373 if (kBitMask_BitmapInputFormat != inputFormat) {
435 inputMasks.red = 0x7C00; 374 inputMasks.red = 0x7C00;
(...skipping 24 matching lines...) Expand all
460 399
461 // Check for a valid number of total bytes when in RLE mode 400 // Check for a valid number of total bytes when in RLE mode
462 if (totalBytes <= offset && kRLE_BitmapInputFormat == inputFormat) { 401 if (totalBytes <= offset && kRLE_BitmapInputFormat == inputFormat) {
463 SkDebugf("Error: RLE requires valid input size.\n"); 402 SkDebugf("Error: RLE requires valid input size.\n");
464 return NULL; 403 return NULL;
465 } 404 }
466 const size_t RLEBytes = totalBytes - offset; 405 const size_t RLEBytes = totalBytes - offset;
467 406
468 // Calculate the number of bytes read so far 407 // Calculate the number of bytes read so far
469 const uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes; 408 const uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes;
470 if (!isIco && offset < bytesRead) { 409 if (offset < bytesRead) {
471 SkDebugf("Error: pixel data offset less than header size.\n"); 410 SkDebugf("Error: pixel data offset less than header size.\n");
472 return NULL; 411 return NULL;
473 } 412 }
474 413
475 // Return the codec 414 // Return the codec
476 // We will use ImageInfo to store width, height, and alpha type. We will 415 // We will use ImageInfo to store width, height, and alpha type. We will
477 // set color type to kN32_SkColorType because that should be the default 416 // set color type to kN32_SkColorType because that should be the default
478 // output. 417 // output.
479 const SkImageInfo& imageInfo = SkImageInfo::Make(width, height, 418 const SkImageInfo& imageInfo = SkImageInfo::Make(width, height,
480 kN32_SkColorType, alphaType); 419 kN32_SkColorType, alphaType);
481 return SkNEW_ARGS(SkBmpCodec, (imageInfo, stream, bitsPerPixel, 420 return SkNEW_ARGS(SkBmpCodec, (imageInfo, stream, bitsPerPixel,
482 inputFormat, masks.detach(), numColors, 421 inputFormat, masks.detach(), numColors,
483 bytesPerColor, offset - bytesRead, 422 bytesPerColor, offset - bytesRead,
484 rowOrder, RLEBytes, isIco)); 423 rowOrder, RLEBytes));
485 } 424 }
486 425
487 /* 426 /*
488 * 427 *
489 * Creates an instance of the decoder 428 * Creates an instance of the decoder
490 * Called only by NewFromStream 429 * Called only by NewFromStream
491 * 430 *
492 */ 431 */
493 SkBmpCodec::SkBmpCodec(const SkImageInfo& info, SkStream* stream, 432 SkBmpCodec::SkBmpCodec(const SkImageInfo& info, SkStream* stream,
494 uint16_t bitsPerPixel, BitmapInputFormat inputFormat, 433 uint16_t bitsPerPixel, BitmapInputFormat inputFormat,
495 SkMasks* masks, uint32_t numColors, 434 SkMasks* masks, uint32_t numColors,
496 uint32_t bytesPerColor, uint32_t offset, 435 uint32_t bytesPerColor, uint32_t offset,
497 RowOrder rowOrder, size_t RLEBytes, bool isIco) 436 RowOrder rowOrder, size_t RLEBytes)
498 : INHERITED(info, stream) 437 : INHERITED(info, stream)
499 , fBitsPerPixel(bitsPerPixel) 438 , fBitsPerPixel(bitsPerPixel)
500 , fInputFormat(inputFormat) 439 , fInputFormat(inputFormat)
501 , fMasks(masks) 440 , fMasks(masks)
502 , fColorTable(NULL) 441 , fColorTable(NULL)
503 , fNumColors(numColors) 442 , fNumColors(numColors)
504 , fBytesPerColor(bytesPerColor) 443 , fBytesPerColor(bytesPerColor)
505 , fOffset(offset) 444 , fOffset(offset)
506 , fRowOrder(rowOrder) 445 , fRowOrder(rowOrder)
507 , fRLEBytes(RLEBytes) 446 , fRLEBytes(RLEBytes)
508 , fIsIco(isIco)
509
510 {} 447 {}
511 448
512 /* 449 /*
513 * 450 *
514 * Initiates the bitmap decode 451 * Initiates the bitmap decode
515 * 452 *
516 */ 453 */
517 SkCodec::Result SkBmpCodec::onGetPixels(const SkImageInfo& dstInfo, 454 SkCodec::Result SkBmpCodec::onGetPixels(const SkImageInfo& dstInfo,
518 void* dst, size_t dstRowBytes, 455 void* dst, size_t dstRowBytes,
519 const Options&, 456 const Options&,
520 SkPMColor*, int*) { 457 SkPMColor*, int*) {
521 // Check for proper input and output formats 458 // Check for proper input and output formats
522 if (!this->rewindIfNeeded()) { 459 if (!this->rewindIfNeeded()) {
523 return kCouldNotRewind; 460 return kCouldNotRewind;
524 } 461 }
525 if (dstInfo.dimensions() != this->getInfo().dimensions()) { 462 if (dstInfo.dimensions() != this->getOriginalInfo().dimensions()) {
526 SkDebugf("Error: scaling not supported.\n"); 463 SkDebugf("Error: scaling not supported.\n");
527 return kInvalidScale; 464 return kInvalidScale;
528 } 465 }
529 if (!conversion_possible(dstInfo, this->getInfo())) { 466 if (!conversion_possible(dstInfo, this->getOriginalInfo())) {
530 SkDebugf("Error: cannot convert input type to output type.\n"); 467 SkDebugf("Error: cannot convert input type to output type.\n");
531 return kInvalidConversion; 468 return kInvalidConversion;
532 } 469 }
533 470
534 // Create the color table if necessary and prepare the stream for decode 471 // Create the color table if necessary and prepare the stream for decode
535 if (!createColorTable(dstInfo.alphaType())) { 472 if (!createColorTable(dstInfo.alphaType())) {
536 SkDebugf("Error: could not create color table.\n"); 473 SkDebugf("Error: could not create color table.\n");
537 return kInvalidInput; 474 return kInvalidInput;
538 } 475 }
539 476
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 } 546 }
610 547
611 // To avoid segmentation faults on bad pixel data, fill the end of the 548 // To avoid segmentation faults on bad pixel data, fill the end of the
612 // color table with black. This is the same the behavior as the 549 // color table with black. This is the same the behavior as the
613 // chromium decoder. 550 // chromium decoder.
614 for (; i < maxColors; i++) { 551 for (; i < maxColors; i++) {
615 colorTable[i] = SkPackARGB32NoCheck(0xFF, 0, 0, 0); 552 colorTable[i] = SkPackARGB32NoCheck(0xFF, 0, 0, 0);
616 } 553 }
617 } 554 }
618 555
619 // Bmp-in-Ico files do not use an offset to indicate where the pixel data 556 // Check that we have not read past the pixel array offset
620 // begins. Pixel data always begins immediately after the color table. 557 if(fOffset < colorBytes) {
621 if (!fIsIco) { 558 // This may occur on OS 2.1 and other old versions where the color
622 // Check that we have not read past the pixel array offset 559 // table defaults to max size, and the bmp tries to use a smaller color
623 if(fOffset < colorBytes) { 560 // table. This is invalid, and our decision is to indicate an error,
624 // This may occur on OS 2.1 and other old versions where the color 561 // rather than try to guess the intended size of the color table.
625 // table defaults to max size, and the bmp tries to use a smaller 562 SkDebugf("Error: pixel data offset less than color table size.\n");
626 // color table. This is invalid, and our decision is to indicate 563 return false;
627 // an error, rather than try to guess the intended size of the 564 }
628 // color table.
629 SkDebugf("Error: pixel data offset less than color table size.\n");
630 return false;
631 }
632 565
633 // After reading the color table, skip to the start of the pixel array 566 // After reading the color table, skip to the start of the pixel array
634 if (stream()->skip(fOffset - colorBytes) != fOffset - colorBytes) { 567 if (stream()->skip(fOffset - colorBytes) != fOffset - colorBytes) {
635 SkDebugf("Error: unable to skip to image data.\n"); 568 SkDebugf("Error: unable to skip to image data.\n");
636 return false; 569 return false;
637 }
638 } 570 }
639 571
640 // Set the color table and return true on success 572 // Set the color table and return true on success
641 fColorTable.reset(SkNEW_ARGS(SkColorTable, (colorTable, maxColors))); 573 if (maxColors > 0) {
574 fColorTable.reset(SkNEW_ARGS(SkColorTable, (colorTable, maxColors)));
575 }
642 return true; 576 return true;
643 } 577 }
644 578
645 /* 579 /*
646 * 580 *
647 * Performs the bitmap decoding for bit masks input format 581 * Performs the bitmap decoding for bit masks input format
648 * 582 *
649 */ 583 */
650 SkCodec::Result SkBmpCodec::decodeMask(const SkImageInfo& dstInfo, 584 SkCodec::Result SkBmpCodec::decodeMask(const SkImageInfo& dstInfo,
651 void* dst, size_t dstRowBytes) { 585 void* dst, size_t dstRowBytes) {
(...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after
1048 982
1049 // FIXME: This code exists to match the behavior in the chromium decoder 983 // FIXME: This code exists to match the behavior in the chromium decoder
1050 // and to follow the bmp specification as it relates to alpha masks. It is 984 // and to follow the bmp specification as it relates to alpha masks. It is
1051 // commented out because we have yet to discover a test image that provides 985 // commented out because we have yet to discover a test image that provides
1052 // an alpha mask and uses this decode mode. 986 // an alpha mask and uses this decode mode.
1053 987
1054 // Now we adjust the output image with some additional behavior that 988 // Now we adjust the output image with some additional behavior that
1055 // SkSwizzler does not support. Firstly, all bmp images that contain 989 // SkSwizzler does not support. Firstly, all bmp images that contain
1056 // alpha are masked by the alpha mask. Secondly, many fully transparent 990 // alpha are masked by the alpha mask. Secondly, many fully transparent
1057 // bmp images are intended to be opaque. Here, we make those corrections. 991 // bmp images are intended to be opaque. Here, we make those corrections.
992 // Modifying alpha is safe because colors are stored unpremultiplied.
1058 /* 993 /*
1059 SkPMColor* dstRow = (SkPMColor*) dst; 994 SkPMColor* dstRow = (SkPMColor*) dst;
1060 if (SkSwizzler::kBGRA == config) { 995 if (SkSwizzler::kBGRA == config) {
1061 for (int y = 0; y < height; y++) { 996 for (int y = 0; y < height; y++) {
1062 for (int x = 0; x < width; x++) { 997 for (int x = 0; x < width; x++) {
1063 if (transparent) { 998 if (transparent) {
1064 dstRow[x] |= 0xFF000000; 999 dstRow[x] |= 0xFF000000;
1065 } else { 1000 } else {
1066 dstRow[x] &= alphaMask; 1001 dstRow[x] &= alphaMask;
1067 } 1002 }
1068 dstRow = SkTAddOffset<SkPMColor>(dstRow, dstRowBytes); 1003 dstRow = SkTAddOffset<SkPMColor>(dstRow, dstRowBytes);
1069 } 1004 }
1070 } 1005 }
1071 } 1006 }
1072 */ 1007 */
1073 1008
1074 // Finally, apply the AND mask for bmp-in-ico images
1075 if (fIsIco) {
1076 // The AND mask is always 1 bit per pixel
1077 const size_t rowBytes = SkAlign4(compute_row_bytes(width, 1));
1078
1079 SkPMColor* dstPtr = (SkPMColor*) dst;
1080 for (int y = 0; y < height; y++) {
1081 // The srcBuffer will at least be large enough
1082 if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) {
1083 SkDebugf("Warning: incomplete AND mask for bmp-in-ico.\n");
1084 return kIncompleteInput;
1085 }
1086
1087 int row;
1088 if (kBottomUp_RowOrder == fRowOrder) {
1089 row = height - y - 1;
1090 } else {
1091 row = y;
1092 }
1093
1094 SkPMColor* dstRow =
1095 SkTAddOffset<SkPMColor>(dstPtr, row * dstRowBytes);
1096
1097 for (int x = 0; x < width; x++) {
1098 int quotient;
1099 int modulus;
1100 SkTDivMod(x, 8, &quotient, &modulus);
1101 uint32_t shift = 7 - modulus;
1102 uint32_t alphaBit =
1103 (srcBuffer.get()[quotient] >> shift) & 0x1;
1104 dstRow[x] &= alphaBit - 1;
1105 }
1106 }
1107 }
1108
1109 // Finished decoding the entire image 1009 // Finished decoding the entire image
1110 return kSuccess; 1010 return kSuccess;
1111 } 1011 }
OLDNEW
« no previous file with comments | « src/codec/SkCodec_libbmp.h ('k') | src/codec/SkCodec_libico.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698