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

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

Issue 1267583002: Create a scanline decoder without creating a codec (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Fix interlaced Created 5 years, 4 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
« no previous file with comments | « src/codec/SkCodec_libpng.h ('k') | src/codec/SkJpegCodec.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 576 matching lines...) Expand 10 before | Expand all | Expand 10 after
587 return kSuccess; 587 return kSuccess;
588 } 588 }
589 589
590 // read rest of file, and get additional comment and time chunks in info_ptr 590 // read rest of file, and get additional comment and time chunks in info_ptr
591 png_read_end(fPng_ptr, fInfo_ptr); 591 png_read_end(fPng_ptr, fInfo_ptr);
592 return kSuccess; 592 return kSuccess;
593 } 593 }
594 594
595 class SkPngScanlineDecoder : public SkScanlineDecoder { 595 class SkPngScanlineDecoder : public SkScanlineDecoder {
596 public: 596 public:
597 SkPngScanlineDecoder(const SkImageInfo& dstInfo, SkPngCodec* codec) 597 SkPngScanlineDecoder(const SkImageInfo& srcInfo, SkPngCodec* codec)
598 : INHERITED(dstInfo) 598 : INHERITED(srcInfo)
599 , fCodec(codec) 599 , fCodec(codec)
600 , fHasAlpha(false) 600 , fHasAlpha(false)
601 {}
602
603 SkCodec::Result onStart(const SkImageInfo& dstInfo,
604 const SkCodec::Options& options,
605 SkPMColor ctable[], int* ctableCount) override
601 { 606 {
607 if (!fCodec->handleRewind()) {
608 return SkCodec::kCouldNotRewind;
609 }
610
611 if (!conversion_possible(dstInfo, this->getInfo())) {
612 return SkCodec::kInvalidConversion;
613 }
614
615 // Check to see if scaling was requested.
616 if (dstInfo.dimensions() != this->getInfo().dimensions()) {
617 return SkCodec::kInvalidScale;
618 }
619
620 const SkCodec::Result result = fCodec->initializeSwizzler(dstInfo, optio ns, ctable,
621 ctableCount);
622 if (result != SkCodec::kSuccess) {
623 return result;
624 }
625
626 fHasAlpha = false;
602 fStorage.reset(dstInfo.width() * SkSwizzler::BytesPerPixel(fCodec->fSrcC onfig)); 627 fStorage.reset(dstInfo.width() * SkSwizzler::BytesPerPixel(fCodec->fSrcC onfig));
603 fSrcRow = static_cast<uint8_t*>(fStorage.get()); 628 fSrcRow = static_cast<uint8_t*>(fStorage.get());
629
630 return SkCodec::kSuccess;
604 } 631 }
605 632
606 SkCodec::Result onGetScanlines(void* dst, int count, size_t rowBytes) overri de { 633 SkCodec::Result onGetScanlines(void* dst, int count, size_t rowBytes) overri de {
607 if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) { 634 if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) {
608 SkCodecPrintf("setjmp long jump!\n"); 635 SkCodecPrintf("setjmp long jump!\n");
609 return SkCodec::kInvalidInput; 636 return SkCodec::kInvalidInput;
610 } 637 }
611 638
612 void* dstRow = dst; 639 void* dstRow = dst;
613 for (int i = 0; i < count; i++) { 640 for (int i = 0; i < count; i++) {
(...skipping 27 matching lines...) Expand all
641 bool fHasAlpha; 668 bool fHasAlpha;
642 SkAutoMalloc fStorage; 669 SkAutoMalloc fStorage;
643 uint8_t* fSrcRow; 670 uint8_t* fSrcRow;
644 671
645 typedef SkScanlineDecoder INHERITED; 672 typedef SkScanlineDecoder INHERITED;
646 }; 673 };
647 674
648 675
649 class SkPngInterlacedScanlineDecoder : public SkScanlineDecoder { 676 class SkPngInterlacedScanlineDecoder : public SkScanlineDecoder {
650 public: 677 public:
651 SkPngInterlacedScanlineDecoder(const SkImageInfo& dstInfo, SkPngCodec* codec ) 678 SkPngInterlacedScanlineDecoder(const SkImageInfo& srcInfo, SkPngCodec* codec )
652 : INHERITED(dstInfo) 679 : INHERITED(srcInfo)
653 , fCodec(codec) 680 , fCodec(codec)
654 , fHasAlpha(false) 681 , fHasAlpha(false)
655 , fCurrentRow(0) 682 , fCurrentRow(0)
656 , fHeight(dstInfo.height()) 683 , fHeight(srcInfo.height())
684 , fCanSkipRewind(false)
685 {}
686
687 SkCodec::Result onStart(const SkImageInfo& dstInfo,
688 const SkCodec::Options& options,
689 SkPMColor ctable[], int* ctableCount) override
657 { 690 {
691 if (!fCodec->handleRewind()) {
692 return SkCodec::kCouldNotRewind;
693 }
694
695 if (!conversion_possible(dstInfo, this->getInfo())) {
696 return SkCodec::kInvalidConversion;
697 }
698
699 // Check to see if scaling was requested.
700 if (dstInfo.dimensions() != this->getInfo().dimensions()) {
701 return SkCodec::kInvalidScale;
702 }
703
704 const SkCodec::Result result = fCodec->initializeSwizzler(dstInfo, optio ns, ctable,
705 ctableCount);
706 if (result != SkCodec::kSuccess) {
707 return result;
708 }
709
710 fHasAlpha = false;
711 fCurrentRow = 0;
712 fHeight = dstInfo.height();
658 fSrcRowBytes = dstInfo.width() * SkSwizzler::BytesPerPixel(fCodec->fSrcC onfig); 713 fSrcRowBytes = dstInfo.width() * SkSwizzler::BytesPerPixel(fCodec->fSrcC onfig);
659 fGarbageRow.reset(fSrcRowBytes); 714 fGarbageRow.reset(fSrcRowBytes);
660 fGarbageRowPtr = static_cast<uint8_t*>(fGarbageRow.get()); 715 fGarbageRowPtr = static_cast<uint8_t*>(fGarbageRow.get());
716 fCanSkipRewind = true;
717
718 return SkCodec::kSuccess;
661 } 719 }
662 720
663 SkCodec::Result onGetScanlines(void* dst, int count, size_t dstRowBytes) ove rride { 721 SkCodec::Result onGetScanlines(void* dst, int count, size_t dstRowBytes) ove rride {
664 //rewind stream if have previously called onGetScanlines, 722 // rewind stream if have previously called onGetScanlines,
665 //since we need entire progressive image to get scanlines 723 // since we need entire progressive image to get scanlines
666 if (!fCodec->handleRewind()) { 724 if (fCanSkipRewind) {
725 // We already rewound in onStart, so there is no reason to rewind.
726 // Next time onGetScanlines is called, we will need to rewind.
727 fCanSkipRewind = false;
728 } else if (!fCodec->handleRewind()) {
667 return SkCodec::kCouldNotRewind; 729 return SkCodec::kCouldNotRewind;
668 } 730 }
731
669 if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) { 732 if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) {
670 SkCodecPrintf("setjmp long jump!\n"); 733 SkCodecPrintf("setjmp long jump!\n");
671 return SkCodec::kInvalidInput; 734 return SkCodec::kInvalidInput;
672 } 735 }
673 const int number_passes = png_set_interlace_handling(fCodec->fPng_ptr); 736 const int number_passes = png_set_interlace_handling(fCodec->fPng_ptr);
674 SkAutoMalloc storage(count * fSrcRowBytes); 737 SkAutoMalloc storage(count * fSrcRowBytes);
675 uint8_t* storagePtr = static_cast<uint8_t*>(storage.get()); 738 uint8_t* storagePtr = static_cast<uint8_t*>(storage.get());
676 uint8_t* srcRow; 739 uint8_t* srcRow;
677 for (int i = 0; i < number_passes; i++) { 740 for (int i = 0; i < number_passes; i++) {
678 //read rows we planned to skip into garbage row 741 //read rows we planned to skip into garbage row
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
711 bool onReallyHasAlpha() const override { return fHasAlpha; } 774 bool onReallyHasAlpha() const override { return fHasAlpha; }
712 775
713 private: 776 private:
714 SkAutoTDelete<SkPngCodec> fCodec; 777 SkAutoTDelete<SkPngCodec> fCodec;
715 bool fHasAlpha; 778 bool fHasAlpha;
716 int fCurrentRow; 779 int fCurrentRow;
717 int fHeight; 780 int fHeight;
718 size_t fSrcRowBytes; 781 size_t fSrcRowBytes;
719 SkAutoMalloc fGarbageRow; 782 SkAutoMalloc fGarbageRow;
720 uint8_t* fGarbageRowPtr; 783 uint8_t* fGarbageRowPtr;
784 // FIXME: This imitates behavior in SkCodec::rewindIfNeeded. That function
785 // is called whenever some action is taken that reads the stream and
786 // therefore the next call will require a rewind. So it modifies a boolean
787 // to note that the *next* time it is called a rewind is needed.
788 // SkPngInterlacedScanlineDecoder has an extra wrinkle - calling onStart
789 // followed by onGetScanlines does *not* require a rewind. Since
790 // rewindIfNeeded does not have this flexibility, we need to add another
791 // layer.
792 bool fCanSkipRewind;
721 793
722 typedef SkScanlineDecoder INHERITED; 794 typedef SkScanlineDecoder INHERITED;
723 }; 795 };
724 796
725 797 SkScanlineDecoder* SkPngCodec::NewSDFromStream(SkStream* stream) {
726 SkScanlineDecoder* SkPngCodec::onGetScanlineDecoder(const SkImageInfo& dstInfo,
727 const Options& options, SkPMColor ctable[], int* ctableCount) {
728 if (!conversion_possible(dstInfo, this->getInfo())) {
729 SkCodecPrintf("no conversion possible\n");
730 return NULL;
731 }
732 // Check to see if scaling was requested.
733 if (dstInfo.dimensions() != this->getInfo().dimensions()) {
734 return NULL;
735 }
736 // Create a new SkPngCodec, to be owned by the scanline decoder.
737 SkStream* stream = this->stream()->duplicate();
738 if (!stream) {
739 return NULL;
740 }
741 SkAutoTDelete<SkPngCodec> codec (static_cast<SkPngCodec*>(SkPngCodec::NewFro mStream(stream))); 798 SkAutoTDelete<SkPngCodec> codec (static_cast<SkPngCodec*>(SkPngCodec::NewFro mStream(stream)));
742 if (!codec) { 799 if (!codec) {
743 return NULL; 800 return NULL;
744 } 801 }
745 802
746 if (codec->initializeSwizzler(dstInfo, options, ctable, ctableCount) != kSuc cess) { 803 codec->fNumberPasses = png_set_interlace_handling(codec->fPng_ptr);
747 SkCodecPrintf("failed to initialize the swizzler.\n"); 804 SkASSERT(codec->fNumberPasses != INVALID_NUMBER_PASSES);
748 return NULL; 805
806 const SkImageInfo& srcInfo = codec->getInfo();
807 if (codec->fNumberPasses > 1) {
808 // interlaced image
809 return SkNEW_ARGS(SkPngInterlacedScanlineDecoder, (srcInfo, codec.detach ()));
749 } 810 }
750 811
751 SkASSERT(codec->fNumberPasses != INVALID_NUMBER_PASSES); 812 return SkNEW_ARGS(SkPngScanlineDecoder, (srcInfo, codec.detach()));
752 if (codec->fNumberPasses > 1) {
753 // interlaced image
754 return SkNEW_ARGS(SkPngInterlacedScanlineDecoder, (dstInfo, codec.detach ()));
755 }
756
757 return SkNEW_ARGS(SkPngScanlineDecoder, (dstInfo, codec.detach()));
758 } 813 }
759 814
OLDNEW
« no previous file with comments | « src/codec/SkCodec_libpng.h ('k') | src/codec/SkJpegCodec.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698