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

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

Issue 1055743003: Swizzler changes Index8 and 565 (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Fix windows errors Created 5 years, 8 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_libgif.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"
11 #include "SkStream.h" 11 #include "SkStream.h"
12 #include "SkUtils.h"
12 13
13 /* 14 /*
14 * 15 *
15 * Checks if the conversion between the input image and the requested output 16 * Checks if the conversion between the input image and the requested output
16 * image has been implemented 17 * image has been implemented
17 * 18 *
18 */ 19 */
19 static bool conversion_possible(const SkImageInfo& dst, 20 static bool conversion_possible(const SkImageInfo& dst,
20 const SkImageInfo& src) { 21 const SkImageInfo& src) {
21 // Ensure that the profile type is unchanged 22 // Ensure that the profile type is unchanged
22 if (dst.profileType() != src.profileType()) { 23 if (dst.profileType() != src.profileType()) {
23 return false; 24 return false;
24 } 25 }
25 26
26 // Check for supported color and alpha types 27 // Check for supported alpha types
28 if (src.alphaType() != dst.alphaType()) {
29 if (kOpaque_SkAlphaType == src.alphaType()) {
30 // If the source is opaque, we must decode to opaque
31 return false;
32 }
33
34 // The source is not opaque
35 switch (dst.alphaType()) {
36 case kPremul_SkAlphaType:
37 case kUnpremul_SkAlphaType:
38 // The source is not opaque, so either of these is okay
39 break;
40 default:
41 // We cannot decode a non-opaque image to opaque (or unknown)
42 return false;
43 }
44 }
45
46 // Check for supported color types
27 switch (dst.colorType()) { 47 switch (dst.colorType()) {
48 // Allow output to kN32 from any type of input
28 case kN32_SkColorType: 49 case kN32_SkColorType:
29 return src.alphaType() == dst.alphaType() || 50 return true;
30 (kPremul_SkAlphaType == dst.alphaType() && 51 // Allow output to kIndex_8 from compatible inputs
31 kUnpremul_SkAlphaType == src.alphaType()); 52 case kIndex_8_SkColorType:
53 return kIndex_8_SkColorType == src.colorType();
32 default: 54 default:
33 return false; 55 return false;
34 } 56 }
35 } 57 }
36 58
37 /* 59 /*
38 * 60 *
39 * Defines the version and type of the second bitmap header 61 * Defines the version and type of the second bitmap header
40 * 62 *
41 */ 63 */
(...skipping 371 matching lines...) Expand 10 before | Expand all | Expand 10 after
413 // Header types are matched based on size. If the header is 435 // Header types are matched based on size. If the header is
414 // V3+, we are guaranteed to be able to read at least this size. 436 // V3+, we are guaranteed to be able to read at least this size.
415 SkASSERT(infoBytesRemaining > 52); 437 SkASSERT(infoBytesRemaining > 52);
416 inputMasks.alpha = get_int(iBuffer.get(), 48); 438 inputMasks.alpha = get_int(iBuffer.get(), 48);
417 if (inputMasks.alpha != 0) { 439 if (inputMasks.alpha != 0) {
418 alphaType = kUnpremul_SkAlphaType; 440 alphaType = kUnpremul_SkAlphaType;
419 } 441 }
420 } 442 }
421 iBuffer.free(); 443 iBuffer.free();
422 444
423 // Additionally, 32 bit bmp-in-icos use the alpha channel 445 // Additionally, 32 bit bmp-in-icos use the alpha channel.
424 if (isIco && 32 == bitsPerPixel) { 446 // And, RLE inputs may skip pixels, leaving them as transparent. This
447 // is uncommon, but we cannot be certain that an RLE bmp will be opaque.
448 if ((isIco && 32 == bitsPerPixel) || (kRLE_BitmapInputFormat == inputFormat) ) {
425 alphaType = kUnpremul_SkAlphaType; 449 alphaType = kUnpremul_SkAlphaType;
426 } 450 }
427 451
428 // Check for valid bits per pixel input 452 // Check for valid bits per pixel.
453 // At the same time, use this information to choose a suggested color type
454 // and to set default masks.
455 SkColorType colorType = kN32_SkColorType;
429 switch (bitsPerPixel) { 456 switch (bitsPerPixel) {
430 // In addition to more standard pixel compression formats, bmp supports 457 // In addition to more standard pixel compression formats, bmp supports
431 // the use of bit masks to determine pixel components. The standard 458 // the use of bit masks to determine pixel components. The standard
432 // format for representing 16-bit colors is 555 (XRRRRRGGGGGBBBBB), 459 // format for representing 16-bit colors is 555 (XRRRRRGGGGGBBBBB),
433 // which does not map well to any Skia color formats. For this reason, 460 // which does not map well to any Skia color formats. For this reason,
434 // we will always enable mask mode with 16 bits per pixel. 461 // we will always enable mask mode with 16 bits per pixel.
435 case 16: 462 case 16:
436 if (kBitMask_BitmapInputFormat != inputFormat) { 463 if (kBitMask_BitmapInputFormat != inputFormat) {
437 inputMasks.red = 0x7C00; 464 inputMasks.red = 0x7C00;
438 inputMasks.green = 0x03E0; 465 inputMasks.green = 0x03E0;
439 inputMasks.blue = 0x001F; 466 inputMasks.blue = 0x001F;
440 inputFormat = kBitMask_BitmapInputFormat; 467 inputFormat = kBitMask_BitmapInputFormat;
441 } 468 }
442 break; 469 break;
470 // We want to decode to kIndex_8 for input formats that are already
471 // designed in index format.
443 case 1: 472 case 1:
444 case 2: 473 case 2:
445 case 4: 474 case 4:
446 case 8: 475 case 8:
476 // However, we cannot in RLE format since we may need to leave some
477 // pixels as transparent. Similarly, we also cannot for ICO images
478 // since we may need to apply a transparent mask.
479 if (kRLE_BitmapInputFormat != inputFormat && !isIco) {
480 colorType = kIndex_8_SkColorType;
481 }
447 case 24: 482 case 24:
448 case 32: 483 case 32:
449 break; 484 break;
450 default: 485 default:
451 SkCodecPrintf("Error: invalid input value for bits per pixel.\n"); 486 SkCodecPrintf("Error: invalid input value for bits per pixel.\n");
452 return false; 487 return false;
453 } 488 }
454 489
455 // Check that input bit masks are valid and create the masks object 490 // Check that input bit masks are valid and create the masks object
456 SkAutoTDelete<SkMasks> 491 SkAutoTDelete<SkMasks>
(...skipping 12 matching lines...) Expand all
469 504
470 // Calculate the number of bytes read so far 505 // Calculate the number of bytes read so far
471 const uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes; 506 const uint32_t bytesRead = kBmpHeaderBytes + infoBytes + maskBytes;
472 if (!isIco && offset < bytesRead) { 507 if (!isIco && offset < bytesRead) {
473 SkCodecPrintf("Error: pixel data offset less than header size.\n"); 508 SkCodecPrintf("Error: pixel data offset less than header size.\n");
474 return false; 509 return false;
475 } 510 }
476 511
477 if (codecOut) { 512 if (codecOut) {
478 // Return the codec 513 // Return the codec
479 // We will use ImageInfo to store width, height, and alpha type. We 514 // We will use ImageInfo to store width, height, suggested color type, a nd
480 // will set color type to kN32_SkColorType because that should be the 515 // suggested alpha type.
481 // default output.
482 const SkImageInfo& imageInfo = SkImageInfo::Make(width, height, 516 const SkImageInfo& imageInfo = SkImageInfo::Make(width, height,
483 kN32_SkColorType, alphaType); 517 colorType, alphaType);
484 *codecOut = SkNEW_ARGS(SkBmpCodec, (imageInfo, stream, bitsPerPixel, 518 *codecOut = SkNEW_ARGS(SkBmpCodec, (imageInfo, stream, bitsPerPixel,
485 inputFormat, masks.detach(), 519 inputFormat, masks.detach(),
486 numColors, bytesPerColor, 520 numColors, bytesPerColor,
487 offset - bytesRead, rowOrder, 521 offset - bytesRead, rowOrder,
488 RLEBytes, isIco)); 522 RLEBytes, isIco));
489 } 523 }
490 return true; 524 return true;
491 } 525 }
492 526
493 /* 527 /*
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 568
535 {} 569 {}
536 570
537 /* 571 /*
538 * 572 *
539 * Initiates the bitmap decode 573 * Initiates the bitmap decode
540 * 574 *
541 */ 575 */
542 SkCodec::Result SkBmpCodec::onGetPixels(const SkImageInfo& dstInfo, 576 SkCodec::Result SkBmpCodec::onGetPixels(const SkImageInfo& dstInfo,
543 void* dst, size_t dstRowBytes, 577 void* dst, size_t dstRowBytes,
544 const Options&, 578 const Options& opts,
545 SkPMColor*, int*) { 579 SkPMColor* inputColorPtr,
580 int* inputColorCount) {
546 // Check for proper input and output formats 581 // Check for proper input and output formats
547 SkCodec::RewindState rewindState = this->rewindIfNeeded(); 582 SkCodec::RewindState rewindState = this->rewindIfNeeded();
548 if (rewindState == kCouldNotRewind_RewindState) { 583 if (rewindState == kCouldNotRewind_RewindState) {
549 return kCouldNotRewind; 584 return kCouldNotRewind;
550 } else if (rewindState == kRewound_RewindState) { 585 } else if (rewindState == kRewound_RewindState) {
551 if (!ReadHeader(this->stream(), fIsIco, NULL)) { 586 if (!ReadHeader(this->stream(), fIsIco, NULL)) {
552 return kCouldNotRewind; 587 return kCouldNotRewind;
553 } 588 }
554 } 589 }
555 if (dstInfo.dimensions() != this->getInfo().dimensions()) { 590 if (dstInfo.dimensions() != this->getInfo().dimensions()) {
556 SkCodecPrintf("Error: scaling not supported.\n"); 591 SkCodecPrintf("Error: scaling not supported.\n");
557 return kInvalidScale; 592 return kInvalidScale;
558 } 593 }
559 if (!conversion_possible(dstInfo, this->getInfo())) { 594 if (!conversion_possible(dstInfo, this->getInfo())) {
560 SkCodecPrintf("Error: cannot convert input type to output type.\n"); 595 SkCodecPrintf("Error: cannot convert input type to output type.\n");
561 return kInvalidConversion; 596 return kInvalidConversion;
562 } 597 }
563 598
564 // Create the color table if necessary and prepare the stream for decode 599 // Create the color table if necessary and prepare the stream for decode
565 if (!createColorTable(dstInfo.alphaType())) { 600 // Note that if it is non-NULL, inputColorCount will be modified
601 if (!createColorTable(dstInfo.alphaType(), inputColorCount)) {
566 SkCodecPrintf("Error: could not create color table.\n"); 602 SkCodecPrintf("Error: could not create color table.\n");
567 return kInvalidInput; 603 return kInvalidInput;
568 } 604 }
569 605
606 // Copy the color table to the client if necessary
607 if (kIndex_8_SkColorType == dstInfo.colorType()) {
608 SkASSERT(NULL != inputColorPtr);
609 SkASSERT(NULL != inputColorCount);
610 SkASSERT(NULL != fColorTable.get());
611 sk_memcpy32(inputColorPtr, fColorTable->readColors(), *inputColorCount);
612 }
613
570 // Perform the decode 614 // Perform the decode
571 switch (fInputFormat) { 615 switch (fInputFormat) {
572 case kBitMask_BitmapInputFormat: 616 case kBitMask_BitmapInputFormat:
573 return decodeMask(dstInfo, dst, dstRowBytes); 617 return decodeMask(dstInfo, dst, dstRowBytes);
574 case kRLE_BitmapInputFormat: 618 case kRLE_BitmapInputFormat:
575 return decodeRLE(dstInfo, dst, dstRowBytes); 619 return decodeRLE(dstInfo, dst, dstRowBytes, opts);
576 case kStandard_BitmapInputFormat: 620 case kStandard_BitmapInputFormat:
577 return decode(dstInfo, dst, dstRowBytes); 621 return decode(dstInfo, dst, dstRowBytes);
578 default: 622 default:
579 SkASSERT(false); 623 SkASSERT(false);
580 return kInvalidInput; 624 return kInvalidInput;
581 } 625 }
582 } 626 }
583 627
584 /* 628 /*
585 * 629 *
586 * Process the color table for the bmp input 630 * Process the color table for the bmp input
587 * 631 *
588 */ 632 */
589 bool SkBmpCodec::createColorTable(SkAlphaType alphaType) { 633 bool SkBmpCodec::createColorTable(SkAlphaType alphaType, int* numColors) {
590 // Allocate memory for color table 634 // Allocate memory for color table
591 uint32_t colorBytes = 0; 635 uint32_t colorBytes = 0;
592 uint32_t maxColors = 0; 636 uint32_t maxColors = 0;
593 SkPMColor colorTable[256]; 637 SkPMColor colorTable[256];
594 if (fBitsPerPixel <= 8) { 638 if (fBitsPerPixel <= 8) {
595 // Zero is a default for maxColors 639 // Zero is a default for maxColors
596 // Also set fNumColors to maxColors when it is too large 640 // Also set fNumColors to maxColors when it is too large
597 maxColors = 1 << fBitsPerPixel; 641 maxColors = 1 << fBitsPerPixel;
598 if (fNumColors == 0 || fNumColors >= maxColors) { 642 if (fNumColors == 0 || fNumColors >= maxColors) {
599 fNumColors = maxColors; 643 fNumColors = maxColors;
600 } 644 }
601 645
646 // Inform the caller of the number of colors
647 if (NULL != numColors) {
648 SkASSERT(256 == *numColors);
649 // We set the number of colors to maxColors in order to ensure
650 // safe memory accesses. Otherwise, an invalid pixel could
651 // access memory outside of our color table array.
652 *numColors = maxColors;
653 }
654
602 // Read the color table from the stream 655 // Read the color table from the stream
603 colorBytes = fNumColors * fBytesPerColor; 656 colorBytes = fNumColors * fBytesPerColor;
604 SkAutoTDeleteArray<uint8_t> cBuffer(SkNEW_ARRAY(uint8_t, colorBytes)); 657 SkAutoTDeleteArray<uint8_t> cBuffer(SkNEW_ARRAY(uint8_t, colorBytes));
605 if (stream()->read(cBuffer.get(), colorBytes) != colorBytes) { 658 if (stream()->read(cBuffer.get(), colorBytes) != colorBytes) {
606 SkCodecPrintf("Error: unable to read color table.\n"); 659 SkCodecPrintf("Error: unable to read color table.\n");
607 return false; 660 return false;
608 } 661 }
609 662
610 // Choose the proper packing function 663 // Choose the proper packing function
611 SkPMColor (*packARGB) (uint32_t, uint32_t, uint32_t, uint32_t); 664 SkPMColor (*packARGB) (uint32_t, uint32_t, uint32_t, uint32_t);
(...skipping 13 matching lines...) Expand all
625 packARGB = NULL; 678 packARGB = NULL;
626 break; 679 break;
627 } 680 }
628 681
629 // Fill in the color table 682 // Fill in the color table
630 uint32_t i = 0; 683 uint32_t i = 0;
631 for (; i < fNumColors; i++) { 684 for (; i < fNumColors; i++) {
632 uint8_t blue = get_byte(cBuffer.get(), i*fBytesPerColor); 685 uint8_t blue = get_byte(cBuffer.get(), i*fBytesPerColor);
633 uint8_t green = get_byte(cBuffer.get(), i*fBytesPerColor + 1); 686 uint8_t green = get_byte(cBuffer.get(), i*fBytesPerColor + 1);
634 uint8_t red = get_byte(cBuffer.get(), i*fBytesPerColor + 2); 687 uint8_t red = get_byte(cBuffer.get(), i*fBytesPerColor + 2);
635 uint8_t alpha = kOpaque_SkAlphaType == alphaType ? 0xFF : 688 uint8_t alpha;
636 (fMasks->getAlphaMask() >> 24) & 689 if (kOpaque_SkAlphaType == alphaType || kRLE_BitmapInputFormat == fI nputFormat) {
637 get_byte(cBuffer.get(), i*fBytesPerColor + 3); 690 alpha = 0xFF;
691 } else {
692 alpha = (fMasks->getAlphaMask() >> 24) &
693 get_byte(cBuffer.get(), i*fBytesPerColor + 3);
694 }
638 colorTable[i] = packARGB(alpha, red, green, blue); 695 colorTable[i] = packARGB(alpha, red, green, blue);
639 } 696 }
640 697
641 // To avoid segmentation faults on bad pixel data, fill the end of the 698 // To avoid segmentation faults on bad pixel data, fill the end of the
642 // color table with black. This is the same the behavior as the 699 // color table with black. This is the same the behavior as the
643 // chromium decoder. 700 // chromium decoder.
644 for (; i < maxColors; i++) { 701 for (; i < maxColors; i++) {
645 colorTable[i] = SkPackARGB32NoCheck(0xFF, 0, 0, 0); 702 colorTable[i] = SkPackARGB32NoCheck(0xFF, 0, 0, 0);
646 } 703 }
647 } 704 }
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
733 790
734 // Finished decoding the entire image 791 // Finished decoding the entire image
735 return kSuccess; 792 return kSuccess;
736 } 793 }
737 794
738 /* 795 /*
739 * 796 *
740 * Set an RLE pixel using the color table 797 * Set an RLE pixel using the color table
741 * 798 *
742 */ 799 */
743 void SkBmpCodec::setRLEPixel(SkPMColor* dst, size_t dstRowBytes, 800 void SkBmpCodec::setRLEPixel(void* dst, size_t dstRowBytes,
744 const SkImageInfo& dstInfo, uint32_t x, uint32_t y, 801 const SkImageInfo& dstInfo, uint32_t x, uint32_t y,
745 uint8_t index) { 802 uint8_t index) {
746 // Set the row 803 // Set the row
747 int height = dstInfo.height(); 804 int height = dstInfo.height();
748 int row; 805 int row;
749 if (kBottomUp_RowOrder == fRowOrder) { 806 if (kBottomUp_RowOrder == fRowOrder) {
750 row = height - y - 1; 807 row = height - y - 1;
751 } else { 808 } else {
752 row = y; 809 row = y;
753 } 810 }
754 811
755 // Set the pixel based on destination color type 812 // Set the pixel based on destination color type
756 switch (dstInfo.colorType()) { 813 switch (dstInfo.colorType()) {
757 case kN32_SkColorType: { 814 case kN32_SkColorType: {
758 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, 815 SkPMColor* dstRow = SkTAddOffset<SkPMColor>((SkPMColor*) dst,
759 row * (int) dstRowBytes); 816 row * (int) dstRowBytes);
760 dstRow[x] = fColorTable->operator[](index); 817 dstRow[x] = fColorTable->operator[](index);
761 break; 818 break;
762 } 819 }
763 case kRGB_565_SkColorType: {
764 uint16_t* dstRow = SkTAddOffset<uint16_t>(dst,
765 row * (int) dstRowBytes);
766 dstRow[x] = SkPixel32ToPixel16(fColorTable->operator[](index));
767 break;
768 }
769 default: 820 default:
770 // This case should not be reached. We should catch an invalid 821 // This case should not be reached. We should catch an invalid
771 // color type when we check that the conversion is possible. 822 // color type when we check that the conversion is possible.
772 SkASSERT(false); 823 SkASSERT(false);
773 break; 824 break;
774 } 825 }
775 } 826 }
776 827
777 /* 828 /*
778 * 829 *
779 * Set an RLE pixel from R, G, B values 830 * Set an RLE pixel from R, G, B values
780 * 831 *
781 */ 832 */
782 void SkBmpCodec::setRLE24Pixel(SkPMColor* dst, size_t dstRowBytes, 833 void SkBmpCodec::setRLE24Pixel(void* dst, size_t dstRowBytes,
783 const SkImageInfo& dstInfo, uint32_t x, 834 const SkImageInfo& dstInfo, uint32_t x,
784 uint32_t y, uint8_t red, uint8_t green, 835 uint32_t y, uint8_t red, uint8_t green,
785 uint8_t blue) { 836 uint8_t blue) {
786 // Set the row 837 // Set the row
787 int height = dstInfo.height(); 838 int height = dstInfo.height();
788 int row; 839 int row;
789 if (kBottomUp_RowOrder == fRowOrder) { 840 if (kBottomUp_RowOrder == fRowOrder) {
790 row = height - y - 1; 841 row = height - y - 1;
791 } else { 842 } else {
792 row = y; 843 row = y;
793 } 844 }
794 845
795 // Set the pixel based on destination color type 846 // Set the pixel based on destination color type
796 switch (dstInfo.colorType()) { 847 switch (dstInfo.colorType()) {
797 case kN32_SkColorType: { 848 case kN32_SkColorType: {
798 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, 849 SkPMColor* dstRow = SkTAddOffset<SkPMColor>((SkPMColor*) dst,
799 row * (int) dstRowBytes); 850 row * (int) dstRowBytes);
800 dstRow[x] = SkPackARGB32NoCheck(0xFF, red, green, blue); 851 dstRow[x] = SkPackARGB32NoCheck(0xFF, red, green, blue);
801 break; 852 break;
802 } 853 }
803 case kRGB_565_SkColorType: {
804 uint16_t* dstRow = SkTAddOffset<uint16_t>(dst,
805 row * (int) dstRowBytes);
806 dstRow[x] = SkPack888ToRGB16(red, green, blue);
807 break;
808 }
809 default: 854 default:
810 // This case should not be reached. We should catch an invalid 855 // This case should not be reached. We should catch an invalid
811 // color type when we check that the conversion is possible. 856 // color type when we check that the conversion is possible.
812 SkASSERT(false); 857 SkASSERT(false);
813 break; 858 break;
814 } 859 }
815 } 860 }
816 861
817 /* 862 /*
818 * 863 *
819 * Performs the bitmap decoding for RLE input format 864 * Performs the bitmap decoding for RLE input format
820 * RLE decoding is performed all at once, rather than a one row at a time 865 * RLE decoding is performed all at once, rather than a one row at a time
821 * 866 *
822 */ 867 */
823 SkCodec::Result SkBmpCodec::decodeRLE(const SkImageInfo& dstInfo, 868 SkCodec::Result SkBmpCodec::decodeRLE(const SkImageInfo& dstInfo,
824 void* dst, size_t dstRowBytes) { 869 void* dst, size_t dstRowBytes,
870 const Options& opts) {
825 // Set RLE flags 871 // Set RLE flags
826 static const uint8_t RLE_ESCAPE = 0; 872 static const uint8_t RLE_ESCAPE = 0;
827 static const uint8_t RLE_EOL = 0; 873 static const uint8_t RLE_EOL = 0;
828 static const uint8_t RLE_EOF = 1; 874 static const uint8_t RLE_EOF = 1;
829 static const uint8_t RLE_DELTA = 2; 875 static const uint8_t RLE_DELTA = 2;
830 876
831 // Set constant values 877 // Set constant values
832 const int width = dstInfo.width(); 878 const int width = dstInfo.width();
833 const int height = dstInfo.height(); 879 const int height = dstInfo.height();
834 880
835 // Input buffer parameters 881 // Input buffer parameters
836 uint32_t currByte = 0; 882 uint32_t currByte = 0;
837 SkAutoTDeleteArray<uint8_t> buffer(SkNEW_ARRAY(uint8_t, fRLEBytes)); 883 SkAutoTDeleteArray<uint8_t> buffer(SkNEW_ARRAY(uint8_t, fRLEBytes));
838 size_t totalBytes = stream()->read(buffer.get(), fRLEBytes); 884 size_t totalBytes = stream()->read(buffer.get(), fRLEBytes);
839 if (totalBytes < fRLEBytes) { 885 if (totalBytes < fRLEBytes) {
840 SkCodecPrintf("Warning: incomplete RLE file.\n"); 886 SkCodecPrintf("Warning: incomplete RLE file.\n");
841 } else if (totalBytes <= 0) { 887 } else if (totalBytes <= 0) {
842 SkCodecPrintf("Error: could not read RLE image data.\n"); 888 SkCodecPrintf("Error: could not read RLE image data.\n");
843 return kInvalidInput; 889 return kInvalidInput;
844 } 890 }
845 891
846 // Destination parameters 892 // Destination parameters
847 int x = 0; 893 int x = 0;
848 int y = 0; 894 int y = 0;
849 // If the code skips pixels, remaining pixels are transparent or black 895
850 // TODO: Skip this if memory was already zeroed. 896 // Set the background as transparent. Then, if the RLE code skips pixels,
851 memset(dst, 0, dstRowBytes * height); 897 // the skipped pixels will be transparent.
852 SkPMColor* dstPtr = (SkPMColor*) dst; 898 // Because of the need for transparent pixels, kN32 is the only color
899 // type that makes sense for the destination format.
900 SkASSERT(kN32_SkColorType == dstInfo.colorType());
901 if (kNo_ZeroInitialized == opts.fZeroInitialized) {
902 SkSwizzler::Fill(dst, dstInfo, dstRowBytes, 0, SK_ColorTRANSPARENT, NULL );
903 }
853 904
854 while (true) { 905 while (true) {
855 // Every entry takes at least two bytes 906 // Every entry takes at least two bytes
856 if ((int) totalBytes - currByte < 2) { 907 if ((int) totalBytes - currByte < 2) {
857 SkCodecPrintf("Warning: incomplete RLE input.\n"); 908 SkCodecPrintf("Warning: incomplete RLE input.\n");
858 return kIncompleteInput; 909 return kIncompleteInput;
859 } 910 }
860 911
861 // Read the next two bytes. These bytes have different meanings 912 // Read the next two bytes. These bytes have different meanings
862 // depending on their values. In the first interpretation, the first 913 // depending on their values. In the first interpretation, the first
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
913 (int) totalBytes - currByte < SkAlign2(rowBytes)) { 964 (int) totalBytes - currByte < SkAlign2(rowBytes)) {
914 SkCodecPrintf("Warning: invalid RLE input.\n"); 965 SkCodecPrintf("Warning: invalid RLE input.\n");
915 return kIncompleteInput; 966 return kIncompleteInput;
916 } 967 }
917 // Set numPixels number of pixels 968 // Set numPixels number of pixels
918 while (numPixels > 0) { 969 while (numPixels > 0) {
919 switch(fBitsPerPixel) { 970 switch(fBitsPerPixel) {
920 case 4: { 971 case 4: {
921 SkASSERT(currByte < totalBytes); 972 SkASSERT(currByte < totalBytes);
922 uint8_t val = buffer.get()[currByte++]; 973 uint8_t val = buffer.get()[currByte++];
923 setRLEPixel(dstPtr, dstRowBytes, dstInfo, x++, 974 setRLEPixel(dst, dstRowBytes, dstInfo, x++,
924 y, val >> 4); 975 y, val >> 4);
925 numPixels--; 976 numPixels--;
926 if (numPixels != 0) { 977 if (numPixels != 0) {
927 setRLEPixel(dstPtr, dstRowBytes, dstInfo, 978 setRLEPixel(dst, dstRowBytes, dstInfo,
928 x++, y, val & 0xF); 979 x++, y, val & 0xF);
929 numPixels--; 980 numPixels--;
930 } 981 }
931 break; 982 break;
932 } 983 }
933 case 8: 984 case 8:
934 SkASSERT(currByte < totalBytes); 985 SkASSERT(currByte < totalBytes);
935 setRLEPixel(dstPtr, dstRowBytes, dstInfo, x++, 986 setRLEPixel(dst, dstRowBytes, dstInfo, x++,
936 y, buffer.get()[currByte++]); 987 y, buffer.get()[currByte++]);
937 numPixels--; 988 numPixels--;
938 break; 989 break;
939 case 24: { 990 case 24: {
940 SkASSERT(currByte + 2 < totalBytes); 991 SkASSERT(currByte + 2 < totalBytes);
941 uint8_t blue = buffer.get()[currByte++]; 992 uint8_t blue = buffer.get()[currByte++];
942 uint8_t green = buffer.get()[currByte++]; 993 uint8_t green = buffer.get()[currByte++];
943 uint8_t red = buffer.get()[currByte++]; 994 uint8_t red = buffer.get()[currByte++];
944 setRLE24Pixel(dstPtr, dstRowBytes, dstInfo, 995 setRLE24Pixel(dst, dstRowBytes, dstInfo,
945 x++, y, red, green, blue); 996 x++, y, red, green, blue);
946 numPixels--; 997 numPixels--;
947 } 998 }
948 default: 999 default:
949 SkASSERT(false); 1000 SkASSERT(false);
950 return kInvalidInput; 1001 return kInvalidInput;
951 } 1002 }
952 } 1003 }
953 // Skip a byte if necessary to maintain alignment 1004 // Skip a byte if necessary to maintain alignment
954 if (!SkIsAlign2(rowBytes)) { 1005 if (!SkIsAlign2(rowBytes)) {
(...skipping 15 matching lines...) Expand all
970 if ((int) totalBytes - currByte < 2) { 1021 if ((int) totalBytes - currByte < 2) {
971 SkCodecPrintf("Warning: incomplete RLE input\n"); 1022 SkCodecPrintf("Warning: incomplete RLE input\n");
972 return kIncompleteInput; 1023 return kIncompleteInput;
973 } 1024 }
974 1025
975 // Fill the pixels up to endX with the specified color 1026 // Fill the pixels up to endX with the specified color
976 uint8_t blue = task; 1027 uint8_t blue = task;
977 uint8_t green = buffer.get()[currByte++]; 1028 uint8_t green = buffer.get()[currByte++];
978 uint8_t red = buffer.get()[currByte++]; 1029 uint8_t red = buffer.get()[currByte++];
979 while (x < endX) { 1030 while (x < endX) {
980 setRLE24Pixel(dstPtr, dstRowBytes, dstInfo, x++, y, red, 1031 setRLE24Pixel(dst, dstRowBytes, dstInfo, x++, y, red,
981 green, blue); 1032 green, blue);
982 } 1033 }
983 } else { 1034 } else {
984 // In RLE8 or RLE4, the second byte read gives the index in the 1035 // In RLE8 or RLE4, the second byte read gives the index in the
985 // color table to look up the pixel color. 1036 // color table to look up the pixel color.
986 // RLE8 has one color index that gets repeated 1037 // RLE8 has one color index that gets repeated
987 // RLE4 has two color indexes in the upper and lower 4 bits of 1038 // RLE4 has two color indexes in the upper and lower 4 bits of
988 // the bytes, which are alternated 1039 // the bytes, which are alternated
989 uint8_t indices[2] = { task, task }; 1040 uint8_t indices[2] = { task, task };
990 if (4 == fBitsPerPixel) { 1041 if (4 == fBitsPerPixel) {
991 indices[0] >>= 4; 1042 indices[0] >>= 4;
992 indices[1] &= 0xf; 1043 indices[1] &= 0xf;
993 } 1044 }
994 1045
995 // Set the indicated number of pixels 1046 // Set the indicated number of pixels
996 for (int which = 0; x < endX; x++) { 1047 for (int which = 0; x < endX; x++) {
997 setRLEPixel(dstPtr, dstRowBytes, dstInfo, x, y, 1048 setRLEPixel(dst, dstRowBytes, dstInfo, x, y,
998 indices[which]); 1049 indices[which]);
999 which = !which; 1050 which = !which;
1000 } 1051 }
1001 } 1052 }
1002 } 1053 }
1003 } 1054 }
1004 } 1055 }
1005 1056
1006 /* 1057 /*
1007 * 1058 *
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
1077 } 1128 }
1078 1129
1079 // FIXME: This code exists to match the behavior in the chromium decoder 1130 // FIXME: This code exists to match the behavior in the chromium decoder
1080 // and to follow the bmp specification as it relates to alpha masks. It is 1131 // and to follow the bmp specification as it relates to alpha masks. It is
1081 // commented out because we have yet to discover a test image that provides 1132 // commented out because we have yet to discover a test image that provides
1082 // an alpha mask and uses this decode mode. 1133 // an alpha mask and uses this decode mode.
1083 1134
1084 // Now we adjust the output image with some additional behavior that 1135 // Now we adjust the output image with some additional behavior that
1085 // SkSwizzler does not support. Firstly, all bmp images that contain 1136 // SkSwizzler does not support. Firstly, all bmp images that contain
1086 // alpha are masked by the alpha mask. Secondly, many fully transparent 1137 // alpha are masked by the alpha mask. Secondly, many fully transparent
1087 // bmp images are intended to be opaque. Here, we make those corrections. 1138 // bmp images are intended to be opaque. Here, we make those corrections
1139 // in the kN32 case.
1088 /* 1140 /*
1089 SkPMColor* dstRow = (SkPMColor*) dst; 1141 SkPMColor* dstRow = (SkPMColor*) dst;
1090 if (SkSwizzler::kBGRA == config) { 1142 if (SkSwizzler::kBGRA == config) {
1091 for (int y = 0; y < height; y++) { 1143 for (int y = 0; y < height; y++) {
1092 for (int x = 0; x < width; x++) { 1144 for (int x = 0; x < width; x++) {
1093 if (transparent) { 1145 if (transparent) {
1094 dstRow[x] |= 0xFF000000; 1146 dstRow[x] |= 0xFF000000;
1095 } else { 1147 } else {
1096 dstRow[x] &= alphaMask; 1148 dstRow[x] &= alphaMask;
1097 } 1149 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1132 uint32_t alphaBit = 1184 uint32_t alphaBit =
1133 (srcBuffer.get()[quotient] >> shift) & 0x1; 1185 (srcBuffer.get()[quotient] >> shift) & 0x1;
1134 dstRow[x] &= alphaBit - 1; 1186 dstRow[x] &= alphaBit - 1;
1135 } 1187 }
1136 } 1188 }
1137 } 1189 }
1138 1190
1139 // Finished decoding the entire image 1191 // Finished decoding the entire image
1140 return kSuccess; 1192 return kSuccess;
1141 } 1193 }
OLDNEW
« no previous file with comments | « src/codec/SkCodec_libbmp.h ('k') | src/codec/SkCodec_libgif.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698