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

Unified 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 side-by-side diff with in-line comments
Download patch
« dm/DMSrcSink.cpp ('K') | « src/codec/SkCodec_libpng.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/codec/SkCodec_libpng.cpp
diff --git a/src/codec/SkCodec_libpng.cpp b/src/codec/SkCodec_libpng.cpp
index c2a032e84ea8d98017998bdf5e6f9e12bf059685..c02990c1c6a201ae7955853c2a4bd32855adc20e 100644
--- a/src/codec/SkCodec_libpng.cpp
+++ b/src/codec/SkCodec_libpng.cpp
@@ -648,6 +648,88 @@ private:
typedef SkScanlineDecoder INHERITED;
};
+
+class SkPngInterlacedScanlineDecoder : public SkScanlineDecoder {
+public:
+ SkPngInterlacedScanlineDecoder(const SkImageInfo& dstInfo, SkPngCodec* codec)
+ : INHERITED(dstInfo)
+ , fCodec(codec)
+ , fHasAlpha(false)
+ {
+ 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
+ fHeight = dstInfo.height();
+ fSrcRowBytes = dstInfo.minRowBytes();
+ fStorageGarbage.reset(fSrcRowBytes);
+ fGarbageRow = static_cast<uint8_t*>(fStorageGarbage.get());
+ }
+
+ SkImageGenerator::Result onGetScanlines(void* dst, int count, size_t dstRowBytes) override {
+ //rewind stream since we need entire progressive image to get scanlines
+ 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.
+ if (setjmp(png_jmpbuf(fCodec->fPng_ptr))) {
+ SkCodecPrintf("setjmp long jump!\n");
+ return SkImageGenerator::kInvalidInput;
+ }
+ const int number_passes = png_set_interlace_handling(fCodec->fPng_ptr);
+ 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
+ fBuffer = static_cast<uint8_t*>(fStorageData.get());
+
+ for (int i = 0; i < number_passes; i++) {
+ //read rows we planned to skip into garbage row
+ for (int y = 0; y < fCurrentRow; y++){
+ png_read_rows(fCodec->fPng_ptr, &fGarbageRow, png_bytepp_NULL, 1);
+ }
+ //read rows we care about into buffer
+ fSrcRow = fBuffer;
+ for (int y = 0; y < count; y++) {
+ png_read_rows(fCodec->fPng_ptr, &fSrcRow, png_bytepp_NULL, 1);
+ fSrcRow += fSrcRowBytes;
+ }
+ //read rows we don't want into garbage buffer
+ for (int y = 0; y < fHeight - fCurrentRow - count; y++) {
+ png_read_rows(fCodec->fPng_ptr, &fGarbageRow, png_bytepp_NULL, 1);
+ }
+ }
+ //swizzle the rows we care about
+ fSrcRow = fBuffer;
+ for (int y = 0; y < count; y++) {
+ fCodec->fSwizzler->setDstRow(dst);
+ fHasAlpha |= !SkSwizzler::IsOpaque(fCodec->fSwizzler->next(fSrcRow));
+ dst = SkTAddOffset<void>(dst, dstRowBytes);
+ fSrcRow += fSrcRowBytes;
+ }
+ fCurrentRow += count;
+ return SkImageGenerator::kSuccess;
+ }
+
+ SkImageGenerator::Result onSkipScanlines(int count) override {
+ //when ongetScanlines is called it will skip to fCurrentRow
+ 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
+ return SkImageGenerator::kSuccess;
+ }
+
+ void onFinish() override {
+ fCodec->finish();
+ }
+
+ bool onReallyHasAlpha() const override { return fHasAlpha; }
+
+private:
+ SkPngCodec* fCodec; // Unowned.
+ bool fHasAlpha;
+ SkAutoMalloc fStorageData;
+ SkAutoMalloc fStorageGarbage;
+ uint8_t* fBuffer;
+ uint8_t* fSrcRow;
+ uint8_t* fGarbageRow;
+ int fHeight;
+ int fSrcRowBytes;
+ int fCurrentRow;
+
+ typedef SkScanlineDecoder INHERITED;
+};
+
+
SkScanlineDecoder* SkPngCodec::onGetScanlineDecoder(const SkImageInfo& dstInfo,
const Options& options, SkPMColor ctable[], int* ctableCount) {
if (!this->handleRewind()) {
@@ -675,8 +757,8 @@ SkScanlineDecoder* SkPngCodec::onGetScanlineDecoder(const SkImageInfo& dstInfo,
SkASSERT(fNumberPasses != INVALID_NUMBER_PASSES);
if (fNumberPasses > 1) {
- // We cannot efficiently do scanline decoding.
- return NULL;
+ // interlaced image
+ return SkNEW_ARGS(SkPngInterlacedScanlineDecoder, (dstInfo, this));
}
return SkNEW_ARGS(SkPngScanlineDecoder, (dstInfo, this));
« 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