| 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 |