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

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: Created 5 years, 3 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 512 matching lines...) Expand 10 before | Expand all | Expand 10 after
523 523
524 // Initialize the swizzler 524 // Initialize the swizzler
525 if (fFrameIsSubset) { 525 if (fFrameIsSubset) {
526 const SkImageInfo subsetDstInfo = dstInfo.makeWH(fFrameDims.width(), fFr ameDims.height()); 526 const SkImageInfo subsetDstInfo = dstInfo.makeWH(fFrameDims.width(), fFr ameDims.height());
527 if (kSuccess != this->initializeSwizzler(subsetDstInfo, opts.fZeroInitia lized)) { 527 if (kSuccess != this->initializeSwizzler(subsetDstInfo, opts.fZeroInitia lized)) {
528 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ; 528 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ;
529 } 529 }
530 530
531 // Fill the background 531 // Fill the background
532 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); 532 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
533 SkSwizzler::Fill(dst, dstInfo, dstRowBytes, this->getInfo().height(), 533 SkSwizzler::Fill(dst, dstInfo, dstRowBytes, this->getFillValue(dstInfo),
534 fFillIndex, colorPtr, opts.fZeroInitialized); 534 opts.fZeroInitialized);
535 535
536 // Modify the dst pointer 536 // Modify the dst pointer
537 const int32_t dstBytesPerPixel = SkColorTypeBytesPerPixel(dstInfo.colorT ype()); 537 const int32_t dstBytesPerPixel = SkColorTypeBytesPerPixel(dstInfo.colorT ype());
538 dst = SkTAddOffset<void*>(dst, dstRowBytes * fFrameDims.top() + 538 dst = SkTAddOffset<void*>(dst, dstRowBytes * fFrameDims.top() +
539 dstBytesPerPixel * fFrameDims.left()); 539 dstBytesPerPixel * fFrameDims.left());
540 } else { 540 } else {
541 if (kSuccess != this->initializeSwizzler(dstInfo, opts.fZeroInitialized) ) { 541 if (kSuccess != this->initializeSwizzler(dstInfo, opts.fZeroInitialized) ) {
542 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ; 542 return gif_error("Could not initialize swizzler.\n", kUnimplemented) ;
543 } 543 }
544 } 544 }
545 545
546 // Check the interlace flag and iterate over rows of the input 546 // Check the interlace flag and iterate over rows of the input
547 uint32_t width = fFrameDims.width(); 547 uint32_t width = fFrameDims.width();
548 uint32_t height = fFrameDims.height(); 548 uint32_t height = fFrameDims.height();
549 if (fGif->Image.Interlace) { 549 if (fGif->Image.Interlace) {
550 // In interlace mode, the rows of input are rearranged in 550 // In interlace mode, the rows of input are rearranged in
551 // the output image. We a helper function to help us 551 // the output image. We a helper function to help us
552 // rearrange the decoded rows. 552 // rearrange the decoded rows.
553 for (uint32_t y = 0; y < height; y++) { 553 for (uint32_t y = 0; y < height; y++) {
554 if (kSuccess != this->readRow()) { 554 if (kSuccess != this->readRow()) {
555 // Recover from error by filling remainder of image 555 // Incomplete interlaced gifs are a unique case. Rather than,
556 memset(fSrcBuffer.get(), fFillIndex, width); 556 // relying on the base class, we will fill the remaining lines
557 // here.
558 const SkImageInfo fillInfo = dstInfo.makeWH(dstInfo.width(), 1);
559 const uint32_t fillValue = this->getFillValue(fillInfo);
557 for (; y < height; y++) { 560 for (; y < height; y++) {
558 void* dstRow = SkTAddOffset<void>(dst, 561 void* dstRow = SkTAddOffset<void>(dst,
559 dstRowBytes * get_output_row_interlaced(y, height)); 562 dstRowBytes * get_output_row_interlaced(y, height));
560 fSwizzler->swizzle(dstRow, fSrcBuffer.get()); 563 SkSwizzler::Fill(dstRow, fillInfo, dstRowBytes, fillValue,
564 opts.fZeroInitialized);
561 } 565 }
562 return gif_error("Could not decode line.\n", kIncompleteInput); 566 return gif_error("Could not decode line.\n", kIncompleteInput);
563 } 567 }
564 void* dstRow = SkTAddOffset<void>(dst, 568 void* dstRow = SkTAddOffset<void>(dst,
565 dstRowBytes * get_output_row_interlaced(y, height)); 569 dstRowBytes * get_output_row_interlaced(y, height));
566 fSwizzler->swizzle(dstRow, fSrcBuffer.get()); 570 fSwizzler->swizzle(dstRow, fSrcBuffer.get());
567 } 571 }
568 } else { 572 } else {
569 // Standard mode 573 // Standard mode
570 void* dstRow = dst; 574 void* dstRow = dst;
571 for (uint32_t y = 0; y < height; y++) { 575 for (uint32_t y = 0; y < height; y++) {
572 if (kSuccess != this->readRow()) { 576 if (kSuccess != this->readRow()) {
573 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get()); 577 this->setIncompleteScanlines(height - y);
574 SkSwizzler::Fill(dstRow, dstInfo, dstRowBytes,
575 height - y, fFillIndex, colorPtr, opts.fZeroInitialized) ;
576 return gif_error("Could not decode line\n", kIncompleteInput); 578 return gif_error("Could not decode line\n", kIncompleteInput);
577 } 579 }
578 fSwizzler->swizzle(dstRow, fSrcBuffer.get()); 580 fSwizzler->swizzle(dstRow, fSrcBuffer.get());
579 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes); 581 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes);
580 } 582 }
581 } 583 }
582 return kSuccess; 584 return kSuccess;
583 } 585 }
584 586
587 uint32_t SkGifCodec::onGetFillValue(const SkImageInfo& dstInfo) const {
588 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
589 return get_color_table_fill_value(dstInfo.colorType(), colorPtr, fFillIndex) ;
590 }
591
585 // TODO (msarett): skbug.com/3582 592 // TODO (msarett): skbug.com/3582
586 // Should we implement reallyHasAlpha? Or should we read extens ion blocks in the 593 // Should we implement reallyHasAlpha? Or should we read extens ion blocks in the
587 // header? Or should we do both? 594 // header? Or should we do both?
588 595
589 class SkGifScanlineDecoder : public SkScanlineDecoder { 596 class SkGifScanlineDecoder : public SkScanlineDecoder {
590 public: 597 public:
591 SkGifScanlineDecoder(const SkImageInfo& srcInfo, SkGifCodec* codec) 598 SkGifScanlineDecoder(SkGifCodec* codec)
592 : INHERITED(srcInfo) 599 : INHERITED(codec, codec->getInfo())
593 , fCodec(codec) 600 , fCodec(codec)
594 {} 601 {}
595 602
596 SkEncodedFormat onGetEncodedFormat() const override { 603 SkEncodedFormat onGetEncodedFormat() const override {
597 return kGIF_SkEncodedFormat; 604 return kGIF_SkEncodedFormat;
598 } 605 }
599 606
600 SkCodec::Result onStart(const SkImageInfo& dstInfo, const SkCodec::Options& opts, 607 SkCodec::Result onStart(const SkImageInfo& dstInfo, const SkCodec::Options& opts,
601 SkPMColor inputColorPtr[], int* inputColorCount) ove rride { 608 SkPMColor inputColorPtr[], int* inputColorCount) ove rride {
602 SkCodec::Result result = fCodec->prepareToDecode(dstInfo, inputColorPtr, inputColorCount, 609 SkCodec::Result result = fCodec->prepareToDecode(dstInfo, inputColorPtr, inputColorCount,
(...skipping 22 matching lines...) Expand all
625 } 632 }
626 } else { 633 } else {
627 if (SkCodec::kSuccess != fCodec->initializeSwizzler(dstInfo, opts.fZ eroInitialized)) { 634 if (SkCodec::kSuccess != fCodec->initializeSwizzler(dstInfo, opts.fZ eroInitialized)) {
628 return gif_error("Could not initialize swizzler.\n", SkCodec::kU nimplemented); 635 return gif_error("Could not initialize swizzler.\n", SkCodec::kU nimplemented);
629 } 636 }
630 } 637 }
631 638
632 return SkCodec::kSuccess; 639 return SkCodec::kSuccess;
633 } 640 }
634 641
635 SkCodec::Result onGetScanlines(void* dst, int count, size_t rowBytes) overri de { 642 uint32_t onGetScanlines(void* dst, int count, size_t rowBytes) override {
636 if (fCodec->fFrameIsSubset) { 643 if (fCodec->fFrameIsSubset) {
637 // Fill the requested rows 644 // Fill the requested rows
638 const SkPMColor* colorPtr = get_color_ptr(fCodec->fColorTable.get()) ; 645 SkSwizzler::Fill(dst, this->dstInfo().makeWH(this->dstInfo().width() , count), rowBytes,
639 SkSwizzler::Fill(dst, this->dstInfo(), rowBytes, count, fCodec->fFil lIndex, 646 fCodec->onGetFillValue(dstInfo()), this->options().fZeroInit ialized);
640 colorPtr, this->options().fZeroInitialized);
641 647
642 // Do nothing for rows before the image frame 648 // Do nothing for rows before the image frame
643 int rowsBeforeFrame = fCodec->fFrameDims.top() - INHERITED::getY(); 649 int rowsBeforeFrame = fCodec->fFrameDims.top() - INHERITED::getY();
644 if (rowsBeforeFrame > 0) { 650 if (rowsBeforeFrame > 0) {
645 count = SkTMin(0, count - rowsBeforeFrame); 651 count = SkTMin(0, count - rowsBeforeFrame);
646 dst = SkTAddOffset<void>(dst, rowBytes * rowsBeforeFrame); 652 dst = SkTAddOffset<void>(dst, rowBytes * rowsBeforeFrame);
647 } 653 }
648 654
649 // Do nothing for rows after the image frame 655 // Do nothing for rows after the image frame
650 int rowsAfterFrame = INHERITED::getY() + count - fCodec->fFrameDims. bottom(); 656 int rowsAfterFrame = INHERITED::getY() + count - fCodec->fFrameDims. bottom();
651 if (rowsAfterFrame > 0) { 657 if (rowsAfterFrame > 0) {
652 count = SkTMin(0, count - rowsAfterFrame); 658 count = SkTMin(0, count - rowsAfterFrame);
653 } 659 }
654 660
655 // Adjust dst pointer for left offset 661 // Adjust dst pointer for left offset
656 dst = SkTAddOffset<void>(dst, SkColorTypeBytesPerPixel( 662 dst = SkTAddOffset<void>(dst, SkColorTypeBytesPerPixel(
657 this->dstInfo().colorType()) * fCodec->fFrameDims.left()); 663 this->dstInfo().colorType()) * fCodec->fFrameDims.left());
658 } 664 }
659 665
666 void* dstRow = dst;
660 for (int i = 0; i < count; i++) { 667 for (int i = 0; i < count; i++) {
661 if (SkCodec::kSuccess != fCodec->readRow()) { 668 if (SkCodec::kSuccess != fCodec->readRow()) {
scroggo 2015/09/22 18:02:48 Should readRow just return a boolean?
msarett 2015/09/23 13:22:40 Yes!
662 const SkPMColor* colorPtr = get_color_ptr(fCodec->fColorTable.ge t()); 669 return i;
663 SkSwizzler::Fill(dst, this->dstInfo(), rowBytes,
664 count - i, fCodec->fFillIndex, colorPtr,
665 this->options().fZeroInitialized);
666 return gif_error("Could not decode line\n", SkCodec::kIncomplete Input);
667 } 670 }
668 fCodec->fSwizzler->swizzle(dst, fCodec->fSrcBuffer.get()); 671 fCodec->fSwizzler->swizzle(dstRow, fCodec->fSrcBuffer.get());
669 dst = SkTAddOffset<void>(dst, rowBytes); 672 dstRow = SkTAddOffset<void>(dstRow, rowBytes);
670 } 673 }
671 return SkCodec::kSuccess; 674 return count;
672 } 675 }
673 676
674 SkScanlineOrder onGetScanlineOrder() const override { 677 SkScanlineOrder onGetScanlineOrder() const override {
675 if (fCodec->fGif->Image.Interlace) { 678 if (fCodec->fGif->Image.Interlace) {
676 return kOutOfOrder_SkScanlineOrder; 679 return kOutOfOrder_SkScanlineOrder;
677 } else { 680 } else {
678 return kTopDown_SkScanlineOrder; 681 return kTopDown_SkScanlineOrder;
679 } 682 }
680 } 683 }
681 684
682 int onGetY() const override { 685 int onGetY(int encodedY) const override {
683 if (fCodec->fGif->Image.Interlace) { 686 if (fCodec->fGif->Image.Interlace) {
684 return get_output_row_interlaced(INHERITED::onGetY(), this->dstInfo( ).height()); 687 return get_output_row_interlaced(encodedY, this->dstInfo().height()) ;
685 } else { 688 } else {
686 return INHERITED::onGetY(); 689 return encodedY;
687 } 690 }
688 } 691 }
689 692
690 private: 693 private:
691 SkAutoTDelete<SkGifCodec> fCodec; 694 SkGifCodec* fCodec; // Owned by parent class
692 695
693 typedef SkScanlineDecoder INHERITED; 696 typedef SkScanlineDecoder INHERITED;
694 }; 697 };
695 698
696 SkScanlineDecoder* SkGifCodec::NewSDFromStream(SkStream* stream) { 699 SkScanlineDecoder* SkGifCodec::NewSDFromStream(SkStream* stream) {
697 SkAutoTDelete<SkGifCodec> codec (static_cast<SkGifCodec*>(SkGifCodec::NewFro mStream(stream))); 700 SkAutoTDelete<SkGifCodec> codec (static_cast<SkGifCodec*>(SkGifCodec::NewFro mStream(stream)));
698 if (!codec) { 701 if (!codec) {
699 return NULL; 702 return NULL;
700 } 703 }
701 704
702 const SkImageInfo& srcInfo = codec->getInfo(); 705 return SkNEW_ARGS(SkGifScanlineDecoder, (codec.detach()));
703
704 return SkNEW_ARGS(SkGifScanlineDecoder, (srcInfo, codec.detach()));
705 } 706 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698