aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/codec/SkPngCodec.h
diff options
context:
space:
mode:
authorGravatar scroggo <scroggo@chromium.org>2016-09-16 08:20:38 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-09-16 08:20:38 -0700
commit8e6c7ada5a4c5a950cded765d14d3e6906acdc79 (patch)
treecd5126dc3309121b759b87d2aff2e435cd813727 /src/codec/SkPngCodec.h
parent2bd295e5a3c24240f6536a72675cc268efb5414e (diff)
Make SkPngCodec decode progressively.
This is a step towards using SkCodec in Chromium, where progressive decoding is necessary. Switch from using png_read_row (which expects all the data to be available) to png_process_data, which uses callbacks when rows are available. Create a new API for SkCodec, which supports progressive decoding and scanline decoding. Future changes will switch the other clients off of startScanlineDecode and get/skip-Scanlines to the new API. Remove SkCodec::kNone_ScanlineOrder, which was only used for interlaced PNG images. In the new API, interlaced PNG fits kTopDown. Also remove updateCurrScanline(), which was only used by the old implementation for interlaced PNG. DMSrcSink: - In CodecSrc::kScanline_Mode, use the new method for scanline decoding for the supported formats (just PNG and PNG-in-ICO for now). fuzz.cpp: - Remove reference to kNone_ScanlineOrder SkCodec: - Add new APIs: - startIncrementalDecode - incrementalDecode - Remove kNone_SkScanlineOrder and updateCurrScanline() - Set fDstInfo and fOptions in getPixels(). This may not be necessary for all implementations, but it simplifies things for SkPngCodec. SkPngCodec: - Implement new APIs - Switch from sk_read_fn/png_read_row etc to png_process_data - Expand AutoCleanPng's role to decode the header and create the SkPngCodec - Make the interlaced PNG decoder report how many lines were initialized during an incomplete decode SkIcoCodec: - Implement the new APIs; supported for PNG in ICO SkSampledCodec: - Call the new method for decoding scanlines, and fall back to the old method if the new version is unimplemented - Remove references to kNone_SkScanlineOrder tests/CodecPartial: - Add a test which decodes part of an image, then finishes the decode, and compares it to the straightforward method tests/CodecTest: - Add a test which decodes all scanlines using the new method - Repurpose the Codec_stripes test to decode using the new method in sections rather than all at once - In the method check(), add a parameter for whether the image supports the new method of scanline decoding, and be explicit about whether an image supports incomplete - Test incomplete PNG decodes. We should have been doing it anyway for non-interlaced (except for an image that is too small - one row), but the new method supports interlaced incomplete as well - Make test_invalid_parameters test the new method - Add a test to ensure that it's safe to fall back to scanline decoding without rewinding BUG=skia:4211 The new version was generally faster than the old version (but not significantly so). Some raw performance differences can be found at https://docs.google.com/a/google.com/spreadsheets/d/1Gis3aRCEa72qBNDRMgGDg3jD-pMgO-FXldlNF9ejo4o/ Design doc can be found at https://docs.google.com/a/google.com/document/d/11Mn8-ePDKwVEMCjs3nWwSjxcSpJ_Cu8DF57KNtUmgLM/ GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1997703003 Review-Url: https://codereview.chromium.org/1997703003
Diffstat (limited to 'src/codec/SkPngCodec.h')
-rw-r--r--src/codec/SkPngCodec.h75
1 files changed, 59 insertions, 16 deletions
diff --git a/src/codec/SkPngCodec.h b/src/codec/SkPngCodec.h
index a4c20c708f..e3059ba0d5 100644
--- a/src/codec/SkPngCodec.h
+++ b/src/codec/SkPngCodec.h
@@ -14,6 +14,13 @@
#include "SkRefCnt.h"
#include "SkSwizzler.h"
+// FIXME (scroggo): GOOGLE3 is currently using an outdated version of libpng,
+// so we need to work around the lack of the method png_process_data_pause.
+// This code will be unnecessary once we update GOOGLE3. It would make more
+// sense to condition this on the version of libpng being used, but we do not
+// know that here because png.h is only included by the cpp file.
+#define SK_GOOGLE3_PNG_HACK
+
class SkStream;
class SkPngCodec : public SkCodec {
@@ -39,25 +46,50 @@ protected:
void* fPtr;
};
+ SkPngCodec(const SkEncodedInfo&, const SkImageInfo&, SkStream*, SkPngChunkReader*,
+ void* png_ptr, void* info_ptr, int bitDepth);
+
Result onGetPixels(const SkImageInfo&, void*, size_t, const Options&, SkPMColor*, int*, int*)
override;
SkEncodedFormat onGetEncodedFormat() const override { return kPNG_SkEncodedFormat; }
bool onRewind() override;
uint64_t onGetFillValue(const SkImageInfo&) const override;
- // Helper to set up swizzler, color xforms, and color table. Also calls png_read_update_info.
- bool initializeXforms(const SkImageInfo& dstInfo, const Options&, SkPMColor* colorPtr,
- int* colorCount);
- void initializeSwizzler(const SkImageInfo& dstInfo, const Options&);
SkSampler* getSampler(bool createIfNecessary) override;
- void allocateStorage(const SkImageInfo& dstInfo);
- void applyXformRow(void* dst, const void* src, SkColorType, SkAlphaType, int width);
+ void applyXformRow(void* dst, const void* src);
- virtual int readRows(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, int count,
- int startRow) = 0;
+ voidp png_ptr() { return fPng_ptr; }
+ voidp info_ptr() { return fInfo_ptr; }
- SkPngCodec(const SkEncodedInfo&, const SkImageInfo&, SkStream*, SkPngChunkReader*,
- void* png_ptr, void* info_ptr, int, int);
+ SkSwizzler* swizzler() { return fSwizzler; }
+
+ // Initialize variables used by applyXformRow.
+ void initializeXformAlphaAndWidth();
+
+ /**
+ * Pass available input to libpng to process it.
+ *
+ * libpng will call any relevant callbacks installed. This will continue decoding
+ * until it reaches the end of the file, or until a callback tells libpng to stop.
+ */
+ void processData();
+
+#ifdef SK_GOOGLE3_PNG_HACK
+ // In libpng 1.2.56, png_process_data_pause does not exist, so when we wanted to
+ // read the header, we may have read too far. In that case, we need to delete the
+ // png_ptr and info_ptr and recreate them. This method does that (and attaches the
+ // chunk reader.
+ bool rereadHeaderIfNecessary();
+
+ // This method sets up the new png_ptr/info_ptr (created in rereadHeaderIfNecessary)
+ // the way we set up the old one the first time in AutoCleanPng.decodeBounds's callback.
+ void rereadInfoCallback();
+#endif
+
+ Result onStartIncrementalDecode(const SkImageInfo& dstInfo, void* pixels, size_t rowBytes,
+ const SkCodec::Options&,
+ SkPMColor* ctable, int* ctableCount) override;
+ Result onIncrementalDecode(int*) override;
SkAutoTUnref<SkPngChunkReader> fPngChunkReader;
voidp fPng_ptr;
@@ -68,12 +100,8 @@ protected:
SkAutoTDelete<SkSwizzler> fSwizzler;
std::unique_ptr<SkColorSpaceXform> fColorXform;
SkAutoTMalloc<uint8_t> fStorage;
- uint8_t* fSwizzlerSrcRow;
uint32_t* fColorXformSrcRow;
- size_t fSrcRowBytes;
-
- const int fNumberPasses;
- int fBitDepth;
+ const int fBitDepth;
private:
@@ -89,9 +117,24 @@ private:
};
bool createColorTable(const SkImageInfo& dstInfo, int* ctableCount);
+ // Helper to set up swizzler, color xforms, and color table. Also calls png_read_update_info.
+ bool initializeXforms(const SkImageInfo& dstInfo, const Options&, SkPMColor* colorPtr,
+ int* colorCount);
+ void initializeSwizzler(const SkImageInfo& dstInfo, const Options&);
+ void allocateStorage(const SkImageInfo& dstInfo);
void destroyReadStruct();
- XformMode fXformMode;
+ virtual Result decodeAllRows(void* dst, size_t rowBytes, int* rowsDecoded) = 0;
+ virtual void setRange(int firstRow, int lastRow, void* dst, size_t rowBytes) = 0;
+ virtual Result decode(int* rowsDecoded) = 0;
+
+ XformMode fXformMode;
+ SkAlphaType fXformAlphaType;
+ int fXformWidth;
+
+#ifdef SK_GOOGLE3_PNG_HACK
+ bool fNeedsToRereadHeader;
+#endif
typedef SkCodec INHERITED;
};