Chromium Code Reviews| 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 |