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

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

Issue 1332053002: Fill incomplete images in SkCodec parent class (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Response to comments 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_libpng.h" 8 #include "SkCodec_libpng.h"
9 #include "SkCodecPriv.h" 9 #include "SkCodecPriv.h"
10 #include "SkColorPriv.h" 10 #include "SkColorPriv.h"
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after
463 return false; 463 return false;
464 } 464 }
465 465
466 fPng_ptr = png_ptr; 466 fPng_ptr = png_ptr;
467 fInfo_ptr = info_ptr; 467 fInfo_ptr = info_ptr;
468 return true; 468 return true;
469 } 469 }
470 470
471 SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& requestedInfo, void* dst, 471 SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& requestedInfo, void* dst,
472 size_t dstRowBytes, const Options& optio ns, 472 size_t dstRowBytes, const Options& optio ns,
473 SkPMColor ctable[], int* ctableCount) { 473 SkPMColor ctable[], int* ctableCount,
474 int* incompleteScanlines) {
474 if (!conversion_possible(requestedInfo, this->getInfo())) { 475 if (!conversion_possible(requestedInfo, this->getInfo())) {
475 return kInvalidConversion; 476 return kInvalidConversion;
476 } 477 }
477 if (options.fSubset) { 478 if (options.fSubset) {
478 // Subsets are not supported. 479 // Subsets are not supported.
479 return kUnimplemented; 480 return kUnimplemented;
480 } 481 }
481 if (requestedInfo.dimensions() != this->getInfo().dimensions()) { 482 if (requestedInfo.dimensions() != this->getInfo().dimensions()) {
482 return kInvalidScale; 483 return kInvalidScale;
483 } 484 }
484 if (!this->rewindIfNeeded()) { 485 if (!this->rewindIfNeeded()) {
485 return kCouldNotRewind; 486 return kCouldNotRewind;
486 } 487 }
487 488
488 // Note that ctable and ctableCount may be modified if there is a color tabl e 489 // Note that ctable and ctableCount may be modified if there is a color tabl e
489 const Result result = this->initializeSwizzler(requestedInfo, options, 490 const Result result = this->initializeSwizzler(requestedInfo, options,
490 ctable, ctableCount); 491 ctable, ctableCount);
491 if (result != kSuccess) { 492 if (result != kSuccess) {
492 return result; 493 return result;
493 } 494 }
494 // FIXME: Could we use the return value of setjmp to specify the type of 495 // FIXME: Could we use the return value of setjmp to specify the type of
495 // error? 496 // error?
497 int row = 0;
496 if (setjmp(png_jmpbuf(fPng_ptr))) { 498 if (setjmp(png_jmpbuf(fPng_ptr))) {
497 SkCodecPrintf("setjmp long jump!\n"); 499 // Assume that any error that occurs while reading rows is caused by an incomplete input.
498 return kInvalidInput; 500 if (fNumberPasses > 1) {
501 // FIXME (msarett): Handle incomplete interlaced pngs.
502 return kInvalidInput;
503 }
504 // FIXME: We do a poor job on incomplete pngs compared to other decoders (ex: Chromium,
505 // Ubuntu Image Viewer). This is because we use the default buffer size in libpng (8192
506 // bytes), and if we can't fill the buffer, we immediately fail. Making our buffer size
507 // smaller would help, but what impact would it have on regular decode p erformance? Should
508 // we investigate using a different API than png_read_row(s)? Chromium uses
509 // png_process_data.
510 *incompleteScanlines = requestedInfo.height() - row;
511 return kIncompleteInput;
499 } 512 }
500 513
501 SkASSERT(fNumberPasses != INVALID_NUMBER_PASSES); 514 SkASSERT(fNumberPasses != INVALID_NUMBER_PASSES);
502 SkAutoMalloc storage; 515 SkAutoMalloc storage;
503 void* dstRow = dst; 516 void* dstRow = dst;
504 if (fNumberPasses > 1) { 517 if (fNumberPasses > 1) {
505 const int width = requestedInfo.width(); 518 const int width = requestedInfo.width();
506 const int height = requestedInfo.height(); 519 const int height = requestedInfo.height();
507 const int bpp = SkSwizzler::BytesPerPixel(fSrcConfig); 520 const int bpp = SkSwizzler::BytesPerPixel(fSrcConfig);
508 const size_t srcRowBytes = width * bpp; 521 const size_t srcRowBytes = width * bpp;
(...skipping 13 matching lines...) Expand all
522 // Now swizzle it. 535 // Now swizzle it.
523 uint8_t* srcRow = base; 536 uint8_t* srcRow = base;
524 for (int y = 0; y < height; y++) { 537 for (int y = 0; y < height; y++) {
525 fReallyHasAlpha |= !SkSwizzler::IsOpaque(fSwizzler->swizzle(dstRow, srcRow)); 538 fReallyHasAlpha |= !SkSwizzler::IsOpaque(fSwizzler->swizzle(dstRow, srcRow));
526 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes); 539 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes);
527 srcRow += srcRowBytes; 540 srcRow += srcRowBytes;
528 } 541 }
529 } else { 542 } else {
530 storage.reset(requestedInfo.width() * SkSwizzler::BytesPerPixel(fSrcConf ig)); 543 storage.reset(requestedInfo.width() * SkSwizzler::BytesPerPixel(fSrcConf ig));
531 uint8_t* srcRow = static_cast<uint8_t*>(storage.get()); 544 uint8_t* srcRow = static_cast<uint8_t*>(storage.get());
532 for (int y = 0; y < requestedInfo.height(); y++) { 545 for (; row < requestedInfo.height(); row++) {
533 png_read_rows(fPng_ptr, &srcRow, png_bytepp_NULL, 1); 546 png_read_rows(fPng_ptr, &srcRow, png_bytepp_NULL, 1);
534 fReallyHasAlpha |= !SkSwizzler::IsOpaque(fSwizzler->swizzle(dstRow, srcRow)); 547 fReallyHasAlpha |= !SkSwizzler::IsOpaque(fSwizzler->swizzle(dstRow, srcRow));
535 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes); 548 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes);
536 } 549 }
537 } 550 }
538 551
539 // FIXME: do we need substituteTranspColor? Note that we cannot do it for 552 // FIXME: do we need substituteTranspColor? Note that we cannot do it for
540 // scanline decoding, but we could do it here. Alternatively, we could do 553 // scanline decoding, but we could do it here. Alternatively, we could do
541 // it as we go, instead of in post-processing like SkPNGImageDecoder. 554 // it as we go, instead of in post-processing like SkPNGImageDecoder.
542 555
543 if (setjmp(png_jmpbuf(fPng_ptr))) { 556 if (setjmp(png_jmpbuf(fPng_ptr))) {
544 // We've already read all the scanlines. This is a success. 557 // We've already read all the scanlines. This is a success.
545 return kSuccess; 558 return kSuccess;
546 } 559 }
547 560
548 // read rest of file, and get additional comment and time chunks in info_ptr 561 // read rest of file, and get additional comment and time chunks in info_ptr
549 png_read_end(fPng_ptr, fInfo_ptr); 562 png_read_end(fPng_ptr, fInfo_ptr);
550 return kSuccess; 563 return kSuccess;
551 } 564 }
552 565
566 uint32_t SkPngCodec::onGetFillValue(const SkImageInfo& dstInfo) const {
567 const SkPMColor* colorPtr = get_color_ptr(fColorTable.get());
568 if (colorPtr) {
569 return get_color_table_fill_value(dstInfo.colorType(), colorPtr, 0);
570 }
571 return INHERITED::onGetFillValue(dstInfo);
572 }
573
553 class SkPngScanlineDecoder : public SkScanlineDecoder { 574 class SkPngScanlineDecoder : public SkScanlineDecoder {
554 public: 575 public:
555 SkPngScanlineDecoder(const SkImageInfo& srcInfo, SkPngCodec* codec) 576 SkPngScanlineDecoder(SkPngCodec* codec)
556 : INHERITED(srcInfo) 577 : INHERITED(codec, codec->getInfo())
557 , fCodec(codec) 578 , fCodec(codec)
558 , fHasAlpha(false) 579 , fHasAlpha(false)
580 , fRow(0)
559 {} 581 {}
560 582
561 SkCodec::Result onStart(const SkImageInfo& dstInfo, 583 SkCodec::Result onStart(const SkImageInfo& dstInfo,
562 const SkCodec::Options& options, 584 const SkCodec::Options& options,
563 SkPMColor ctable[], int* ctableCount) override { 585 SkPMColor ctable[], int* ctableCount) override {
564 if (!fCodec->rewindIfNeeded()) { 586 if (!fCodec->rewindIfNeeded()) {
565 return SkCodec::kCouldNotRewind; 587 return SkCodec::kCouldNotRewind;
566 } 588 }
567 589
568 if (!conversion_possible(dstInfo, this->getInfo())) { 590 if (!conversion_possible(dstInfo, this->getInfo())) {
569 return SkCodec::kInvalidConversion; 591 return SkCodec::kInvalidConversion;
570 } 592 }
571 593
572 // Check to see if scaling was requested. 594 // Check to see if scaling was requested.
573 if (dstInfo.dimensions() != this->getInfo().dimensions()) { 595 if (dstInfo.dimensions() != this->getInfo().dimensions()) {
574 if (!SkScaledCodec::DimensionsSupportedForSampling(this->getInfo(), dstInfo)) { 596 if (!SkScaledCodec::DimensionsSupportedForSampling(this->getInfo(), dstInfo)) {
575 return SkCodec::kInvalidScale; 597 return SkCodec::kInvalidScale;
576 } 598 }
577 } 599 }
578 600
579 const SkCodec::Result result = fCodec->initializeSwizzler(dstInfo, optio ns, ctable, 601 const SkCodec::Result result = fCodec->initializeSwizzler(dstInfo, optio ns, ctable,
580 ctableCount); 602 ctableCount);
581 if (result != SkCodec::kSuccess) { 603 if (result != SkCodec::kSuccess) {
582 return result; 604 return result;
583 } 605 }
584 606
585 fHasAlpha = false; 607 fHasAlpha = false;
586 fStorage.reset(this->getInfo().width() * SkSwizzler::BytesPerPixel(fCode c->fSrcConfig)); 608 fStorage.reset(this->getInfo().width() * SkSwizzler::BytesPerPixel(fCode c->fSrcConfig));
587 fSrcRow = static_cast<uint8_t*>(fStorage.get()); 609 fSrcRow = static_cast<uint8_t*>(fStorage.get());
588 610
589 return SkCodec::kSuccess; 611 return SkCodec::kSuccess;
590 } 612 }
591 613
592 SkCodec::Result onGetScanlines(void* dst, int count, size_t rowBytes) overri de { 614 uint32_t onGetScanlines(void* dst, int count, size_t rowBytes) override {
615 // Assume that an error in libpng indicates an incomplete input.
593 if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) { 616 if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) {
594 SkCodecPrintf("setjmp long jump!\n"); 617 SkCodecPrintf("setjmp long jump!\n");
595 return SkCodec::kInvalidInput; 618 return fRow;
scroggo 2015/09/25 15:55:06 Oh, wait, you said that "this works", and I though
msarett 2015/10/01 12:44:52 It does work...For some reason I only thought it w
596 } 619 }
597 620
598 void* dstRow = dst; 621 void* dstRow = dst;
599 for (int i = 0; i < count; i++) { 622 for (fRow = 0; fRow < count; fRow++) {
600 png_read_rows(fCodec->fPng_ptr, &fSrcRow, png_bytepp_NULL, 1); 623 png_read_rows(fCodec->fPng_ptr, &fSrcRow, png_bytepp_NULL, 1);
601 fHasAlpha |= !SkSwizzler::IsOpaque(fCodec->fSwizzler->swizzle(dstRow , fSrcRow)); 624 fHasAlpha |= !SkSwizzler::IsOpaque(fCodec->fSwizzler->swizzle(dstRow , fSrcRow));
602 dstRow = SkTAddOffset<void>(dstRow, rowBytes); 625 dstRow = SkTAddOffset<void>(dstRow, rowBytes);
603 } 626 }
604 return SkCodec::kSuccess; 627 return fRow;
605 } 628 }
606 629
607 SkCodec::Result onSkipScanlines(int count) override { 630 uint32_t onSkipScanlines(int count) override {
608 // FIXME: Could we use the return value of setjmp to specify the type of 631 // Assume that an error in libpng indicates an incomplete input.
609 // error?
610 if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) { 632 if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) {
611 SkCodecPrintf("setjmp long jump!\n"); 633 SkCodecPrintf("setjmp long jump!\n");
612 return SkCodec::kInvalidInput; 634 return fRow;
613 } 635 }
614 //there is a potential tradeoff of memory vs speed created by putting th is in a loop. 636 //there is a potential tradeoff of memory vs speed created by putting th is in a loop.
615 //calling png_read_rows in a loop is insignificantly slower than calling it once with count 637 //calling png_read_rows in a loop is insignificantly slower than calling it once with count
616 //as png_read_rows has it's own loop which calls png_read_row count time s. 638 //as png_read_rows has it's own loop which calls png_read_row count time s.
617 for (int i = 0; i < count; i++) { 639 for (fRow = 0; fRow < count; fRow++) {
618 png_read_rows(fCodec->fPng_ptr, &fSrcRow, png_bytepp_NULL, 1); 640 png_read_rows(fCodec->fPng_ptr, &fSrcRow, png_bytepp_NULL, 1);
619 } 641 }
620 return SkCodec::kSuccess; 642 return fRow;
621 } 643 }
622 644
623 bool onReallyHasAlpha() const override { return fHasAlpha; } 645 bool onReallyHasAlpha() const override { return fHasAlpha; }
624 646
625 SkEncodedFormat onGetEncodedFormat() const override { 647 SkEncodedFormat onGetEncodedFormat() const override {
626 return kPNG_SkEncodedFormat; 648 return kPNG_SkEncodedFormat;
627 } 649 }
628 650
629 651
630 private: 652 private:
631 SkAutoTDelete<SkPngCodec> fCodec; 653 SkPngCodec* fCodec; // Owned by parent class
632 bool fHasAlpha; 654 bool fHasAlpha;
655 uint32_t fRow;
633 SkAutoMalloc fStorage; 656 SkAutoMalloc fStorage;
634 uint8_t* fSrcRow; 657 uint8_t* fSrcRow;
635 658
636 typedef SkScanlineDecoder INHERITED; 659 typedef SkScanlineDecoder INHERITED;
637 }; 660 };
638 661
639 662
640 class SkPngInterlacedScanlineDecoder : public SkScanlineDecoder { 663 class SkPngInterlacedScanlineDecoder : public SkScanlineDecoder {
641 public: 664 public:
642 SkPngInterlacedScanlineDecoder(const SkImageInfo& srcInfo, SkPngCodec* codec ) 665 SkPngInterlacedScanlineDecoder(SkPngCodec* codec)
643 : INHERITED(srcInfo) 666 : INHERITED(codec, codec->getInfo())
644 , fCodec(codec) 667 , fCodec(codec)
645 , fHasAlpha(false) 668 , fHasAlpha(false)
646 , fCurrentRow(0) 669 , fCurrentRow(0)
647 , fHeight(srcInfo.height()) 670 , fHeight(codec->getInfo().height())
648 , fCanSkipRewind(false) 671 , fCanSkipRewind(false)
649 {} 672 {}
650 673
651 SkCodec::Result onStart(const SkImageInfo& dstInfo, 674 SkCodec::Result onStart(const SkImageInfo& dstInfo,
652 const SkCodec::Options& options, 675 const SkCodec::Options& options,
653 SkPMColor ctable[], int* ctableCount) override 676 SkPMColor ctable[], int* ctableCount) override
654 { 677 {
655 if (!fCodec->rewindIfNeeded()) { 678 if (!fCodec->rewindIfNeeded()) {
656 return SkCodec::kCouldNotRewind; 679 return SkCodec::kCouldNotRewind;
657 } 680 }
658 681
659 if (!conversion_possible(dstInfo, this->getInfo())) { 682 if (!conversion_possible(dstInfo, this->getInfo())) {
660 return SkCodec::kInvalidConversion; 683 return SkCodec::kInvalidConversion;
661 } 684 }
662 685
663 // Check to see if scaling was requested. 686 // Check to see if scaling was requested.
664 if (dstInfo.dimensions() != this->getInfo().dimensions()) { 687 if (dstInfo.dimensions() != this->getInfo().dimensions()) {
665 if (!SkScaledCodec::DimensionsSupportedForSampling(this->getInfo(), dstInfo)) { 688 if (!SkScaledCodec::DimensionsSupportedForSampling(this->getInfo(), dstInfo)) {
666 return SkCodec::kInvalidScale; 689 return SkCodec::kInvalidScale;
667 } 690 }
668 } 691 }
669 692
670 const SkCodec::Result result = fCodec->initializeSwizzler(dstInfo, optio ns, ctable, 693 const SkCodec::Result result = fCodec->initializeSwizzler(dstInfo, optio ns, ctable,
671 ctableCount); 694 ctableCount);
672 if (result != SkCodec::kSuccess) { 695 if (result != SkCodec::kSuccess) {
673 return result; 696 return result;
674 } 697 }
675 698
676 fHasAlpha = false; 699 fHasAlpha = false;
677 fCurrentRow = 0; 700 fCurrentRow = 0;
678 fHeight = dstInfo.height(); 701 fHeight = dstInfo.height();
679 fSrcRowBytes = this->getInfo().width() * SkSwizzler::BytesPerPixel(fCode c->fSrcConfig); 702 fSrcRowBytes = this->getInfo().width() * SkSwizzler::BytesPerPixel(fCode c->fSrcConfig);
680 fGarbageRow.reset(fSrcRowBytes); 703 fGarbageRow.reset(fSrcRowBytes);
681 fGarbageRowPtr = static_cast<uint8_t*>(fGarbageRow.get()); 704 fGarbageRowPtr = static_cast<uint8_t*>(fGarbageRow.get());
682 fCanSkipRewind = true; 705 fCanSkipRewind = true;
683 706
684 return SkCodec::kSuccess; 707 return SkCodec::kSuccess;
685 } 708 }
686 709
687 SkCodec::Result onGetScanlines(void* dst, int count, size_t dstRowBytes) ove rride { 710 uint32_t onGetScanlines(void* dst, int count, size_t dstRowBytes) override {
688 // rewind stream if have previously called onGetScanlines, 711 // rewind stream if have previously called onGetScanlines,
689 // since we need entire progressive image to get scanlines 712 // since we need entire progressive image to get scanlines
690 if (fCanSkipRewind) { 713 if (fCanSkipRewind) {
691 // We already rewound in onStart, so there is no reason to rewind. 714 // We already rewound in onStart, so there is no reason to rewind.
692 // Next time onGetScanlines is called, we will need to rewind. 715 // Next time onGetScanlines is called, we will need to rewind.
693 fCanSkipRewind = false; 716 fCanSkipRewind = false;
694 } else if (!fCodec->rewindIfNeeded()) { 717 } else if (!fCodec->rewindIfNeeded()) {
695 return SkCodec::kCouldNotRewind; 718 return 0;
696 } 719 }
697 720
698 if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) { 721 if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) {
699 SkCodecPrintf("setjmp long jump!\n"); 722 SkCodecPrintf("setjmp long jump!\n");
700 return SkCodec::kInvalidInput; 723 // FIXME (msarett): Returning 0 is pessimistic. If we can complete a single pass,
724 // we may be able to report that all of the memory has been initiali zed. Even if we
725 // fail on the first pass, we can still report than some scanlines a re initialized.
726 return 0;
701 } 727 }
702 const int number_passes = png_set_interlace_handling(fCodec->fPng_ptr); 728 const int number_passes = png_set_interlace_handling(fCodec->fPng_ptr);
703 SkAutoMalloc storage(count * fSrcRowBytes); 729 SkAutoMalloc storage(count * fSrcRowBytes);
704 uint8_t* storagePtr = static_cast<uint8_t*>(storage.get()); 730 uint8_t* storagePtr = static_cast<uint8_t*>(storage.get());
705 uint8_t* srcRow; 731 uint8_t* srcRow;
706 for (int i = 0; i < number_passes; i++) { 732 for (int i = 0; i < number_passes; i++) {
707 //read rows we planned to skip into garbage row 733 //read rows we planned to skip into garbage row
708 for (int y = 0; y < fCurrentRow; y++){ 734 for (int y = 0; y < fCurrentRow; y++){
709 png_read_rows(fCodec->fPng_ptr, &fGarbageRowPtr, png_bytepp_NULL , 1); 735 png_read_rows(fCodec->fPng_ptr, &fGarbageRowPtr, png_bytepp_NULL , 1);
710 } 736 }
(...skipping 10 matching lines...) Expand all
721 } 747 }
722 //swizzle the rows we care about 748 //swizzle the rows we care about
723 srcRow = storagePtr; 749 srcRow = storagePtr;
724 void* dstRow = dst; 750 void* dstRow = dst;
725 for (int y = 0; y < count; y++) { 751 for (int y = 0; y < count; y++) {
726 fHasAlpha |= !SkSwizzler::IsOpaque(fCodec->fSwizzler->swizzle(dstRow , srcRow)); 752 fHasAlpha |= !SkSwizzler::IsOpaque(fCodec->fSwizzler->swizzle(dstRow , srcRow));
727 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes); 753 dstRow = SkTAddOffset<void>(dstRow, dstRowBytes);
728 srcRow += fSrcRowBytes; 754 srcRow += fSrcRowBytes;
729 } 755 }
730 fCurrentRow += count; 756 fCurrentRow += count;
731 return SkCodec::kSuccess; 757 return count;
732 } 758 }
733 759
734 SkCodec::Result onSkipScanlines(int count) override { 760 uint32_t onSkipScanlines(int count) override {
735 //when ongetScanlines is called it will skip to fCurrentRow 761 //when ongetScanlines is called it will skip to fCurrentRow
736 fCurrentRow += count; 762 fCurrentRow += count;
737 return SkCodec::kSuccess; 763 return count;
738 } 764 }
739 765
740 bool onReallyHasAlpha() const override { return fHasAlpha; } 766 bool onReallyHasAlpha() const override { return fHasAlpha; }
741 767
742 SkScanlineOrder onGetScanlineOrder() const override { 768 SkScanlineOrder onGetScanlineOrder() const override {
743 return kNone_SkScanlineOrder; 769 return kNone_SkScanlineOrder;
744 } 770 }
745 771
746 SkEncodedFormat onGetEncodedFormat() const override { 772 SkEncodedFormat onGetEncodedFormat() const override {
747 return kPNG_SkEncodedFormat; 773 return kPNG_SkEncodedFormat;
748 } 774 }
749 775
750 private: 776 private:
751 SkAutoTDelete<SkPngCodec> fCodec; 777 SkPngCodec* fCodec; // Owned by parent class
752 bool fHasAlpha; 778 bool fHasAlpha;
753 int fCurrentRow; 779 int fCurrentRow;
754 int fHeight; 780 int fHeight;
755 size_t fSrcRowBytes; 781 size_t fSrcRowBytes;
756 SkAutoMalloc fGarbageRow; 782 SkAutoMalloc fGarbageRow;
757 uint8_t* fGarbageRowPtr; 783 uint8_t* fGarbageRowPtr;
758 // FIXME: This imitates behavior in SkCodec::rewindIfNeeded. That function 784 // FIXME: This imitates behavior in SkCodec::rewindIfNeeded. That function
759 // is called whenever some action is taken that reads the stream and 785 // is called whenever some action is taken that reads the stream and
760 // therefore the next call will require a rewind. So it modifies a boolean 786 // therefore the next call will require a rewind. So it modifies a boolean
761 // to note that the *next* time it is called a rewind is needed. 787 // to note that the *next* time it is called a rewind is needed.
762 // SkPngInterlacedScanlineDecoder has an extra wrinkle - calling onStart 788 // SkPngInterlacedScanlineDecoder has an extra wrinkle - calling onStart
763 // followed by onGetScanlines does *not* require a rewind. Since 789 // followed by onGetScanlines does *not* require a rewind. Since
764 // rewindIfNeeded does not have this flexibility, we need to add another 790 // rewindIfNeeded does not have this flexibility, we need to add another
765 // layer. 791 // layer.
766 bool fCanSkipRewind; 792 bool fCanSkipRewind;
767 793
768 typedef SkScanlineDecoder INHERITED; 794 typedef SkScanlineDecoder INHERITED;
769 }; 795 };
770 796
771 SkScanlineDecoder* SkPngCodec::NewSDFromStream(SkStream* stream) { 797 SkScanlineDecoder* SkPngCodec::NewSDFromStream(SkStream* stream) {
772 SkAutoTDelete<SkPngCodec> codec (static_cast<SkPngCodec*>(SkPngCodec::NewFro mStream(stream))); 798 SkAutoTDelete<SkPngCodec> codec (static_cast<SkPngCodec*>(SkPngCodec::NewFro mStream(stream)));
773 if (!codec) { 799 if (!codec) {
774 return nullptr; 800 return nullptr;
775 } 801 }
776 802
777 codec->fNumberPasses = png_set_interlace_handling(codec->fPng_ptr); 803 codec->fNumberPasses = png_set_interlace_handling(codec->fPng_ptr);
778 SkASSERT(codec->fNumberPasses != INVALID_NUMBER_PASSES); 804 SkASSERT(codec->fNumberPasses != INVALID_NUMBER_PASSES);
779 805
780 const SkImageInfo& srcInfo = codec->getInfo();
781 if (codec->fNumberPasses > 1) { 806 if (codec->fNumberPasses > 1) {
782 // interlaced image 807 // interlaced image
783 return new SkPngInterlacedScanlineDecoder(srcInfo, codec.detach()); 808 return new SkPngInterlacedScanlineDecoder(codec.detach());
784 } 809 }
785 810
786 return new SkPngScanlineDecoder(srcInfo, codec.detach()); 811 return new SkPngScanlineDecoder(codec.detach());
787 } 812 }
788 813
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698