| 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" |
| (...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 421 | 421 |
| 422 // Modify the destination info | 422 // Modify the destination info |
| 423 const SkImageInfo subsetDstInfo = | 423 const SkImageInfo subsetDstInfo = |
| 424 dstInfo.makeWH(innerWidth, innerHeight); | 424 dstInfo.makeWH(innerWidth, innerHeight); |
| 425 | 425 |
| 426 // Fill the destination with the fill color | 426 // Fill the destination with the fill color |
| 427 // FIXME: This may not be the behavior that we want for | 427 // FIXME: This may not be the behavior that we want for |
| 428 // animated gifs where we draw on top of the | 428 // animated gifs where we draw on top of the |
| 429 // previous frame. | 429 // previous frame. |
| 430 if (!skipBackground) { | 430 if (!skipBackground) { |
| 431 SkSwizzler::Fill(dst, dstInfo, dstRowBytes, height, fill
Index, colorTable); | 431 SkSwizzler::Fill(dst, dstInfo, dstRowBytes, height, |
| 432 fillIndex, colorTable); |
| 432 } | 433 } |
| 433 | 434 |
| 434 // Modify the dst pointer | 435 // Modify the dst pointer |
| 435 const int32_t dstBytesPerPixel = | 436 const int32_t dstBytesPerPixel = |
| 436 SkColorTypeBytesPerPixel(dstColorType); | 437 SkColorTypeBytesPerPixel(dstColorType); |
| 437 void* subsetDst = SkTAddOffset<void*>(dst, | 438 dst = SkTAddOffset<void*>(dst, |
| 438 dstRowBytes * imageTop + | 439 dstRowBytes * imageTop + |
| 439 dstBytesPerPixel * imageLeft); | 440 dstBytesPerPixel * imageLeft); |
| 440 | 441 |
| 441 // Create the subset swizzler | 442 // Create the subset swizzler |
| 442 swizzler.reset(SkSwizzler::CreateSwizzler( | 443 swizzler.reset(SkSwizzler::CreateSwizzler( |
| 443 SkSwizzler::kIndex, colorTable, subsetDstInfo, | 444 SkSwizzler::kIndex, colorTable, subsetDstInfo, |
| 444 subsetDst, dstRowBytes, zeroInit)); | 445 zeroInit)); |
| 445 } else { | 446 } else { |
| 446 // Create the fully dimensional swizzler | 447 // Create the fully dimensional swizzler |
| 447 swizzler.reset(SkSwizzler::CreateSwizzler( | 448 swizzler.reset(SkSwizzler::CreateSwizzler( |
| 448 SkSwizzler::kIndex, colorTable, dstInfo, dst, | 449 SkSwizzler::kIndex, colorTable, dstInfo, zeroInit)); |
| 449 dstRowBytes, zeroInit)); | |
| 450 } | 450 } |
| 451 | 451 |
| 452 // Stores output from dgiflib and input to the swizzler | 452 // Stores output from dgiflib and input to the swizzler |
| 453 SkAutoTDeleteArray<uint8_t> | 453 SkAutoTDeleteArray<uint8_t> |
| 454 buffer(SkNEW_ARRAY(uint8_t, innerWidth)); | 454 buffer(SkNEW_ARRAY(uint8_t, innerWidth)); |
| 455 | 455 |
| 456 // Check the interlace flag and iterate over rows of the input | 456 // Check the interlace flag and iterate over rows of the input |
| 457 if (fGif->Image.Interlace) { | 457 if (fGif->Image.Interlace) { |
| 458 // In interlace mode, the rows of input are rearranged in | 458 // In interlace mode, the rows of input are rearranged in |
| 459 // the output image. We use an iterator to take care of | 459 // the output image. We use an iterator to take care of |
| 460 // the rearranging. | 460 // the rearranging. |
| 461 SkGifInterlaceIter iter(innerHeight); | 461 SkGifInterlaceIter iter(innerHeight); |
| 462 for (int32_t y = 0; y < innerHeight; y++) { | 462 for (int32_t y = 0; y < innerHeight; y++) { |
| 463 if (GIF_ERROR == DGifGetLine(fGif, buffer.get(), | 463 if (GIF_ERROR == DGifGetLine(fGif, buffer.get(), |
| 464 innerWidth)) { | 464 innerWidth)) { |
| 465 // Recover from error by filling remainder of image | 465 // Recover from error by filling remainder of image |
| 466 if (!skipBackground) { | 466 if (!skipBackground) { |
| 467 memset(buffer.get(), fillIndex, innerWidth); | 467 memset(buffer.get(), fillIndex, innerWidth); |
| 468 for (; y < innerHeight; y++) { | 468 for (; y < innerHeight; y++) { |
| 469 swizzler->next(buffer.get(), iter.nextY()); | 469 void* dstRow = SkTAddOffset<void>(dst, |
| 470 dstRowBytes * iter.nextY()); |
| 471 swizzler->swizzle(dstRow, buffer.get()); |
| 470 } | 472 } |
| 471 } | 473 } |
| 472 return gif_error(SkStringPrintf( | 474 return gif_error(SkStringPrintf( |
| 473 "Could not decode line %d of %d.\n", | 475 "Could not decode line %d of %d.\n", |
| 474 y, height - 1).c_str(), kIncompleteInput); | 476 y, height - 1).c_str(), kIncompleteInput); |
| 475 } | 477 } |
| 476 swizzler->next(buffer.get(), iter.nextY()); | 478 void* dstRow = SkTAddOffset<void>( |
| 479 dst, dstRowBytes * iter.nextY()); |
| 480 swizzler->swizzle(dstRow, buffer.get()); |
| 477 } | 481 } |
| 478 } else { | 482 } else { |
| 479 // Standard mode | 483 // Standard mode |
| 484 void* dstRow = dst; |
| 480 for (int32_t y = 0; y < innerHeight; y++) { | 485 for (int32_t y = 0; y < innerHeight; y++) { |
| 481 if (GIF_ERROR == DGifGetLine(fGif, buffer.get(), | 486 if (GIF_ERROR == DGifGetLine(fGif, buffer.get(), |
| 482 innerWidth)) { | 487 innerWidth)) { |
| 483 if (!skipBackground) { | 488 if (!skipBackground) { |
| 484 SkSwizzler::Fill(swizzler->getDstRow(), dstInfo,
dstRowBytes, | 489 SkSwizzler::Fill(dstRow, dstInfo, dstRowBytes, |
| 485 innerHeight - y, fillIndex, colorTable); | 490 innerHeight - y, fillIndex, colorTable); |
| 486 } | 491 } |
| 487 return gif_error(SkStringPrintf( | 492 return gif_error(SkStringPrintf( |
| 488 "Could not decode line %d of %d.\n", | 493 "Could not decode line %d of %d.\n", |
| 489 y, height - 1).c_str(), kIncompleteInput); | 494 y, height - 1).c_str(), kIncompleteInput); |
| 490 } | 495 } |
| 491 swizzler->next(buffer.get()); | 496 swizzler->swizzle(dstRow, buffer.get()); |
| 497 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes); |
| 492 } | 498 } |
| 493 } | 499 } |
| 494 | 500 |
| 495 // FIXME: Gif files may have multiple images stored in a single | 501 // FIXME: Gif files may have multiple images stored in a single |
| 496 // file. This is most commonly used to enable | 502 // file. This is most commonly used to enable |
| 497 // animations. Since we are leaving animated gifs as a | 503 // animations. Since we are leaving animated gifs as a |
| 498 // TODO, we will return kSuccess after decoding the | 504 // TODO, we will return kSuccess after decoding the |
| 499 // first image in the file. This is the same behavior | 505 // first image in the file. This is the same behavior |
| 500 // as SkImageDecoder_libgif. | 506 // as SkImageDecoder_libgif. |
| 501 // | 507 // |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 565 // giflib returns an error code if the record type is not known. | 571 // giflib returns an error code if the record type is not known. |
| 566 // We should catch this error immediately. | 572 // We should catch this error immediately. |
| 567 SkASSERT(false); | 573 SkASSERT(false); |
| 568 break; | 574 break; |
| 569 } | 575 } |
| 570 } while (TERMINATE_RECORD_TYPE != recordType); | 576 } while (TERMINATE_RECORD_TYPE != recordType); |
| 571 | 577 |
| 572 return gif_error("Could not find any images to decode in gif file.\n", | 578 return gif_error("Could not find any images to decode in gif file.\n", |
| 573 kInvalidInput); | 579 kInvalidInput); |
| 574 } | 580 } |
| OLD | NEW |