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_libgif.h" | 8 #include "SkCodec_libgif.h" |
| 9 #include "SkCodecPriv.h" | 9 #include "SkCodecPriv.h" |
| 10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
| 11 #include "SkColorTable.h" | 11 #include "SkColorTable.h" |
| 12 #include "SkGifInterlaceIter.h" | |
| 13 #include "SkStream.h" | 12 #include "SkStream.h" |
| 14 #include "SkSwizzler.h" | 13 #include "SkSwizzler.h" |
| 15 #include "SkUtils.h" | 14 #include "SkUtils.h" |
| 16 | 15 |
| 17 /* | 16 /* |
| 18 * Checks the start of the stream to see if the image is a gif | 17 * Checks the start of the stream to see if the image is a gif |
| 19 */ | 18 */ |
| 20 bool SkGifCodec::IsGif(SkStream* stream) { | 19 bool SkGifCodec::IsGif(SkStream* stream) { |
| 21 char buf[GIF_STAMP_LEN]; | 20 char buf[GIF_STAMP_LEN]; |
| 22 if (stream->read(buf, GIF_STAMP_LEN) == GIF_STAMP_LEN) { | 21 if (stream->read(buf, GIF_STAMP_LEN) == GIF_STAMP_LEN) { |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 115 // There should only be one graphics control extension for the image frame | 114 // There should only be one graphics control extension for the image frame |
| 116 break; | 115 break; |
| 117 } | 116 } |
| 118 } | 117 } |
| 119 | 118 |
| 120 // Use maximum unsigned int (surely an invalid index) to indicate that a val id | 119 // Use maximum unsigned int (surely an invalid index) to indicate that a val id |
| 121 // index was not found. | 120 // index was not found. |
| 122 return SK_MaxU32; | 121 return SK_MaxU32; |
| 123 } | 122 } |
| 124 | 123 |
| 124 static inline uint32_t ceil_div(uint32_t a, uint32_t b) { | |
| 125 return (a + b - 1) / b; | |
| 126 } | |
| 127 | |
| 128 /* | |
| 129 * Gets the output row corresponding to the encoded row for interlaced gifs | |
| 130 */ | |
| 131 static uint32_t get_output_row_interlaced(uint32_t encodedRow, uint32_t height) { | |
| 132 SkASSERT(encodedRow < height); | |
| 133 // First pass | |
| 134 if (encodedRow * 8 < height) { | |
| 135 return encodedRow * 8; | |
| 136 // Second pass | |
| 137 } else if (encodedRow * 4 < height) { | |
|
scroggo
2015/08/28 13:42:32
nit: These do not need to be else statements, sinc
msarett
2015/08/28 14:30:36
Fixing.
| |
| 138 return 4 + 8 * (encodedRow - ceil_div(height, 8)); | |
| 139 // Third pass | |
| 140 } else if (encodedRow * 2 < height) { | |
| 141 return 2 + 4 * (encodedRow - ceil_div(height, 4)); | |
| 142 // Fourth pass | |
| 143 } else { | |
| 144 return 1 + 2 * (encodedRow - ceil_div(height, 2)); | |
| 145 } | |
| 146 } | |
| 147 | |
| 125 /* | 148 /* |
| 126 * Read enough of the stream to initialize the SkGifCodec. | 149 * Read enough of the stream to initialize the SkGifCodec. |
| 127 * Returns a bool representing success or failure. | 150 * Returns a bool representing success or failure. |
| 128 * | 151 * |
| 129 * @param codecOut | 152 * @param codecOut |
| 130 * If it returned true, and codecOut was not NULL, | 153 * If it returned true, and codecOut was not NULL, |
| 131 * codecOut will be set to a new SkGifCodec. | 154 * codecOut will be set to a new SkGifCodec. |
| 132 * | 155 * |
| 133 * @param gifOut | 156 * @param gifOut |
| 134 * If it returned true, and codecOut was NULL, | 157 * If it returned true, and codecOut was NULL, |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 417 SkSwizzler::kIndex, colorTable, dstInfo, | 440 SkSwizzler::kIndex, colorTable, dstInfo, |
| 418 zeroInit, this->getInfo())); | 441 zeroInit, this->getInfo())); |
| 419 } | 442 } |
| 420 | 443 |
| 421 // Stores output from dgiflib and input to the swizzler | 444 // Stores output from dgiflib and input to the swizzler |
| 422 SkAutoTDeleteArray<uint8_t> | 445 SkAutoTDeleteArray<uint8_t> |
| 423 buffer(SkNEW_ARRAY(uint8_t, innerWidth)); | 446 buffer(SkNEW_ARRAY(uint8_t, innerWidth)); |
| 424 | 447 |
| 425 // Check the interlace flag and iterate over rows of the input | 448 // Check the interlace flag and iterate over rows of the input |
| 426 if (fGif->Image.Interlace) { | 449 if (fGif->Image.Interlace) { |
| 427 // In interlace mode, the rows of input are rearranged in | |
| 428 // the output image. We use an iterator to take care of | |
| 429 // the rearranging. | |
| 430 SkGifInterlaceIter iter(innerHeight); | |
| 431 for (int32_t y = 0; y < innerHeight; y++) { | 450 for (int32_t y = 0; y < innerHeight; y++) { |
| 432 if (GIF_ERROR == DGifGetLine(fGif, buffer.get(), | 451 if (GIF_ERROR == DGifGetLine(fGif, buffer.get(), |
| 433 innerWidth)) { | 452 innerWidth)) { |
| 434 // Recover from error by filling remainder of image | 453 // Recover from error by filling remainder of image |
| 435 if (!skipBackground) { | 454 if (!skipBackground) { |
| 436 memset(buffer.get(), fillIndex, innerWidth); | 455 memset(buffer.get(), fillIndex, innerWidth); |
| 437 for (; y < innerHeight; y++) { | 456 for (; y < innerHeight; y++) { |
| 438 void* dstRow = SkTAddOffset<void>(dst, | 457 void* dstRow = SkTAddOffset<void>(dst, |
| 439 dstRowBytes * iter.nextY()); | 458 dstRowBytes * |
| 459 get_output_row_interlaced(y, innerHe ight)); | |
| 440 swizzler->swizzle(dstRow, buffer.get()); | 460 swizzler->swizzle(dstRow, buffer.get()); |
| 441 } | 461 } |
| 442 } | 462 } |
| 443 return gif_error(SkStringPrintf( | 463 return gif_error(SkStringPrintf( |
| 444 "Could not decode line %d of %d.\n", | 464 "Could not decode line %d of %d.\n", |
| 445 y, height - 1).c_str(), kIncompleteInput); | 465 y, height - 1).c_str(), kIncompleteInput); |
| 446 } | 466 } |
| 447 void* dstRow = SkTAddOffset<void>( | 467 void* dstRow = SkTAddOffset<void>( |
| 448 dst, dstRowBytes * iter.nextY()); | 468 dst, dstRowBytes * |
| 469 get_output_row_interlaced(y, innerHeight)); | |
| 449 swizzler->swizzle(dstRow, buffer.get()); | 470 swizzler->swizzle(dstRow, buffer.get()); |
| 450 } | 471 } |
| 451 } else { | 472 } else { |
| 452 // Standard mode | 473 // Standard mode |
| 453 void* dstRow = dst; | 474 void* dstRow = dst; |
| 454 for (int32_t y = 0; y < innerHeight; y++) { | 475 for (int32_t y = 0; y < innerHeight; y++) { |
| 455 if (GIF_ERROR == DGifGetLine(fGif, buffer.get(), | 476 if (GIF_ERROR == DGifGetLine(fGif, buffer.get(), |
| 456 innerWidth)) { | 477 innerWidth)) { |
| 457 if (!skipBackground) { | 478 if (!skipBackground) { |
| 458 SkSwizzler::Fill(dstRow, dstInfo, dstRowBytes, | 479 SkSwizzler::Fill(dstRow, dstInfo, dstRowBytes, |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 527 // giflib returns an error code if the record type is not known. | 548 // giflib returns an error code if the record type is not known. |
| 528 // We should catch this error immediately. | 549 // We should catch this error immediately. |
| 529 SkASSERT(false); | 550 SkASSERT(false); |
| 530 break; | 551 break; |
| 531 } | 552 } |
| 532 } while (TERMINATE_RECORD_TYPE != recordType); | 553 } while (TERMINATE_RECORD_TYPE != recordType); |
| 533 | 554 |
| 534 return gif_error("Could not find any images to decode in gif file.\n", | 555 return gif_error("Could not find any images to decode in gif file.\n", |
| 535 kInvalidInput); | 556 kInvalidInput); |
| 536 } | 557 } |
| OLD | NEW |