| 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 "SkBmpStandardCodec.h" | 8 #include "SkBmpStandardCodec.h" |
| 9 #include "SkCodecPriv.h" | 9 #include "SkCodecPriv.h" |
| 10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 } | 46 } |
| 47 if (dstInfo.dimensions() != this->getInfo().dimensions()) { | 47 if (dstInfo.dimensions() != this->getInfo().dimensions()) { |
| 48 SkCodecPrintf("Error: scaling not supported.\n"); | 48 SkCodecPrintf("Error: scaling not supported.\n"); |
| 49 return kInvalidScale; | 49 return kInvalidScale; |
| 50 } | 50 } |
| 51 if (!conversion_possible(dstInfo, this->getInfo())) { | 51 if (!conversion_possible(dstInfo, this->getInfo())) { |
| 52 SkCodecPrintf("Error: cannot convert input type to output type.\n"); | 52 SkCodecPrintf("Error: cannot convert input type to output type.\n"); |
| 53 return kInvalidConversion; | 53 return kInvalidConversion; |
| 54 } | 54 } |
| 55 | 55 |
| 56 // Create the color table if necessary and prepare the stream for decode | 56 Result result = this->prepareToDecode(dstInfo, opts, inputColorPtr, inputCol
orCount); |
| 57 // Note that if it is non-NULL, inputColorCount will be modified | 57 if (kSuccess != result) { |
| 58 if (!this->createColorTable(dstInfo.alphaType(), inputColorCount)) { | 58 return result; |
| 59 SkCodecPrintf("Error: could not create color table.\n"); | |
| 60 return kInvalidInput; | |
| 61 } | |
| 62 | |
| 63 // Copy the color table to the client if necessary | |
| 64 copy_color_table(dstInfo, fColorTable, inputColorPtr, inputColorCount); | |
| 65 | |
| 66 // Initialize a swizzler if necessary | |
| 67 if (!this->initializeSwizzler(dstInfo, opts)) { | |
| 68 SkCodecPrintf("Error: cannot initialize swizzler.\n"); | |
| 69 return kInvalidConversion; | |
| 70 } | 59 } |
| 71 | 60 |
| 72 return this->decode(dstInfo, dst, dstRowBytes, opts); | 61 return this->decode(dstInfo, dst, dstRowBytes, opts); |
| 73 } | 62 } |
| 74 | 63 |
| 75 /* | 64 /* |
| 76 * Process the color table for the bmp input | 65 * Process the color table for the bmp input |
| 77 */ | 66 */ |
| 78 bool SkBmpStandardCodec::createColorTable(SkAlphaType alphaType, int* numColors
) { | 67 bool SkBmpStandardCodec::createColorTable(SkAlphaType alphaType, int* numColors
) { |
| 79 // Allocate memory for color table | 68 // Allocate memory for color table |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 } | 152 } |
| 164 } | 153 } |
| 165 | 154 |
| 166 // Return true on success | 155 // Return true on success |
| 167 return true; | 156 return true; |
| 168 } | 157 } |
| 169 | 158 |
| 170 bool SkBmpStandardCodec::initializeSwizzler(const SkImageInfo& dstInfo, | 159 bool SkBmpStandardCodec::initializeSwizzler(const SkImageInfo& dstInfo, |
| 171 const Options& opts) { | 160 const Options& opts) { |
| 172 // Allocate space for a row buffer | 161 // Allocate space for a row buffer |
| 173 const size_t rowBytes = SkAlign4(compute_row_bytes(dstInfo.width(), this->bi
tsPerPixel())); | 162 const size_t rowBytes = SkAlign4(compute_row_bytes(this->getInfo().width(), |
| 163 this->bitsPerPixel())); |
| 174 fSrcBuffer.reset(SkNEW_ARRAY(uint8_t, rowBytes)); | 164 fSrcBuffer.reset(SkNEW_ARRAY(uint8_t, rowBytes)); |
| 175 | 165 |
| 176 // Get swizzler configuration | 166 // Get swizzler configuration |
| 177 SkSwizzler::SrcConfig config; | 167 SkSwizzler::SrcConfig config; |
| 178 switch (this->bitsPerPixel()) { | 168 switch (this->bitsPerPixel()) { |
| 179 case 1: | 169 case 1: |
| 180 config = SkSwizzler::kIndex1; | 170 config = SkSwizzler::kIndex1; |
| 181 break; | 171 break; |
| 182 case 2: | 172 case 2: |
| 183 config = SkSwizzler::kIndex2; | 173 config = SkSwizzler::kIndex2; |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 SkASSERT(false); | 234 SkASSERT(false); |
| 245 return 0; | 235 return 0; |
| 246 } | 236 } |
| 247 return fillColorOrIndex; | 237 return fillColorOrIndex; |
| 248 } | 238 } |
| 249 | 239 |
| 250 /* | 240 /* |
| 251 * Performs the bitmap decoding for standard input format | 241 * Performs the bitmap decoding for standard input format |
| 252 */ | 242 */ |
| 253 SkCodec::Result SkBmpStandardCodec::decode(const SkImageInfo& dstInfo, | 243 SkCodec::Result SkBmpStandardCodec::decode(const SkImageInfo& dstInfo, |
| 254 void* dst, size_t dstRowBytes, | 244 void* dst, size_t dstRowBytes, |
| 255 const Options& opts) { | 245 const Options& opts) { |
| 256 // Set constant values | 246 // Set constant values |
| 257 const int width = dstInfo.width(); | 247 const int width = this->getInfo().width(); |
| 258 const int height = dstInfo.height(); | 248 const int height = dstInfo.height(); |
| 259 const size_t rowBytes = SkAlign4(compute_row_bytes(width, this->bitsPerPixel
())); | 249 const size_t rowBytes = SkAlign4(compute_row_bytes(width, this->bitsPerPixel
())); |
| 260 | 250 |
| 261 // Iterate over rows of the image | 251 // Iterate over rows of the image |
| 262 for (int y = 0; y < height; y++) { | 252 for (int y = 0; y < height; y++) { |
| 263 // Read a row of the input | 253 // Read a row of the input |
| 264 if (this->stream()->read(fSrcBuffer.get(), rowBytes) != rowBytes) { | 254 if (this->stream()->read(fSrcBuffer.get(), rowBytes) != rowBytes) { |
| 265 SkCodecPrintf("Warning: incomplete input stream.\n"); | 255 SkCodecPrintf("Warning: incomplete input stream.\n"); |
| 266 // Fill the destination image on failure | 256 // Fill the destination image on failure |
| 267 // Get the fill color/index and check if it is 0 | 257 // Get the fill color/index and check if it is 0 |
| 268 uint32_t fillColorOrIndex = get_fill_color_or_index(this->bitsPerPix
el(), | 258 uint32_t fillColorOrIndex = get_fill_color_or_index(this->bitsPerPix
el(), |
| 269 dstInfo.alphaType()); | 259 dstInfo.alphaType()); |
| 270 bool zeroFill = (0 == fillColorOrIndex); | 260 bool zeroFill = (0 == fillColorOrIndex); |
| 271 | 261 |
| 272 if (kNo_ZeroInitialized == opts.fZeroInitialized || !zeroFill) { | 262 if (kNo_ZeroInitialized == opts.fZeroInitialized || !zeroFill) { |
| 273 // Get a pointer to the color table if it exists | 263 // Get a pointer to the color table if it exists |
| 274 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); | 264 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); |
| 275 | 265 |
| 276 void* dstStart = this->getDstStartRow(dst, dstRowBytes, y); | 266 void* dstStart = this->getDstStartRow(dst, dstRowBytes, y); |
| 277 SkSwizzler::Fill(dstStart, dstInfo, dstRowBytes, dstInfo.height(
) - y, | 267 SkSwizzler::Fill(dstStart, dstInfo, dstRowBytes, dstInfo.height(
) - y, |
| 278 fillColorOrIndex, colorPtr); | 268 fillColorOrIndex, colorPtr); |
| 279 } | 269 } |
| 280 return kIncompleteInput; | 270 return kIncompleteInput; |
| 281 } | 271 } |
| 282 | 272 |
| 283 // Decode the row in destination format | 273 // Decode the row in destination format |
| 284 uint32_t row; | 274 uint32_t row = this->getDstRow(y); |
| 285 if (SkBmpCodec::kTopDown_RowOrder == this->rowOrder()) { | |
| 286 row = y; | |
| 287 } else { | |
| 288 row = height - 1 - y; | |
| 289 } | |
| 290 | 275 |
| 291 void* dstRow = SkTAddOffset<void>(dst, row * dstRowBytes); | 276 void* dstRow = SkTAddOffset<void>(dst, row * dstRowBytes); |
| 292 fSwizzler->swizzle(dstRow, fSrcBuffer.get()); | 277 fSwizzler->swizzle(dstRow, fSrcBuffer.get()); |
| 293 } | 278 } |
| 294 | 279 |
| 295 // Finally, apply the AND mask for bmp-in-ico images | 280 // Finally, apply the AND mask for bmp-in-ico images |
| 296 if (fInIco) { | 281 if (fInIco) { |
| 297 // BMP in ICO have transparency, so this cannot be 565, and this mask | 282 // BMP in ICO have transparency, so this cannot be 565, and this mask |
| 298 // prevents us from using kIndex8. The below code depends on the output | 283 // prevents us from using kIndex8. The below code depends on the output |
| 299 // being an SkPMColor. | 284 // being an SkPMColor. |
| 300 SkASSERT(dstInfo.colorType() == kN32_SkColorType); | 285 SkASSERT(dstInfo.colorType() == kN32_SkColorType); |
| 301 | 286 |
| 302 // The AND mask is always 1 bit per pixel | 287 // The AND mask is always 1 bit per pixel |
| 303 const size_t rowBytes = SkAlign4(compute_row_bytes(width, 1)); | 288 const size_t rowBytes = SkAlign4(compute_row_bytes(width, 1)); |
| 304 | 289 |
| 305 SkPMColor* dstPtr = (SkPMColor*) dst; | 290 SkPMColor* dstPtr = (SkPMColor*) dst; |
| 306 for (int y = 0; y < height; y++) { | 291 for (int y = 0; y < height; y++) { |
| 307 // The srcBuffer will at least be large enough | 292 // The srcBuffer will at least be large enough |
| 308 if (stream()->read(fSrcBuffer.get(), rowBytes) != rowBytes) { | 293 if (stream()->read(fSrcBuffer.get(), rowBytes) != rowBytes) { |
| 309 SkCodecPrintf("Warning: incomplete AND mask for bmp-in-ico.\n"); | 294 SkCodecPrintf("Warning: incomplete AND mask for bmp-in-ico.\n"); |
| 310 return kIncompleteInput; | 295 return kIncompleteInput; |
| 311 } | 296 } |
| 312 | 297 |
| 313 int row; | 298 int row = this->getDstRow(y); |
| 314 if (SkBmpCodec::kBottomUp_RowOrder == this->rowOrder()) { | |
| 315 row = height - y - 1; | |
| 316 } else { | |
| 317 row = y; | |
| 318 } | |
| 319 | 299 |
| 320 SkPMColor* dstRow = | 300 SkPMColor* dstRow = |
| 321 SkTAddOffset<SkPMColor>(dstPtr, row * dstRowBytes); | 301 SkTAddOffset<SkPMColor>(dstPtr, row * dstRowBytes); |
| 322 | 302 |
| 323 for (int x = 0; x < width; x++) { | 303 for (int x = 0; x < width; x++) { |
| 324 int quotient; | 304 int quotient; |
| 325 int modulus; | 305 int modulus; |
| 326 SkTDivMod(x, 8, "ient, &modulus); | 306 SkTDivMod(x, 8, "ient, &modulus); |
| 327 uint32_t shift = 7 - modulus; | 307 uint32_t shift = 7 - modulus; |
| 328 uint32_t alphaBit = | 308 uint32_t alphaBit = |
| 329 (fSrcBuffer.get()[quotient] >> shift) & 0x1; | 309 (fSrcBuffer.get()[quotient] >> shift) & 0x1; |
| 330 dstRow[x] &= alphaBit - 1; | 310 dstRow[x] &= alphaBit - 1; |
| 331 } | 311 } |
| 332 } | 312 } |
| 333 } | 313 } |
| 334 | 314 |
| 335 // Finished decoding the entire image | 315 // Finished decoding the entire image |
| 336 return kSuccess; | 316 return kSuccess; |
| 337 } | 317 } |
| 318 |
| 319 SkCodec::Result SkBmpStandardCodec::prepareToDecode(const SkImageInfo& dstInfo, |
| 320 const SkCodec::Options& options, SkPMColor inputColorPtr[], int* inputCo
lorCount) { |
| 321 // Create the color table if necessary and prepare the stream for decode |
| 322 // Note that if it is non-NULL, inputColorCount will be modified |
| 323 if (!this->createColorTable(dstInfo.alphaType(), inputColorCount)) { |
| 324 SkCodecPrintf("Error: could not create color table.\n"); |
| 325 return SkCodec::kInvalidInput; |
| 326 } |
| 327 |
| 328 // Copy the color table to the client if necessary |
| 329 copy_color_table(dstInfo, this->fColorTable, inputColorPtr, inputColorCount)
; |
| 330 |
| 331 // Initialize a swizzler if necessary |
| 332 if (!this->initializeSwizzler(dstInfo, options)) { |
| 333 SkCodecPrintf("Error: cannot initialize swizzler.\n"); |
| 334 return SkCodec::kInvalidConversion; |
| 335 } |
| 336 return SkCodec::kSuccess; |
| 337 } |
| OLD | NEW |