Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(141)

Side by Side Diff: src/codec/SkCodec_libgif.cpp

Issue 1332053002: Fill incomplete images in SkCodec parent class (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Rebase on merged SkCodec and SkScanlineDecoder Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 // There should only be one graphics control extension for the image frame 89 // There should only be one graphics control extension for the image frame
90 break; 90 break;
91 } 91 }
92 } 92 }
93 93
94 // Use maximum unsigned int (surely an invalid index) to indicate that a val id 94 // Use maximum unsigned int (surely an invalid index) to indicate that a val id
95 // index was not found. 95 // index was not found.
96 return SK_MaxU32; 96 return SK_MaxU32;
97 } 97 }
98 98
99 static inline uint32_t ceil_div(uint32_t a, uint32_t b) {
100 return (a + b - 1) / b;
101 }
102
103 /*
104 * Gets the output row corresponding to the encoded row for interlaced gifs
105 */
106 static uint32_t get_output_row_interlaced(uint32_t encodedRow, uint32_t height) {
107 SkASSERT(encodedRow < height);
108 // First pass
109 if (encodedRow * 8 < height) {
110 return encodedRow * 8;
111 }
112 // Second pass
113 if (encodedRow * 4 < height) {
114 return 4 + 8 * (encodedRow - ceil_div(height, 8));
115 }
116 // Third pass
117 if (encodedRow * 2 < height) {
118 return 2 + 4 * (encodedRow - ceil_div(height, 4));
119 }
120 // Fourth pass
121 return 1 + 2 * (encodedRow - ceil_div(height, 2));
122 }
123
124 /* 99 /*
125 * This function cleans up the gif object after the decode completes 100 * This function cleans up the gif object after the decode completes
126 * It is used in a SkAutoTCallIProc template 101 * It is used in a SkAutoTCallIProc template
127 */ 102 */
128 void SkGifCodec::CloseGif(GifFileType* gif) { 103 void SkGifCodec::CloseGif(GifFileType* gif) {
129 DGifCloseFile(gif, NULL); 104 DGifCloseFile(gif, NULL);
130 } 105 }
131 106
132 /* 107 /*
133 * This function free extension data that has been saved to assist the image 108 * This function free extension data that has been saved to assist the image
(...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after
485 ZeroInitialized zeroInit) { 460 ZeroInitialized zeroInit) {
486 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); 461 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
487 fSwizzler.reset(SkSwizzler::CreateSwizzler(SkSwizzler::kIndex, 462 fSwizzler.reset(SkSwizzler::CreateSwizzler(SkSwizzler::kIndex,
488 colorPtr, dstInfo, zeroInit, this->getInfo())); 463 colorPtr, dstInfo, zeroInit, this->getInfo()));
489 if (nullptr != fSwizzler.get()) { 464 if (nullptr != fSwizzler.get()) {
490 return kSuccess; 465 return kSuccess;
491 } 466 }
492 return kUnimplemented; 467 return kUnimplemented;
493 } 468 }
494 469
495 SkCodec::Result SkGifCodec::readRow() { 470 bool SkGifCodec::readRow() {
496 if (GIF_ERROR == DGifGetLine(fGif, fSrcBuffer.get(), fFrameDims.width())) { 471 return GIF_ERROR != DGifGetLine(fGif, fSrcBuffer.get(), fFrameDims.width());
497 return kIncompleteInput;
498 }
499 return kSuccess;
500 } 472 }
501 473
502 /* 474 /*
503 * Initiates the gif decode 475 * Initiates the gif decode
504 */ 476 */
505 SkCodec::Result SkGifCodec::onGetPixels(const SkImageInfo& dstInfo, 477 SkCodec::Result SkGifCodec::onGetPixels(const SkImageInfo& dstInfo,
506 void* dst, size_t dstRowBytes, 478 void* dst, size_t dstRowBytes,
507 const Options& opts, 479 const Options& opts,
508 SkPMColor* inputColorPtr, 480 SkPMColor* inputColorPtr,
509 int* inputColorCount) { 481 int* inputColorCount,
482 int* rowsDecoded) {
510 Result result = this->prepareToDecode(dstInfo, inputColorPtr, inputColorCoun t, opts); 483 Result result = this->prepareToDecode(dstInfo, inputColorPtr, inputColorCoun t, opts);
511 if (kSuccess != result) { 484 if (kSuccess != result) {
512 return result; 485 return result;
513 } 486 }
514 487
515 if (dstInfo.dimensions() != this->getInfo().dimensions()) { 488 if (dstInfo.dimensions() != this->getInfo().dimensions()) {
516 return gif_error("Scaling not supported.\n", kInvalidScale); 489 return gif_error("Scaling not supported.\n", kInvalidScale);
517 } 490 }
518 491
519 // Initialize the swizzler 492 // Initialize the swizzler
520 if (fFrameIsSubset) { 493 if (fFrameIsSubset) {
521 const SkImageInfo subsetDstInfo = dstInfo.makeWH(fFrameDims.width(), fFr ameDims.height()); 494 const SkImageInfo subsetDstInfo = dstInfo.makeWH(fFrameDims.width(), fFr ameDims.height());
522 if (kSuccess != this->initializeSwizzler(subsetDstInfo, opts.fZeroInitia lized)) { 495 if (kSuccess != this->initializeSwizzler(subsetDstInfo, opts.fZeroInitia lized)) {
523 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ; 496 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ;
524 } 497 }
525 498
526 // Fill the background 499 // Fill the background
527 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); 500 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
528 SkSwizzler::Fill(dst, dstInfo, dstRowBytes, this->getInfo().height(), 501 SkSwizzler::Fill(dst, dstInfo, dstRowBytes, this->getFillValue(dstInfo.c olorType(),
529 fFillIndex, colorPtr, opts.fZeroInitialized); 502 dstInfo.alphaType()), opts.fZeroInitialized);
530 503
531 // Modify the dst pointer 504 // Modify the dst pointer
532 const int32_t dstBytesPerPixel = SkColorTypeBytesPerPixel(dstInfo.colorT ype()); 505 const int32_t dstBytesPerPixel = SkColorTypeBytesPerPixel(dstInfo.colorT ype());
533 dst = SkTAddOffset<void*>(dst, dstRowBytes * fFrameDims.top() + 506 dst = SkTAddOffset<void*>(dst, dstRowBytes * fFrameDims.top() +
534 dstBytesPerPixel * fFrameDims.left()); 507 dstBytesPerPixel * fFrameDims.left());
535 } else { 508 } else {
536 if (kSuccess != this->initializeSwizzler(dstInfo, opts.fZeroInitialized) ) { 509 if (kSuccess != this->initializeSwizzler(dstInfo, opts.fZeroInitialized) ) {
537 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ; 510 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ;
538 } 511 }
539 } 512 }
540 513
541 // Check the interlace flag and iterate over rows of the input 514 // Iterate over rows of the input
542 uint32_t width = fFrameDims.width(); 515 uint32_t width = fFrameDims.width();
543 uint32_t height = fFrameDims.height(); 516 uint32_t height = fFrameDims.height();
544 if (fGif->Image.Interlace) { 517 for (uint32_t y = 0; y < height; y++) {
545 // In interlace mode, the rows of input are rearranged in 518 if (!this->readRow()) {
546 // the output image. We a helper function to help us 519 *rowsDecoded = y;
547 // rearrange the decoded rows. 520 return gif_error("Could not decode line.\n", kIncompleteInput);
548 for (uint32_t y = 0; y < height; y++) {
549 if (kSuccess != this->readRow()) {
550 // Recover from error by filling remainder of image
551 memset(fSrcBuffer.get(), fFillIndex, width);
552 for (; y < height; y++) {
553 void* dstRow = SkTAddOffset<void>(dst,
554 dstRowBytes * get_output_row_interlaced(y, height));
555 fSwizzler->swizzle(dstRow, fSrcBuffer.get());
556 }
557 return gif_error("Could not decode line.\n", kIncompleteInput);
558 }
559 void* dstRow = SkTAddOffset<void>(dst,
560 dstRowBytes * get_output_row_interlaced(y, height));
561 fSwizzler->swizzle(dstRow, fSrcBuffer.get());
562 } 521 }
563 } else { 522 void* dstRow = SkTAddOffset<void>(dst, dstRowBytes * this->nextScanline( y));
564 // Standard mode 523 fSwizzler->swizzle(dstRow, fSrcBuffer.get());
565 void* dstRow = dst;
566 for (uint32_t y = 0; y < height; y++) {
567 if (kSuccess != this->readRow()) {
568 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
569 SkSwizzler::Fill(dstRow, dstInfo, dstRowBytes,
570 height - y, fFillIndex, colorPtr, opts.fZeroInitialized) ;
571 return gif_error("Could not decode line\n", kIncompleteInput);
572 }
573 fSwizzler->swizzle(dstRow, fSrcBuffer.get());
574 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes);
575 }
576 } 524 }
577 return kSuccess; 525 return kSuccess;
578 } 526 }
579 527
528 uint32_t SkGifCodec::onGetFillValue(SkColorType colorType, SkAlphaType alphaType ) const {
529 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
530 return get_color_table_fill_value(colorType, colorPtr, fFillIndex);
531 }
532
580 SkCodec::Result SkGifCodec::onStartScanlineDecode(const SkImageInfo& dstInfo, 533 SkCodec::Result SkGifCodec::onStartScanlineDecode(const SkImageInfo& dstInfo,
581 const SkCodec::Options& opts, SkPMColor inputColorPtr[], int* inputColor Count) { 534 const SkCodec::Options& opts, SkPMColor inputColorPtr[], int* inputColor Count) {
582 Result result = this->prepareToDecode(dstInfo, inputColorPtr, inputColorCoun t, 535
583 this->options()); 536 Result result = this->prepareToDecode(dstInfo, inputColorPtr, inputColorCoun t, this->options());
584 if (kSuccess != result) { 537 if (kSuccess != result) {
585 return result; 538 return result;
586 } 539 }
587 540
588 // Check to see if scaling was requested. 541 // Check to see if scaling was requested.
589 if (dstInfo.dimensions() != this->getInfo().dimensions()) { 542 if (dstInfo.dimensions() != this->getInfo().dimensions()) {
590 if (!SkScaledCodec::DimensionsSupportedForSampling(this->getInfo(), dstI nfo)) { 543 if (!SkScaledCodec::DimensionsSupportedForSampling(this->getInfo(), dstI nfo)) {
591 return gif_error("Scaling not supported.\n", SkCodec::kInvalidScale) ; 544 return gif_error("Scaling not supported.\n", SkCodec::kInvalidScale) ;
592 } 545 }
593 } 546 }
(...skipping 10 matching lines...) Expand all
604 } 557 }
605 } else { 558 } else {
606 if (kSuccess != this->initializeSwizzler(dstInfo, opts.fZeroInitialized) ) { 559 if (kSuccess != this->initializeSwizzler(dstInfo, opts.fZeroInitialized) ) {
607 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ; 560 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ;
608 } 561 }
609 } 562 }
610 563
611 return kSuccess; 564 return kSuccess;
612 } 565 }
613 566
614 SkCodec::Result SkGifCodec::onGetScanlines(void* dst, int count, size_t rowBytes ) { 567 uint32_t SkGifCodec::onGetScanlines(void* dst, int count, size_t rowBytes) {
568 int rowsBeforeFrame = 0;
569 int rowsAfterFrame = 0;
615 if (fFrameIsSubset) { 570 if (fFrameIsSubset) {
616 // Fill the requested rows 571 // Fill the requested rows
617 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); 572 SkSwizzler::Fill(dst, this->dstInfo().makeWH(this->dstInfo().width(), co unt), rowBytes,
618 SkSwizzler::Fill(dst, this->dstInfo(), rowBytes, count, fFillIndex, 573 this->onGetFillValue(this->dstInfo().colorType(), this->dstInfo( ).alphaType()),
619 colorPtr, this->options().fZeroInitialized); 574 this->options().fZeroInitialized);
620 575
621 // Do nothing for rows before the image frame 576 // Do nothing for rows before the image frame
622 // FIXME: nextScanline is not virtual, so using "INHERITED" does not cha nge 577 // FIXME: Do we handle fFrameIsSubset properly for interlaced images?
623 // behavior. Was the intent to call this->INHERITED::onNextScanline()? S ame 578 rowsBeforeFrame = SkTMax(0, fFrameDims.top() - this->nextScanline());
624 // for the next call down below. 579 count = SkTMax(0, count - rowsBeforeFrame);
625 int rowsBeforeFrame = fFrameDims.top() - this->INHERITED::nextScanline() ; 580 dst = SkTAddOffset<void>(dst, rowBytes * rowsBeforeFrame);
626 if (rowsBeforeFrame > 0) {
627 count = SkTMin(0, count - rowsBeforeFrame);
628 dst = SkTAddOffset<void>(dst, rowBytes * rowsBeforeFrame);
629 }
630 581
631 // Do nothing for rows after the image frame 582 // Do nothing for rows after the image frame
632 int rowsAfterFrame = this->INHERITED::nextScanline() + count - fFrameDim s.bottom(); 583 rowsAfterFrame = SkTMax(0, this->nextScanline() + count - fFrameDims.bot tom());
633 if (rowsAfterFrame > 0) { 584 count = SkTMax(0, count - rowsAfterFrame);
634 count = SkTMin(0, count - rowsAfterFrame);
635 }
636 585
637 // Adjust dst pointer for left offset 586 // Adjust dst pointer for left offset
638 int bpp = SkColorTypeBytesPerPixel(this->dstInfo().colorType()) * fFrame Dims.left(); 587 int bpp = SkColorTypeBytesPerPixel(this->dstInfo().colorType()) * fFrame Dims.left();
639 dst = SkTAddOffset<void>(dst, bpp); 588 dst = SkTAddOffset<void>(dst, bpp);
640 } 589 }
641 590
642 for (int i = 0; i < count; i++) { 591 for (int i = 0; i < count; i++) {
643 if (kSuccess != this->readRow()) { 592 if (!this->readRow()) {
644 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); 593 return i + rowsBeforeFrame;
645 SkSwizzler::Fill(dst, this->dstInfo(), rowBytes, count - i, fFillInd ex, colorPtr,
646 this->options().fZeroInitialized);
647 return gif_error("Could not decode line\n", SkCodec::kIncompleteInpu t);
648 } 594 }
649 fSwizzler->swizzle(dst, fSrcBuffer.get()); 595 fSwizzler->swizzle(dst, fSrcBuffer.get());
650 dst = SkTAddOffset<void>(dst, rowBytes); 596 dst = SkTAddOffset<void>(dst, rowBytes);
651 } 597 }
652 return SkCodec::kSuccess; 598 return count + rowsBeforeFrame + rowsAfterFrame;
653 } 599 }
654 600
655 SkCodec::SkScanlineOrder SkGifCodec::onGetScanlineOrder() const { 601 SkCodec::SkScanlineOrder SkGifCodec::onGetScanlineOrder() const {
656 if (fGif->Image.Interlace) { 602 if (fGif->Image.Interlace) {
657 return kOutOfOrder_SkScanlineOrder; 603 return kOutOfOrder_SkScanlineOrder;
658 } else {
659 return kTopDown_SkScanlineOrder;
660 } 604 }
605 return kTopDown_SkScanlineOrder;
661 } 606 }
662
663 int SkGifCodec::onNextScanline() const {
664 if (fGif->Image.Interlace) {
665 return get_output_row_interlaced(this->INHERITED::onNextScanline(), this ->dstInfo().height());
666 } else {
667 return this->INHERITED::onNextScanline();
668 }
669 }
670
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698