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

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

Issue 1194703002: onGetScanlines and onSkipScanlines for interlaced pngs (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 6 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
« dm/DMSrcSink.cpp ('K') | « src/codec/SkCodec_libpng.h ('k') | no next file » | 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 630 matching lines...) Expand 10 before | Expand all | Expand 10 after
641 641
642 private: 642 private:
643 SkPngCodec* fCodec; // Unowned. 643 SkPngCodec* fCodec; // Unowned.
644 bool fHasAlpha; 644 bool fHasAlpha;
645 SkAutoMalloc fStorage; 645 SkAutoMalloc fStorage;
646 uint8_t* fSrcRow; 646 uint8_t* fSrcRow;
647 647
648 typedef SkScanlineDecoder INHERITED; 648 typedef SkScanlineDecoder INHERITED;
649 }; 649 };
650 650
651
652 class SkPngInterlacedScanlineDecoder : public SkScanlineDecoder {
653 public:
654 SkPngInterlacedScanlineDecoder(const SkImageInfo& dstInfo, SkPngCodec* codec )
655 : INHERITED(dstInfo)
656 , fCodec(codec)
657 , fHasAlpha(false)
658 {
659 fCurrentRow = 0;
emmaleer 2015/06/18 21:05:41 Should these variables be defined in the cosntruct
msarett 2015/06/19 13:35:54 I prefer them here. For interlaced png, you proba
emmaleer 2015/06/19 14:28:08 Done.
scroggo 2015/06/19 15:45:53 Taking that a step further, I believe you can even
emmaleer 2015/06/19 22:12:20 I left fStorageGarbage in the body of the construc
660 fHeight = dstInfo.height();
661 fSrcRowBytes = dstInfo.minRowBytes();
662 fStorageGarbage.reset(fSrcRowBytes);
663 fGarbageRow = static_cast<uint8_t*>(fStorageGarbage.get());
664 }
665
666 SkImageGenerator::Result onGetScanlines(void* dst, int count, size_t dstRowB ytes) override {
667 //rewind stream since we need entire progressive image to get scanlines
668 fCodec->handleRewind();
scroggo 2015/06/19 15:45:53 If handleRewind returns false (which it can for a
emmaleer 2015/06/19 22:12:20 Done.
669 if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) {
670 SkCodecPrintf("setjmp long jump!\n");
671 return SkImageGenerator::kInvalidInput;
672 }
673 const int number_passes = png_set_interlace_handling(fCodec->fPng_ptr);
674 fStorageData.reset(count * fSrcRowBytes);
msarett 2015/06/19 13:35:54 Maybe this belongs on the constructor as well? Do
emmaleer 2015/06/19 14:28:08 On 2015/06/19 13:35:54, msarett wrote: > Maybe thi
scroggo 2015/06/19 15:45:53 (FYI: If you put ">"s at the beginning of each lin
emmaleer 2015/06/19 22:12:20 Good to know, I thought ">" was used for a new lin
675 fBuffer = static_cast<uint8_t*>(fStorageData.get());
676
677 for (int i = 0; i < number_passes; i++) {
678 //read rows we planned to skip into garbage row
679 for (int y = 0; y < fCurrentRow; y++){
680 png_read_rows(fCodec->fPng_ptr, &fGarbageRow, png_bytepp_NULL, 1 );
681 }
682 //read rows we care about into buffer
683 fSrcRow = fBuffer;
684 for (int y = 0; y < count; y++) {
685 png_read_rows(fCodec->fPng_ptr, &fSrcRow, png_bytepp_NULL, 1);
686 fSrcRow += fSrcRowBytes;
687 }
688 //read rows we don't want into garbage buffer
689 for (int y = 0; y < fHeight - fCurrentRow - count; y++) {
690 png_read_rows(fCodec->fPng_ptr, &fGarbageRow, png_bytepp_NULL, 1 );
691 }
692 }
693 //swizzle the rows we care about
694 fSrcRow = fBuffer;
695 for (int y = 0; y < count; y++) {
696 fCodec->fSwizzler->setDstRow(dst);
697 fHasAlpha |= !SkSwizzler::IsOpaque(fCodec->fSwizzler->next(fSrcRow)) ;
698 dst = SkTAddOffset<void>(dst, dstRowBytes);
699 fSrcRow += fSrcRowBytes;
700 }
701 fCurrentRow += count;
702 return SkImageGenerator::kSuccess;
703 }
704
705 SkImageGenerator::Result onSkipScanlines(int count) override {
706 //when ongetScanlines is called it will skip to fCurrentRow
707 fCurrentRow += count;
scroggo 2015/06/19 15:45:53 I think if we've already read rows, you'll want to
scroggo 2015/06/19 16:00:40 And, I was confused... The way the other scanline
emmaleer 2015/06/19 22:12:20 I added the boolean fRewindNeeded to keep track if
708 return SkImageGenerator::kSuccess;
709 }
710
711 void onFinish() override {
712 fCodec->finish();
713 }
714
715 bool onReallyHasAlpha() const override { return fHasAlpha; }
716
717 private:
718 SkPngCodec* fCodec; // Unowned.
719 bool fHasAlpha;
720 SkAutoMalloc fStorageData;
721 SkAutoMalloc fStorageGarbage;
722 uint8_t* fBuffer;
723 uint8_t* fSrcRow;
724 uint8_t* fGarbageRow;
725 int fHeight;
726 int fSrcRowBytes;
727 int fCurrentRow;
728
729 typedef SkScanlineDecoder INHERITED;
730 };
731
732
651 SkScanlineDecoder* SkPngCodec::onGetScanlineDecoder(const SkImageInfo& dstInfo, 733 SkScanlineDecoder* SkPngCodec::onGetScanlineDecoder(const SkImageInfo& dstInfo,
652 const Options& options, SkPMColor ctable[], int* ctableCount) { 734 const Options& options, SkPMColor ctable[], int* ctableCount) {
653 if (!this->handleRewind()) { 735 if (!this->handleRewind()) {
654 return NULL; 736 return NULL;
655 } 737 }
656 738
657 // Check to see if scaling was requested. 739 // Check to see if scaling was requested.
658 if (dstInfo.dimensions() != this->getInfo().dimensions()) { 740 if (dstInfo.dimensions() != this->getInfo().dimensions()) {
659 return NULL; 741 return NULL;
660 } 742 }
661 743
662 if (!conversion_possible(dstInfo, this->getInfo())) { 744 if (!conversion_possible(dstInfo, this->getInfo())) {
663 SkCodecPrintf("no conversion possible\n"); 745 SkCodecPrintf("no conversion possible\n");
664 return NULL; 746 return NULL;
665 } 747 }
666 748
667 // Note: We set dst to NULL since we do not know it yet. rowBytes is not nee ded, 749 // Note: We set dst to NULL since we do not know it yet. rowBytes is not nee ded,
668 // since we'll be manually updating the dstRow, but the SkSwizzler requires it to 750 // since we'll be manually updating the dstRow, but the SkSwizzler requires it to
669 // be at least dstInfo.minRowBytes. 751 // be at least dstInfo.minRowBytes.
670 if (this->initializeSwizzler(dstInfo, NULL, dstInfo.minRowBytes(), options, ctable, 752 if (this->initializeSwizzler(dstInfo, NULL, dstInfo.minRowBytes(), options, ctable,
671 ctableCount) != kSuccess) { 753 ctableCount) != kSuccess) {
672 SkCodecPrintf("failed to initialize the swizzler.\n"); 754 SkCodecPrintf("failed to initialize the swizzler.\n");
673 return NULL; 755 return NULL;
674 } 756 }
675 757
676 SkASSERT(fNumberPasses != INVALID_NUMBER_PASSES); 758 SkASSERT(fNumberPasses != INVALID_NUMBER_PASSES);
677 if (fNumberPasses > 1) { 759 if (fNumberPasses > 1) {
678 // We cannot efficiently do scanline decoding. 760 // interlaced image
679 return NULL; 761 return SkNEW_ARGS(SkPngInterlacedScanlineDecoder, (dstInfo, this));
680 } 762 }
681 763
682 return SkNEW_ARGS(SkPngScanlineDecoder, (dstInfo, this)); 764 return SkNEW_ARGS(SkPngScanlineDecoder, (dstInfo, this));
683 } 765 }
684 766
OLDNEW
« dm/DMSrcSink.cpp ('K') | « src/codec/SkCodec_libpng.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698