OLD | NEW |
---|---|
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 596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
607 if (kIndex_8_SkColorType == dstInfo.colorType()) { | 607 if (kIndex_8_SkColorType == dstInfo.colorType()) { |
608 SkASSERT(NULL != inputColorPtr); | 608 SkASSERT(NULL != inputColorPtr); |
609 SkASSERT(NULL != inputColorCount); | 609 SkASSERT(NULL != inputColorCount); |
610 SkASSERT(NULL != fColorTable.get()); | 610 SkASSERT(NULL != fColorTable.get()); |
611 sk_memcpy32(inputColorPtr, fColorTable->readColors(), *inputColorCount); | 611 sk_memcpy32(inputColorPtr, fColorTable->readColors(), *inputColorCount); |
612 } | 612 } |
613 | 613 |
614 // Perform the decode | 614 // Perform the decode |
615 switch (fInputFormat) { | 615 switch (fInputFormat) { |
616 case kBitMask_BitmapInputFormat: | 616 case kBitMask_BitmapInputFormat: |
617 return decodeMask(dstInfo, dst, dstRowBytes); | 617 return decodeMask(dstInfo, dst, dstRowBytes, opts); |
618 case kRLE_BitmapInputFormat: | 618 case kRLE_BitmapInputFormat: |
619 return decodeRLE(dstInfo, dst, dstRowBytes, opts); | 619 return decodeRLE(dstInfo, dst, dstRowBytes, opts); |
620 case kStandard_BitmapInputFormat: | 620 case kStandard_BitmapInputFormat: |
621 return decode(dstInfo, dst, dstRowBytes); | 621 return decode(dstInfo, dst, dstRowBytes, opts); |
622 default: | 622 default: |
623 SkASSERT(false); | 623 SkASSERT(false); |
624 return kInvalidInput; | 624 return kInvalidInput; |
625 } | 625 } |
626 } | 626 } |
627 | 627 |
628 /* | 628 /* |
629 * | 629 * |
630 * Process the color table for the bmp input | 630 * Process the color table for the bmp input |
631 * | 631 * |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
694 } | 694 } |
695 colorTable[i] = packARGB(alpha, red, green, blue); | 695 colorTable[i] = packARGB(alpha, red, green, blue); |
696 } | 696 } |
697 | 697 |
698 // 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 |
699 // 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 |
700 // chromium decoder. | 700 // chromium decoder. |
701 for (; i < maxColors; i++) { | 701 for (; i < maxColors; i++) { |
702 colorTable[i] = SkPackARGB32NoCheck(0xFF, 0, 0, 0); | 702 colorTable[i] = SkPackARGB32NoCheck(0xFF, 0, 0, 0); |
703 } | 703 } |
704 | |
705 // Set the color table | |
706 fColorTable.reset(SkNEW_ARGS(SkColorTable, (colorTable, maxColors))); | |
704 } | 707 } |
705 | 708 |
706 // Bmp-in-Ico files do not use an offset to indicate where the pixel data | 709 // Bmp-in-Ico files do not use an offset to indicate where the pixel data |
707 // begins. Pixel data always begins immediately after the color table. | 710 // begins. Pixel data always begins immediately after the color table. |
708 if (!fIsIco) { | 711 if (!fIsIco) { |
709 // Check that we have not read past the pixel array offset | 712 // Check that we have not read past the pixel array offset |
710 if(fOffset < colorBytes) { | 713 if(fOffset < colorBytes) { |
711 // This may occur on OS 2.1 and other old versions where the color | 714 // This may occur on OS 2.1 and other old versions where the color |
712 // table defaults to max size, and the bmp tries to use a smaller | 715 // table defaults to max size, and the bmp tries to use a smaller |
713 // color table. This is invalid, and our decision is to indicate | 716 // color table. This is invalid, and our decision is to indicate |
714 // an error, rather than try to guess the intended size of the | 717 // an error, rather than try to guess the intended size of the |
715 // color table. | 718 // color table. |
716 SkCodecPrintf("Error: pixel data offset less than color table size.\ n"); | 719 SkCodecPrintf("Error: pixel data offset less than color table size.\ n"); |
717 return false; | 720 return false; |
718 } | 721 } |
719 | 722 |
720 // After reading the color table, skip to the start of the pixel array | 723 // After reading the color table, skip to the start of the pixel array |
721 if (stream()->skip(fOffset - colorBytes) != fOffset - colorBytes) { | 724 if (stream()->skip(fOffset - colorBytes) != fOffset - colorBytes) { |
722 SkCodecPrintf("Error: unable to skip to image data.\n"); | 725 SkCodecPrintf("Error: unable to skip to image data.\n"); |
723 return false; | 726 return false; |
724 } | 727 } |
725 } | 728 } |
726 | 729 |
727 // Set the color table and return true on success | 730 // Return true on success |
728 fColorTable.reset(SkNEW_ARGS(SkColorTable, (colorTable, maxColors))); | |
729 return true; | 731 return true; |
730 } | 732 } |
731 | 733 |
732 /* | 734 /* |
733 * | 735 * |
734 * Performs the bitmap decoding for bit masks input format | 736 * Performs the bitmap decoding for bit masks input format |
735 * | 737 * |
736 */ | 738 */ |
737 SkCodec::Result SkBmpCodec::decodeMask(const SkImageInfo& dstInfo, | 739 SkCodec::Result SkBmpCodec::decodeMask(const SkImageInfo& dstInfo, |
738 void* dst, size_t dstRowBytes) { | 740 void* dst, size_t dstRowBytes, |
741 const Options& opts) { | |
739 // Set constant values | 742 // Set constant values |
740 const int width = dstInfo.width(); | 743 const int width = dstInfo.width(); |
741 const int height = dstInfo.height(); | 744 const int height = dstInfo.height(); |
742 const size_t rowBytes = SkAlign4(compute_row_bytes(width, fBitsPerPixel)); | 745 const size_t rowBytes = SkAlign4(compute_row_bytes(width, fBitsPerPixel)); |
743 | 746 |
744 // Allocate a buffer large enough to hold the full image | 747 // Allocate a buffer large enough to hold the full image |
745 SkAutoTDeleteArray<uint8_t> | 748 SkAutoTDeleteArray<uint8_t> |
746 srcBuffer(SkNEW_ARRAY(uint8_t, height*rowBytes)); | 749 srcBuffer(SkNEW_ARRAY(uint8_t, height*rowBytes)); |
747 uint8_t* srcRow = srcBuffer.get(); | 750 uint8_t* srcRow = srcBuffer.get(); |
748 | 751 |
749 // Create the swizzler | 752 // Create the swizzler |
750 SkAutoTDelete<SkMaskSwizzler> maskSwizzler( | 753 SkAutoTDelete<SkMaskSwizzler> maskSwizzler( |
751 SkMaskSwizzler::CreateMaskSwizzler(dstInfo, dst, dstRowBytes, | 754 SkMaskSwizzler::CreateMaskSwizzler(dstInfo, dst, dstRowBytes, |
752 fMasks, fBitsPerPixel)); | 755 fMasks, fBitsPerPixel)); |
753 | 756 |
754 // Iterate over rows of the image | 757 // Iterate over rows of the image |
755 bool transparent = true; | 758 bool transparent = true; |
756 for (int y = 0; y < height; y++) { | 759 for (int y = 0; y < height; y++) { |
757 // Read a row of the input | 760 // Read a row of the input |
758 if (stream()->read(srcRow, rowBytes) != rowBytes) { | 761 if (stream()->read(srcRow, rowBytes) != rowBytes) { |
759 SkCodecPrintf("Warning: incomplete input stream.\n"); | 762 SkCodecPrintf("Warning: incomplete input stream.\n"); |
763 // Fill the destination image on failure | |
764 // By using zero as the fill value, we will fill with transparent | |
765 // pixels for non-opaque images and white for opaque images. | |
766 // These are arbitrary choices but allow for consistent behavior. | |
767 if (kNo_ZeroInitialized == opts.fZeroInitialized) { | |
768 void* dstStart = (kTopDown_RowOrder == fRowOrder) ? | |
769 SkTAddOffset<void*>(dst, y * dstRowBytes) : dst; | |
770 SkSwizzler::Fill(dstStart, dstInfo, dstRowBytes, dstInfo.height( ) - y, 0, NULL); | |
771 } | |
760 return kIncompleteInput; | 772 return kIncompleteInput; |
761 } | 773 } |
762 | 774 |
763 // Decode the row in destination format | 775 // Decode the row in destination format |
764 int row = kBottomUp_RowOrder == fRowOrder ? height - 1 - y : y; | 776 int row = kBottomUp_RowOrder == fRowOrder ? height - 1 - y : y; |
765 SkSwizzler::ResultAlpha r = maskSwizzler->next(srcRow, row); | 777 SkSwizzler::ResultAlpha r = maskSwizzler->next(srcRow, row); |
766 transparent &= SkSwizzler::IsTransparent(r); | 778 transparent &= SkSwizzler::IsTransparent(r); |
767 | 779 |
768 // Move to the next row | 780 // Move to the next row |
769 srcRow = SkTAddOffset<uint8_t>(srcRow, rowBytes); | 781 srcRow = SkTAddOffset<uint8_t>(srcRow, rowBytes); |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
892 // Destination parameters | 904 // Destination parameters |
893 int x = 0; | 905 int x = 0; |
894 int y = 0; | 906 int y = 0; |
895 | 907 |
896 // Set the background as transparent. Then, if the RLE code skips pixels, | 908 // Set the background as transparent. Then, if the RLE code skips pixels, |
897 // the skipped pixels will be transparent. | 909 // the skipped pixels will be transparent. |
898 // Because of the need for transparent pixels, kN32 is the only color | 910 // Because of the need for transparent pixels, kN32 is the only color |
899 // type that makes sense for the destination format. | 911 // type that makes sense for the destination format. |
900 SkASSERT(kN32_SkColorType == dstInfo.colorType()); | 912 SkASSERT(kN32_SkColorType == dstInfo.colorType()); |
901 if (kNo_ZeroInitialized == opts.fZeroInitialized) { | 913 if (kNo_ZeroInitialized == opts.fZeroInitialized) { |
902 SkSwizzler::Fill(dst, dstInfo, dstRowBytes, 0, SK_ColorTRANSPARENT, NULL ); | 914 SkSwizzler::Fill(dst, dstInfo, dstRowBytes, height, SK_ColorTRANSPARENT, NULL); |
903 } | 915 } |
904 | 916 |
905 while (true) { | 917 while (true) { |
906 // Every entry takes at least two bytes | 918 // Every entry takes at least two bytes |
907 if ((int) totalBytes - currByte < 2) { | 919 if ((int) totalBytes - currByte < 2) { |
908 SkCodecPrintf("Warning: incomplete RLE input.\n"); | 920 SkCodecPrintf("Warning: incomplete RLE input.\n"); |
909 return kIncompleteInput; | 921 return kIncompleteInput; |
910 } | 922 } |
911 | 923 |
912 // Read the next two bytes. These bytes have different meanings | 924 // Read the next two bytes. These bytes have different meanings |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1053 } | 1065 } |
1054 } | 1066 } |
1055 } | 1067 } |
1056 | 1068 |
1057 /* | 1069 /* |
1058 * | 1070 * |
1059 * Performs the bitmap decoding for standard input format | 1071 * Performs the bitmap decoding for standard input format |
1060 * | 1072 * |
1061 */ | 1073 */ |
1062 SkCodec::Result SkBmpCodec::decode(const SkImageInfo& dstInfo, | 1074 SkCodec::Result SkBmpCodec::decode(const SkImageInfo& dstInfo, |
1063 void* dst, size_t dstRowBytes) { | 1075 void* dst, size_t dstRowBytes, |
1076 const Options& opts) { | |
1064 // Set constant values | 1077 // Set constant values |
1065 const int width = dstInfo.width(); | 1078 const int width = dstInfo.width(); |
1066 const int height = dstInfo.height(); | 1079 const int height = dstInfo.height(); |
1067 const size_t rowBytes = SkAlign4(compute_row_bytes(width, fBitsPerPixel)); | 1080 const size_t rowBytes = SkAlign4(compute_row_bytes(width, fBitsPerPixel)); |
1068 | 1081 |
1069 // Get swizzler configuration | 1082 // Get swizzler configuration |
1070 SkSwizzler::SrcConfig config; | 1083 SkSwizzler::SrcConfig config; |
1071 switch (fBitsPerPixel) { | 1084 switch (fBitsPerPixel) { |
1072 case 1: | 1085 case 1: |
1073 config = SkSwizzler::kIndex1; | 1086 config = SkSwizzler::kIndex1; |
(...skipping 15 matching lines...) Expand all Loading... | |
1089 config = SkSwizzler::kBGRX; | 1102 config = SkSwizzler::kBGRX; |
1090 } else { | 1103 } else { |
1091 config = SkSwizzler::kBGRA; | 1104 config = SkSwizzler::kBGRA; |
1092 } | 1105 } |
1093 break; | 1106 break; |
1094 default: | 1107 default: |
1095 SkASSERT(false); | 1108 SkASSERT(false); |
1096 return kInvalidInput; | 1109 return kInvalidInput; |
1097 } | 1110 } |
1098 | 1111 |
1112 // Get a pointer to the color table if it exists | |
1113 const SkPMColor* colorPtr = NULL != fColorTable.get() ? fColorTable->readCol ors() : NULL; | |
1114 | |
1099 // Create swizzler | 1115 // Create swizzler |
1100 SkAutoTDelete<SkSwizzler> swizzler(SkSwizzler::CreateSwizzler(config, | 1116 SkAutoTDelete<SkSwizzler> swizzler(SkSwizzler::CreateSwizzler(config, |
1101 fColorTable->readColors(), dstInfo, dst, dstRowBytes, | 1117 colorPtr, dstInfo, dst, dstRowBytes, |
1102 SkImageGenerator::kNo_ZeroInitialized)); | 1118 SkImageGenerator::kNo_ZeroInitialized)); |
1103 | 1119 |
1104 // Allocate space for a row buffer and a source for the swizzler | 1120 // Allocate space for a row buffer and a source for the swizzler |
1105 SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, rowBytes)); | 1121 SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, rowBytes)); |
1106 | 1122 |
1107 // Iterate over rows of the image | 1123 // Iterate over rows of the image |
1108 // FIXME: bool transparent = true; | 1124 // FIXME: bool transparent = true; |
1109 for (int y = 0; y < height; y++) { | 1125 for (int y = 0; y < height; y++) { |
1110 // Read a row of the input | 1126 // Read a row of the input |
1111 if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) { | 1127 if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) { |
1112 SkCodecPrintf("Warning: incomplete input stream.\n"); | 1128 SkCodecPrintf("Warning: incomplete input stream.\n"); |
1129 // Fill the destination image on failure | |
1130 // By using zero as the fill value, we will fill with the first | |
1131 // color in the color table for palette images, transparent | |
1132 // pixels for non-opaque images, and white for opaque images. | |
1133 // These are arbitrary choices but allow for consistent behavior. | |
1134 if (kNo_ZeroInitialized == opts.fZeroInitialized) { | |
1135 void* dstStart = (kTopDown_RowOrder == fRowOrder) ? | |
scroggo
2015/04/10 21:08:32
nit: It seems like you could use a macro/static fu
msarett
2015/04/10 21:22:32
Done.
| |
1136 SkTAddOffset<void*>(dst, y * dstRowBytes) : dst; | |
1137 SkSwizzler::Fill(dstStart, dstInfo, dstRowBytes, dstInfo.height( ) - y, 0, | |
1138 colorPtr); | |
1139 } | |
1113 return kIncompleteInput; | 1140 return kIncompleteInput; |
1114 } | 1141 } |
1115 | 1142 |
1116 // Decode the row in destination format | 1143 // Decode the row in destination format |
1117 uint32_t row; | 1144 uint32_t row; |
1118 if (kTopDown_RowOrder == fRowOrder) { | 1145 if (kTopDown_RowOrder == fRowOrder) { |
1119 row = y; | 1146 row = y; |
1120 } else { | 1147 } else { |
1121 row = height - 1 - y; | 1148 row = height - 1 - y; |
1122 } | 1149 } |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1184 uint32_t alphaBit = | 1211 uint32_t alphaBit = |
1185 (srcBuffer.get()[quotient] >> shift) & 0x1; | 1212 (srcBuffer.get()[quotient] >> shift) & 0x1; |
1186 dstRow[x] &= alphaBit - 1; | 1213 dstRow[x] &= alphaBit - 1; |
1187 } | 1214 } |
1188 } | 1215 } |
1189 } | 1216 } |
1190 | 1217 |
1191 // Finished decoding the entire image | 1218 // Finished decoding the entire image |
1192 return kSuccess; | 1219 return kSuccess; |
1193 } | 1220 } |
OLD | NEW |