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 655 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. | 777 if (kNo_ZeroInitialized == opts.fZeroInitialized || 0 != fillColor)
{ |
779 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; |
| 1097 bool zeroFill = true; |
1095 switch (fBitsPerPixel) { | 1098 switch (fBitsPerPixel) { |
1096 case 1: | 1099 case 1: |
1097 config = SkSwizzler::kIndex1; | 1100 config = SkSwizzler::kIndex1; |
| 1101 fillColorOrIndex = 0; |
1098 break; | 1102 break; |
1099 case 2: | 1103 case 2: |
1100 config = SkSwizzler::kIndex2; | 1104 config = SkSwizzler::kIndex2; |
| 1105 fillColorOrIndex = 0; |
1101 break; | 1106 break; |
1102 case 4: | 1107 case 4: |
1103 config = SkSwizzler::kIndex4; | 1108 config = SkSwizzler::kIndex4; |
| 1109 fillColorOrIndex = 0; |
1104 break; | 1110 break; |
1105 case 8: | 1111 case 8: |
1106 config = SkSwizzler::kIndex; | 1112 config = SkSwizzler::kIndex; |
| 1113 fillColorOrIndex = 0; |
1107 break; | 1114 break; |
1108 case 24: | 1115 case 24: |
1109 config = SkSwizzler::kBGR; | 1116 config = SkSwizzler::kBGR; |
| 1117 fillColorOrIndex = SK_ColorBLACK; |
| 1118 zeroFill = false; |
1110 break; | 1119 break; |
1111 case 32: | 1120 case 32: |
1112 if (kOpaque_SkAlphaType == dstInfo.alphaType()) { | 1121 if (kOpaque_SkAlphaType == dstInfo.alphaType()) { |
1113 config = SkSwizzler::kBGRX; | 1122 config = SkSwizzler::kBGRX; |
| 1123 fillColorOrIndex = SK_ColorBLACK; |
| 1124 zeroFill = false; |
1114 } else { | 1125 } else { |
1115 config = SkSwizzler::kBGRA; | 1126 config = SkSwizzler::kBGRA; |
| 1127 fillColorOrIndex = SK_ColorTRANSPARENT; |
1116 } | 1128 } |
1117 break; | 1129 break; |
1118 default: | 1130 default: |
1119 SkASSERT(false); | 1131 SkASSERT(false); |
1120 return kInvalidInput; | 1132 return kInvalidInput; |
1121 } | 1133 } |
1122 | 1134 |
1123 // Get a pointer to the color table if it exists | 1135 // Get a pointer to the color table if it exists |
1124 const SkPMColor* colorPtr = NULL != fColorTable.get() ? fColorTable->readCol
ors() : NULL; | 1136 const SkPMColor* colorPtr = NULL != fColorTable.get() ? fColorTable->readCol
ors() : NULL; |
1125 | 1137 |
1126 // Create swizzler | 1138 // Create swizzler |
1127 SkAutoTDelete<SkSwizzler> swizzler(SkSwizzler::CreateSwizzler(config, | 1139 SkAutoTDelete<SkSwizzler> swizzler(SkSwizzler::CreateSwizzler(config, |
1128 colorPtr, dstInfo, dst, dstRowBytes, | 1140 colorPtr, dstInfo, dst, dstRowBytes, |
1129 SkImageGenerator::kNo_ZeroInitialized)); | 1141 SkImageGenerator::kNo_ZeroInitialized)); |
1130 | 1142 |
1131 // Allocate space for a row buffer and a source for the swizzler | 1143 // Allocate space for a row buffer and a source for the swizzler |
1132 SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, rowBytes)); | 1144 SkAutoTDeleteArray<uint8_t> srcBuffer(SkNEW_ARRAY(uint8_t, rowBytes)); |
1133 | 1145 |
1134 // Iterate over rows of the image | 1146 // Iterate over rows of the image |
1135 // FIXME: bool transparent = true; | 1147 // FIXME: bool transparent = true; |
1136 for (int y = 0; y < height; y++) { | 1148 for (int y = 0; y < height; y++) { |
1137 // Read a row of the input | 1149 // Read a row of the input |
1138 if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) { | 1150 if (stream()->read(srcBuffer.get(), rowBytes) != rowBytes) { |
1139 SkCodecPrintf("Warning: incomplete input stream.\n"); | 1151 SkCodecPrintf("Warning: incomplete input stream.\n"); |
1140 // Fill the destination image on failure | 1152 // Fill the destination image on failure |
1141 // By using zero as the fill value, we will fill with the first | 1153 if (kNo_ZeroInitialized == opts.fZeroInitialized || !zeroFill) { |
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) { | |
1146 void* dstStart = get_dst_start_row(dst, dstRowBytes, y, fRowOrde
r); | 1154 void* dstStart = get_dst_start_row(dst, dstRowBytes, y, fRowOrde
r); |
1147 SkSwizzler::Fill(dstStart, dstInfo, dstRowBytes, dstInfo.height(
) - y, 0, | 1155 SkSwizzler::Fill(dstStart, dstInfo, dstRowBytes, dstInfo.height(
) - y, |
1148 colorPtr); | 1156 fillColorOrIndex, colorPtr); |
1149 } | 1157 } |
1150 return kIncompleteInput; | 1158 return kIncompleteInput; |
1151 } | 1159 } |
1152 | 1160 |
1153 // Decode the row in destination format | 1161 // Decode the row in destination format |
1154 uint32_t row; | 1162 uint32_t row; |
1155 if (kTopDown_RowOrder == fRowOrder) { | 1163 if (kTopDown_RowOrder == fRowOrder) { |
1156 row = y; | 1164 row = y; |
1157 } else { | 1165 } else { |
1158 row = height - 1 - y; | 1166 row = height - 1 - y; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1221 uint32_t alphaBit = | 1229 uint32_t alphaBit = |
1222 (srcBuffer.get()[quotient] >> shift) & 0x1; | 1230 (srcBuffer.get()[quotient] >> shift) & 0x1; |
1223 dstRow[x] &= alphaBit - 1; | 1231 dstRow[x] &= alphaBit - 1; |
1224 } | 1232 } |
1225 } | 1233 } |
1226 } | 1234 } |
1227 | 1235 |
1228 // Finished decoding the entire image | 1236 // Finished decoding the entire image |
1229 return kSuccess; | 1237 return kSuccess; |
1230 } | 1238 } |
OLD | NEW |