| 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 "SkBmpRLECodec.h" | 8 #include "SkBmpRLECodec.h" |
| 9 #include "SkCodecPriv.h" | 9 #include "SkCodecPriv.h" |
| 10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 63 *rowsDecoded = dstInfo.height(); | 63 *rowsDecoded = dstInfo.height(); |
| 64 return kIncompleteInput; | 64 return kIncompleteInput; |
| 65 } | 65 } |
| 66 | 66 |
| 67 return kSuccess; | 67 return kSuccess; |
| 68 } | 68 } |
| 69 | 69 |
| 70 /* | 70 /* |
| 71 * Process the color table for the bmp input | 71 * Process the color table for the bmp input |
| 72 */ | 72 */ |
| 73 bool SkBmpRLECodec::createColorTable(int* numColors) { | 73 bool SkBmpRLECodec::createColorTable(SkColorType dstColorType, int* numColors)
{ |
| 74 // Allocate memory for color table | 74 // Allocate memory for color table |
| 75 uint32_t colorBytes = 0; | 75 uint32_t colorBytes = 0; |
| 76 SkPMColor colorTable[256]; | 76 SkPMColor colorTable[256]; |
| 77 if (this->bitsPerPixel() <= 8) { | 77 if (this->bitsPerPixel() <= 8) { |
| 78 // Inform the caller of the number of colors | 78 // Inform the caller of the number of colors |
| 79 uint32_t maxColors = 1 << this->bitsPerPixel(); | 79 uint32_t maxColors = 1 << this->bitsPerPixel(); |
| 80 if (nullptr != numColors) { | 80 if (nullptr != numColors) { |
| 81 // We set the number of colors to maxColors in order to ensure | 81 // We set the number of colors to maxColors in order to ensure |
| 82 // safe memory accesses. Otherwise, an invalid pixel could | 82 // safe memory accesses. Otherwise, an invalid pixel could |
| 83 // access memory outside of our color table array. | 83 // access memory outside of our color table array. |
| 84 *numColors = maxColors; | 84 *numColors = maxColors; |
| 85 } | 85 } |
| 86 // Don't bother reading more than maxColors. | 86 // Don't bother reading more than maxColors. |
| 87 const uint32_t numColorsToRead = | 87 const uint32_t numColorsToRead = |
| 88 fNumColors == 0 ? maxColors : SkTMin(fNumColors, maxColors); | 88 fNumColors == 0 ? maxColors : SkTMin(fNumColors, maxColors); |
| 89 | 89 |
| 90 // Read the color table from the stream | 90 // Read the color table from the stream |
| 91 colorBytes = numColorsToRead * fBytesPerColor; | 91 colorBytes = numColorsToRead * fBytesPerColor; |
| 92 SkAutoTDeleteArray<uint8_t> cBuffer(new uint8_t[colorBytes]); | 92 SkAutoTDeleteArray<uint8_t> cBuffer(new uint8_t[colorBytes]); |
| 93 if (stream()->read(cBuffer.get(), colorBytes) != colorBytes) { | 93 if (stream()->read(cBuffer.get(), colorBytes) != colorBytes) { |
| 94 SkCodecPrintf("Error: unable to read color table.\n"); | 94 SkCodecPrintf("Error: unable to read color table.\n"); |
| 95 return false; | 95 return false; |
| 96 } | 96 } |
| 97 | 97 |
| 98 // Fill in the color table | 98 // Fill in the color table |
| 99 PackColorProc packARGB = choose_pack_color_proc(false, dstColorType); |
| 99 uint32_t i = 0; | 100 uint32_t i = 0; |
| 100 for (; i < numColorsToRead; i++) { | 101 for (; i < numColorsToRead; i++) { |
| 101 uint8_t blue = get_byte(cBuffer.get(), i*fBytesPerColor); | 102 uint8_t blue = get_byte(cBuffer.get(), i*fBytesPerColor); |
| 102 uint8_t green = get_byte(cBuffer.get(), i*fBytesPerColor + 1); | 103 uint8_t green = get_byte(cBuffer.get(), i*fBytesPerColor + 1); |
| 103 uint8_t red = get_byte(cBuffer.get(), i*fBytesPerColor + 2); | 104 uint8_t red = get_byte(cBuffer.get(), i*fBytesPerColor + 2); |
| 104 colorTable[i] = SkPackARGB32NoCheck(0xFF, red, green, blue); | 105 colorTable[i] = packARGB(0xFF, red, green, blue); |
| 105 } | 106 } |
| 106 | 107 |
| 107 // To avoid segmentation faults on bad pixel data, fill the end of the | 108 // To avoid segmentation faults on bad pixel data, fill the end of the |
| 108 // color table with black. This is the same the behavior as the | 109 // color table with black. This is the same the behavior as the |
| 109 // chromium decoder. | 110 // chromium decoder. |
| 110 for (; i < maxColors; i++) { | 111 for (; i < maxColors; i++) { |
| 111 colorTable[i] = SkPackARGB32NoCheck(0xFF, 0, 0, 0); | 112 colorTable[i] = SkPackARGB32NoCheck(0xFF, 0, 0, 0); |
| 112 } | 113 } |
| 113 | 114 |
| 114 // Set the color table | 115 // Set the color table |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 void SkBmpRLECodec::setPixel(void* dst, size_t dstRowBytes, | 202 void SkBmpRLECodec::setPixel(void* dst, size_t dstRowBytes, |
| 202 const SkImageInfo& dstInfo, uint32_t x, uint32_t y, | 203 const SkImageInfo& dstInfo, uint32_t x, uint32_t y, |
| 203 uint8_t index) { | 204 uint8_t index) { |
| 204 if (dst && is_coord_necessary(x, fSampleX, dstInfo.width())) { | 205 if (dst && is_coord_necessary(x, fSampleX, dstInfo.width())) { |
| 205 // Set the row | 206 // Set the row |
| 206 uint32_t row = this->getDstRow(y, dstInfo.height()); | 207 uint32_t row = this->getDstRow(y, dstInfo.height()); |
| 207 | 208 |
| 208 // Set the pixel based on destination color type | 209 // Set the pixel based on destination color type |
| 209 const int dstX = get_dst_coord(x, fSampleX); | 210 const int dstX = get_dst_coord(x, fSampleX); |
| 210 switch (dstInfo.colorType()) { | 211 switch (dstInfo.colorType()) { |
| 211 case kN32_SkColorType: { | 212 case kRGBA_8888_SkColorType: |
| 213 case kBGRA_8888_SkColorType: { |
| 212 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, row * (int) dst
RowBytes); | 214 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, row * (int) dst
RowBytes); |
| 213 dstRow[dstX] = fColorTable->operator[](index); | 215 dstRow[dstX] = fColorTable->operator[](index); |
| 214 break; | 216 break; |
| 215 } | 217 } |
| 216 case kRGB_565_SkColorType: { | 218 case kRGB_565_SkColorType: { |
| 217 uint16_t* dstRow = SkTAddOffset<uint16_t>(dst, row * (int) dstRo
wBytes); | 219 uint16_t* dstRow = SkTAddOffset<uint16_t>(dst, row * (int) dstRo
wBytes); |
| 218 dstRow[dstX] = SkPixel32ToPixel16(fColorTable->operator[](index)
); | 220 dstRow[dstX] = SkPixel32ToPixel16(fColorTable->operator[](index)
); |
| 219 break; | 221 break; |
| 220 } | 222 } |
| 221 default: | 223 default: |
| (...skipping 12 matching lines...) Expand all Loading... |
| 234 const SkImageInfo& dstInfo, uint32_t x, | 236 const SkImageInfo& dstInfo, uint32_t x, |
| 235 uint32_t y, uint8_t red, uint8_t green, | 237 uint32_t y, uint8_t red, uint8_t green, |
| 236 uint8_t blue) { | 238 uint8_t blue) { |
| 237 if (dst && is_coord_necessary(x, fSampleX, dstInfo.width())) { | 239 if (dst && is_coord_necessary(x, fSampleX, dstInfo.width())) { |
| 238 // Set the row | 240 // Set the row |
| 239 uint32_t row = this->getDstRow(y, dstInfo.height()); | 241 uint32_t row = this->getDstRow(y, dstInfo.height()); |
| 240 | 242 |
| 241 // Set the pixel based on destination color type | 243 // Set the pixel based on destination color type |
| 242 const int dstX = get_dst_coord(x, fSampleX); | 244 const int dstX = get_dst_coord(x, fSampleX); |
| 243 switch (dstInfo.colorType()) { | 245 switch (dstInfo.colorType()) { |
| 244 case kN32_SkColorType: { | 246 case kRGBA_8888_SkColorType: { |
| 245 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, row * (int) dst
RowBytes); | 247 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, row * (int) dst
RowBytes); |
| 246 dstRow[dstX] = SkPackARGB32NoCheck(0xFF, red, green, blue); | 248 dstRow[dstX] = SkPackARGB_as_RGBA(0xFF, red, green, blue); |
| 249 break; |
| 250 } |
| 251 case kBGRA_8888_SkColorType: { |
| 252 SkPMColor* dstRow = SkTAddOffset<SkPMColor>(dst, row * (int) dst
RowBytes); |
| 253 dstRow[dstX] = SkPackARGB_as_BGRA(0xFF, red, green, blue); |
| 247 break; | 254 break; |
| 248 } | 255 } |
| 249 case kRGB_565_SkColorType: { | 256 case kRGB_565_SkColorType: { |
| 250 uint16_t* dstRow = SkTAddOffset<uint16_t>(dst, row * (int) dstRo
wBytes); | 257 uint16_t* dstRow = SkTAddOffset<uint16_t>(dst, row * (int) dstRo
wBytes); |
| 251 dstRow[dstX] = SkPack888ToRGB16(red, green, blue); | 258 dstRow[dstX] = SkPack888ToRGB16(red, green, blue); |
| 252 break; | 259 break; |
| 253 } | 260 } |
| 254 default: | 261 default: |
| 255 // This case should not be reached. We should catch an invalid | 262 // This case should not be reached. We should catch an invalid |
| 256 // color type when we check that the conversion is possible. | 263 // color type when we check that the conversion is possible. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 268 return kUnimplemented; | 275 return kUnimplemented; |
| 269 } | 276 } |
| 270 | 277 |
| 271 // Reset fSampleX. If it needs to be a value other than 1, it will get modif
ied by | 278 // Reset fSampleX. If it needs to be a value other than 1, it will get modif
ied by |
| 272 // the sampler. | 279 // the sampler. |
| 273 fSampleX = 1; | 280 fSampleX = 1; |
| 274 fLinesToSkip = 0; | 281 fLinesToSkip = 0; |
| 275 | 282 |
| 276 // Create the color table if necessary and prepare the stream for decode | 283 // Create the color table if necessary and prepare the stream for decode |
| 277 // Note that if it is non-NULL, inputColorCount will be modified | 284 // Note that if it is non-NULL, inputColorCount will be modified |
| 278 if (!this->createColorTable(inputColorCount)) { | 285 if (!this->createColorTable(dstInfo.colorType(), inputColorCount)) { |
| 279 SkCodecPrintf("Error: could not create color table.\n"); | 286 SkCodecPrintf("Error: could not create color table.\n"); |
| 280 return SkCodec::kInvalidInput; | 287 return SkCodec::kInvalidInput; |
| 281 } | 288 } |
| 282 | 289 |
| 283 // Copy the color table to the client if necessary | 290 // Copy the color table to the client if necessary |
| 284 copy_color_table(dstInfo, this->fColorTable, inputColorPtr, inputColorCount)
; | 291 copy_color_table(dstInfo, this->fColorTable, inputColorPtr, inputColorCount)
; |
| 285 | 292 |
| 286 // Initialize a buffer for encoded RLE data | 293 // Initialize a buffer for encoded RLE data |
| 287 fRLEBytes = fOrigRLEBytes; | 294 fRLEBytes = fOrigRLEBytes; |
| 288 if (!this->initializeStreamBuffer()) { | 295 if (!this->initializeStreamBuffer()) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 308 const int width = this->getInfo().width(); | 315 const int width = this->getInfo().width(); |
| 309 int height = info.height(); | 316 int height = info.height(); |
| 310 | 317 |
| 311 // Account for sampling. | 318 // Account for sampling. |
| 312 SkImageInfo dstInfo = info.makeWH(get_scaled_dimension(width, fSampleX), hei
ght); | 319 SkImageInfo dstInfo = info.makeWH(get_scaled_dimension(width, fSampleX), hei
ght); |
| 313 | 320 |
| 314 // Set the background as transparent. Then, if the RLE code skips pixels, | 321 // Set the background as transparent. Then, if the RLE code skips pixels, |
| 315 // the skipped pixels will be transparent. | 322 // the skipped pixels will be transparent. |
| 316 // Because of the need for transparent pixels, kN32 is the only color | 323 // Because of the need for transparent pixels, kN32 is the only color |
| 317 // type that makes sense for the destination format. | 324 // type that makes sense for the destination format. |
| 318 SkASSERT(kN32_SkColorType == dstInfo.colorType()); | 325 SkASSERT(kRGBA_8888_SkColorType == dstInfo.colorType() || |
| 326 kBGRA_8888_SkColorType == dstInfo.colorType()); |
| 319 if (dst) { | 327 if (dst) { |
| 320 SkSampler::Fill(dstInfo, dst, dstRowBytes, SK_ColorTRANSPARENT, opts.fZe
roInitialized); | 328 SkSampler::Fill(dstInfo, dst, dstRowBytes, SK_ColorTRANSPARENT, opts.fZe
roInitialized); |
| 321 } | 329 } |
| 322 | 330 |
| 323 // Adjust the height and the dst if the previous call to decodeRows() left u
s | 331 // Adjust the height and the dst if the previous call to decodeRows() left u
s |
| 324 // with lines that need to be skipped. | 332 // with lines that need to be skipped. |
| 325 if (height > fLinesToSkip) { | 333 if (height > fLinesToSkip) { |
| 326 height -= fLinesToSkip; | 334 height -= fLinesToSkip; |
| 327 dst = SkTAddOffset<void>(dst, fLinesToSkip * dstRowBytes); | 335 dst = SkTAddOffset<void>(dst, fLinesToSkip * dstRowBytes); |
| 328 fLinesToSkip = 0; | 336 fLinesToSkip = 0; |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 539 fSampler.reset(new SkBmpRLESampler(this)); | 547 fSampler.reset(new SkBmpRLESampler(this)); |
| 540 } | 548 } |
| 541 | 549 |
| 542 return fSampler; | 550 return fSampler; |
| 543 } | 551 } |
| 544 | 552 |
| 545 int SkBmpRLECodec::setSampleX(int sampleX){ | 553 int SkBmpRLECodec::setSampleX(int sampleX){ |
| 546 fSampleX = sampleX; | 554 fSampleX = sampleX; |
| 547 return get_scaled_dimension(this->getInfo().width(), sampleX); | 555 return get_scaled_dimension(this->getInfo().width(), sampleX); |
| 548 } | 556 } |
| OLD | NEW |