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 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
90 kCMYK4BitRLE_BitmapCompressionMethod = 13 | 90 kCMYK4BitRLE_BitmapCompressionMethod = 13 |
91 }; | 91 }; |
92 | 92 |
93 /* | 93 /* |
94 * | 94 * |
95 * Checks the start of the stream to see if the image is a bitmap | 95 * Checks the start of the stream to see if the image is a bitmap |
96 * | 96 * |
97 */ | 97 */ |
98 bool SkBmpCodec::IsBmp(SkStream* stream) { | 98 bool SkBmpCodec::IsBmp(SkStream* stream) { |
99 // TODO: Support "IC", "PT", "CI", "CP", "BA" | 99 // TODO: Support "IC", "PT", "CI", "CP", "BA" |
100 // TODO: ICO files may contain a BMP and need to use this decoder | |
101 const char bmpSig[] = { 'B', 'M' }; | 100 const char bmpSig[] = { 'B', 'M' }; |
102 char buffer[sizeof(bmpSig)]; | 101 char buffer[sizeof(bmpSig)]; |
103 return stream->read(buffer, sizeof(bmpSig)) == sizeof(bmpSig) && | 102 return stream->read(buffer, sizeof(bmpSig)) == sizeof(bmpSig) && |
104 !memcmp(buffer, bmpSig, sizeof(bmpSig)); | 103 !memcmp(buffer, bmpSig, sizeof(bmpSig)); |
105 } | 104 } |
106 | 105 |
107 /* | 106 /* |
108 * | 107 * |
109 * Assumes IsBmp was called and returned true | 108 * Assumes IsBmp was called and returned true |
110 * Creates a bmp decoder | 109 * Creates a bmp decoder |
(...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
607 if (kIndex_8_SkColorType == dstInfo.colorType()) { | 606 if (kIndex_8_SkColorType == dstInfo.colorType()) { |
608 SkASSERT(NULL != inputColorPtr); | 607 SkASSERT(NULL != inputColorPtr); |
609 SkASSERT(NULL != inputColorCount); | 608 SkASSERT(NULL != inputColorCount); |
610 SkASSERT(NULL != fColorTable.get()); | 609 SkASSERT(NULL != fColorTable.get()); |
611 sk_memcpy32(inputColorPtr, fColorTable->readColors(), *inputColorCount); | 610 sk_memcpy32(inputColorPtr, fColorTable->readColors(), *inputColorCount); |
612 } | 611 } |
613 | 612 |
614 // Perform the decode | 613 // Perform the decode |
615 switch (fInputFormat) { | 614 switch (fInputFormat) { |
616 case kBitMask_BitmapInputFormat: | 615 case kBitMask_BitmapInputFormat: |
617 return decodeMask(dstInfo, dst, dstRowBytes, opts); | 616 return decodeMask(dstInfo, dst, dstRowBytes, opts); |
scroggo
2015/04/14 13:10:32
nit: Rebasing between uploads can make it harder t
msarett
2015/04/14 19:30:36
Sorry about that. Good to know.
| |
618 case kRLE_BitmapInputFormat: | 617 case kRLE_BitmapInputFormat: |
619 return decodeRLE(dstInfo, dst, dstRowBytes, opts); | 618 return decodeRLE(dstInfo, dst, dstRowBytes, opts); |
620 case kStandard_BitmapInputFormat: | 619 case kStandard_BitmapInputFormat: |
621 return decode(dstInfo, dst, dstRowBytes, opts); | 620 return decode(dstInfo, dst, dstRowBytes, opts); |
622 default: | 621 default: |
623 SkASSERT(false); | 622 SkASSERT(false); |
624 return kInvalidInput; | 623 return kInvalidInput; |
625 } | 624 } |
626 } | 625 } |
627 | 626 |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
766 SkMaskSwizzler::CreateMaskSwizzler(dstInfo, dst, dstRowBytes, | 765 SkMaskSwizzler::CreateMaskSwizzler(dstInfo, dst, dstRowBytes, |
767 fMasks, fBitsPerPixel)); | 766 fMasks, fBitsPerPixel)); |
768 | 767 |
769 // Iterate over rows of the image | 768 // Iterate over rows of the image |
770 bool transparent = true; | 769 bool transparent = true; |
771 for (int y = 0; y < height; y++) { | 770 for (int y = 0; y < height; y++) { |
772 // Read a row of the input | 771 // Read a row of the input |
773 if (stream()->read(srcRow, rowBytes) != rowBytes) { | 772 if (stream()->read(srcRow, rowBytes) != rowBytes) { |
774 SkCodecPrintf("Warning: incomplete input stream.\n"); | 773 SkCodecPrintf("Warning: incomplete input stream.\n"); |
775 // Fill the destination image on failure | 774 // Fill the destination image on failure |
776 // By using zero as the fill value, we will fill with transparent | 775 SkPMColor fillColor = dstInfo.alphaType() == kOpaque_SkAlphaType ? |
777 // pixels for non-opaque images and white for opaque images. | 776 SK_ColorBLACK : SK_ColorTRANSPARENT; |
778 // These are arbitrary choices but allow for consistent behavior. | |
779 if (kNo_ZeroInitialized == opts.fZeroInitialized) { | 777 if (kNo_ZeroInitialized == opts.fZeroInitialized) { |
780 void* dstStart = get_dst_start_row(dst, dstRowBytes, y, fRowOrde r); | 778 void* dstStart = get_dst_start_row(dst, dstRowBytes, y, fRowOrde r); |
781 SkSwizzler::Fill(dstStart, dstInfo, dstRowBytes, dstInfo.height( ) - y, 0, NULL); | 779 SkSwizzler::Fill(dstStart, dstInfo, dstRowBytes, dstInfo.height( ) - y, fillColor, |
780 NULL); | |
782 } | 781 } |
783 return kIncompleteInput; | 782 return kIncompleteInput; |
784 } | 783 } |
785 | 784 |
786 // Decode the row in destination format | 785 // Decode the row in destination format |
787 int row = kBottomUp_RowOrder == fRowOrder ? height - 1 - y : y; | 786 int row = kBottomUp_RowOrder == fRowOrder ? height - 1 - y : y; |
788 SkSwizzler::ResultAlpha r = maskSwizzler->next(srcRow, row); | 787 SkSwizzler::ResultAlpha r = maskSwizzler->next(srcRow, row); |
789 transparent &= SkSwizzler::IsTransparent(r); | 788 transparent &= SkSwizzler::IsTransparent(r); |
790 | 789 |
791 // Move to the next row | 790 // Move to the next row |
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1083 * | 1082 * |
1084 */ | 1083 */ |
1085 SkCodec::Result SkBmpCodec::decode(const SkImageInfo& dstInfo, | 1084 SkCodec::Result SkBmpCodec::decode(const SkImageInfo& dstInfo, |
1086 void* dst, size_t dstRowBytes, | 1085 void* dst, size_t dstRowBytes, |
1087 const Options& opts) { | 1086 const Options& opts) { |
1088 // Set constant values | 1087 // Set constant values |
1089 const int width = dstInfo.width(); | 1088 const int width = dstInfo.width(); |
1090 const int height = dstInfo.height(); | 1089 const int height = dstInfo.height(); |
1091 const size_t rowBytes = SkAlign4(compute_row_bytes(width, fBitsPerPixel)); | 1090 const size_t rowBytes = SkAlign4(compute_row_bytes(width, fBitsPerPixel)); |
1092 | 1091 |
1093 // Get swizzler configuration | 1092 // Get swizzler configuration and choose the fill value for failures. We wi ll use |
1093 // zero as the default palette index, black for opaque images, and transpare nt for | |
1094 // non-opaque images. | |
1094 SkSwizzler::SrcConfig config; | 1095 SkSwizzler::SrcConfig config; |
1096 uint32_t fillColorOrIndex; | |
1095 switch (fBitsPerPixel) { | 1097 switch (fBitsPerPixel) { |
1096 case 1: | 1098 case 1: |
1097 config = SkSwizzler::kIndex1; | 1099 config = SkSwizzler::kIndex1; |
1100 fillColorOrIndex = 0; | |
1098 break; | 1101 break; |
1099 case 2: | 1102 case 2: |
1100 config = SkSwizzler::kIndex2; | 1103 config = SkSwizzler::kIndex2; |
1104 fillColorOrIndex = 0; | |
1101 break; | 1105 break; |
1102 case 4: | 1106 case 4: |
1103 config = SkSwizzler::kIndex4; | 1107 config = SkSwizzler::kIndex4; |
1108 fillColorOrIndex = 0; | |
1104 break; | 1109 break; |
1105 case 8: | 1110 case 8: |
1106 config = SkSwizzler::kIndex; | 1111 config = SkSwizzler::kIndex; |
1112 fillColorOrIndex = 0; | |
1107 break; | 1113 break; |
1108 case 24: | 1114 case 24: |
1109 config = SkSwizzler::kBGR; | 1115 config = SkSwizzler::kBGR; |
1116 fillColorOrIndex = SK_ColorBLACK; | |
1110 break; | 1117 break; |
1111 case 32: | 1118 case 32: |
1112 if (kOpaque_SkAlphaType == dstInfo.alphaType()) { | 1119 if (kOpaque_SkAlphaType == dstInfo.alphaType()) { |
1113 config = SkSwizzler::kBGRX; | 1120 config = SkSwizzler::kBGRX; |
1121 fillColorOrIndex = SK_ColorBLACK; | |
1114 } else { | 1122 } else { |
1115 config = SkSwizzler::kBGRA; | 1123 config = SkSwizzler::kBGRA; |
1124 fillColorOrIndex = SK_ColorTRANSPARENT; | |
1116 } | 1125 } |
1117 break; | 1126 break; |
1118 default: | 1127 default: |
1119 SkASSERT(false); | 1128 SkASSERT(false); |
1120 return kInvalidInput; | 1129 return kInvalidInput; |
1121 } | 1130 } |
1122 | 1131 |
1123 // Get a pointer to the color table if it exists | 1132 // Get a pointer to the color table if it exists |
1124 const SkPMColor* colorPtr = NULL != fColorTable.get() ? fColorTable->readCol ors() : NULL; | 1133 const SkPMColor* colorPtr = NULL != fColorTable.get() ? fColorTable->readCol ors() : NULL; |
1125 | 1134 |
1126 // Create swizzler | 1135 // Create swizzler |
1127 SkAutoTDelete<SkSwizzler> swizzler(SkSwizzler::CreateSwizzler(config, | 1136 SkAutoTDelete<SkSwizzler> swizzler(SkSwizzler::CreateSwizzler(config, |
1128 colorPtr, dstInfo, dst, dstRowBytes, | 1137 colorPtr, dstInfo, dst, dstRowBytes, |
1129 SkImageGenerator::kNo_ZeroInitialized)); | 1138 SkImageGenerator::kNo_ZeroInitialized)); |
1130 | 1139 |
1131 // Allocate space for a row buffer and a source for the swizzler | 1140 // Allocate space for a row buffer and a source for the swizzler |
1132 SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, rowBytes)); | 1141 SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, rowBytes)); |
1133 | 1142 |
1134 // Iterate over rows of the image | 1143 // Iterate over rows of the image |
1135 // FIXME: bool transparent = true; | 1144 // FIXME: bool transparent = true; |
1136 for (int y = 0; y < height; y++) { | 1145 for (int y = 0; y < height; y++) { |
1137 // Read a row of the input | 1146 // Read a row of the input |
1138 if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) { | 1147 if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) { |
1139 SkCodecPrintf("Warning: incomplete input stream.\n"); | 1148 SkCodecPrintf("Warning: incomplete input stream.\n"); |
1140 // Fill the destination image on failure | 1149 // Fill the destination image on failure |
1141 // By using zero as the fill value, we will fill with the first | |
1142 // color in the color table for palette images, transparent | |
1143 // pixels for non-opaque images, and white for opaque images. | |
1144 // These are arbitrary choices but allow for consistent behavior. | |
1145 if (kNo_ZeroInitialized == opts.fZeroInitialized) { | 1150 if (kNo_ZeroInitialized == opts.fZeroInitialized) { |
scroggo
2015/04/14 13:10:32
Since fillColorOrIndex may not be 0, being zero in
msarett
2015/04/14 19:30:36
Yes you are right!
| |
1146 void* dstStart = get_dst_start_row(dst, dstRowBytes, y, fRowOrde r); | 1151 void* dstStart = get_dst_start_row(dst, dstRowBytes, y, fRowOrde r); |
1147 SkSwizzler::Fill(dstStart, dstInfo, dstRowBytes, dstInfo.height( ) - y, 0, | 1152 SkSwizzler::Fill(dstStart, dstInfo, dstRowBytes, dstInfo.height( ) - y, |
1148 colorPtr); | 1153 fillColorOrIndex, colorPtr); |
1149 } | 1154 } |
1150 return kIncompleteInput; | 1155 return kIncompleteInput; |
1151 } | 1156 } |
1152 | 1157 |
1153 // Decode the row in destination format | 1158 // Decode the row in destination format |
1154 uint32_t row; | 1159 uint32_t row; |
1155 if (kTopDown_RowOrder == fRowOrder) { | 1160 if (kTopDown_RowOrder == fRowOrder) { |
1156 row = y; | 1161 row = y; |
1157 } else { | 1162 } else { |
1158 row = height - 1 - y; | 1163 row = height - 1 - y; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1221 uint32_t alphaBit = | 1226 uint32_t alphaBit = |
1222 (srcBuffer.get()[quotient] >> shift) & 0x1; | 1227 (srcBuffer.get()[quotient] >> shift) & 0x1; |
1223 dstRow[x] &= alphaBit - 1; | 1228 dstRow[x] &= alphaBit - 1; |
1224 } | 1229 } |
1225 } | 1230 } |
1226 } | 1231 } |
1227 | 1232 |
1228 // Finished decoding the entire image | 1233 // Finished decoding the entire image |
1229 return kSuccess; | 1234 return kSuccess; |
1230 } | 1235 } |
OLD | NEW |