aboutsummaryrefslogtreecommitdiffhomepage
path: root/include/codec
diff options
context:
space:
mode:
authorGravatar scroggo <scroggo@chromium.org>2016-06-01 07:31:28 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-06-01 07:31:28 -0700
commit30e78c9737ff4861dc4e3fa1e4cd010680ed6965 (patch)
treeb5f81285844f331b3ae29f088cef22e45ca83e8a /include/codec
parente3fa811657ecf4ab694d026752a81080c6b10611 (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() 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 - Make initializeSwizzler return a bool instead of an SkCodec::Result (It only returned kSuccess or kInvalidInput anyway) 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 Committed: https://skia.googlesource.com/skia/+/a4b09a117d4d1ba5dda372e6a2323e653766539e Review-Url: https://codereview.chromium.org/1997703003
Diffstat (limited to 'include/codec')
-rw-r--r--include/codec/SkCodec.h97
1 files changed, 79 insertions, 18 deletions
diff --git a/include/codec/SkCodec.h b/include/codec/SkCodec.h
index 50875e46c4..f66eb85377 100644
--- a/include/codec/SkCodec.h
+++ b/include/codec/SkCodec.h
@@ -23,6 +23,10 @@ class SkData;
class SkPngChunkReader;
class SkSampler;
+namespace DM {
+class CodecSrc;
+}
+
/**
* Abstraction layer directly on top of an image codec.
*/
@@ -253,8 +257,8 @@ public:
* If the EncodedFormat is kWEBP_SkEncodedFormat (the only one which
* currently supports subsets), the top and left values must be even.
*
- * In getPixels, we will attempt to decode the exact rectangular
- * subset specified by fSubset.
+ * In getPixels and incremental decode, we will attempt to decode the
+ * exact rectangular subset specified by fSubset.
*
* In a scanline decode, it does not make sense to specify a subset
* top or subset height, since the client already controls which rows
@@ -349,6 +353,67 @@ public:
}
/**
+ * Prepare for an incremental decode with the specified options.
+ *
+ * This may require a rewind.
+ *
+ * @param dstInfo Info of the destination. If the dimensions do not match
+ * those of getInfo, this implies a scale.
+ * @param dst Memory to write to. Needs to be large enough to hold the subset,
+ * if present, or the full image as described in dstInfo.
+ * @param options Contains decoding options, including if memory is zero
+ * initialized and whether to decode a subset.
+ * @param ctable A pointer to a color table. When dstInfo.colorType() is
+ * kIndex8, this should be non-NULL and have enough storage for 256
+ * colors. The color table will be populated after decoding the palette.
+ * @param ctableCount A pointer to the size of the color table. When
+ * dstInfo.colorType() is kIndex8, this should be non-NULL. It will
+ * be modified to the true size of the color table (<= 256) after
+ * decoding the palette.
+ * @return Enum representing success or reason for failure.
+ */
+ Result startIncrementalDecode(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,
+ const SkCodec::Options*, SkPMColor* ctable, int* ctableCount);
+
+ Result startIncrementalDecode(const SkImageInfo& dstInfo, void* dst, size_t rowBytes,
+ const SkCodec::Options* options) {
+ return this->startIncrementalDecode(dstInfo, dst, rowBytes, options, nullptr, nullptr);
+ }
+
+ Result startIncrementalDecode(const SkImageInfo& dstInfo, void* dst, size_t rowBytes) {
+ return this->startIncrementalDecode(dstInfo, dst, rowBytes, nullptr, nullptr, nullptr);
+ }
+
+ /**
+ * Start/continue the incremental decode.
+ *
+ * Not valid to call before calling startIncrementalDecode().
+ *
+ * After the first call, should only be called again if more data has been
+ * provided to the source SkStream.
+ *
+ * Unlike getPixels and getScanlines, this does not do any filling. This is
+ * left up to the caller, since they may be skipping lines or continuing the
+ * decode later. In the latter case, they may choose to initialize all lines
+ * first, or only initialize the remaining lines after the first call.
+ *
+ * @param rowsDecoded Optional output variable returning the total number of
+ * lines initialized. Only meaningful if this method returns kIncompleteInput.
+ * Otherwise the implementation may not set it.
+ * Note that some implementations may have initialized this many rows, but
+ * not necessarily finished those rows (e.g. interlaced PNG). This may be
+ * useful for determining what rows the client needs to initialize.
+ * @return kSuccess if all lines requested in startIncrementalDecode have
+ * been completely decoded. kIncompleteInput otherwise.
+ */
+ Result incrementalDecode(int* rowsDecoded = nullptr) {
+ if (!fStartedIncrementalDecode) {
+ return kInvalidParameters;
+ }
+ return this->onIncrementalDecode(rowsDecoded);
+ }
+
+ /**
* The remaining functions revolve around decoding scanlines.
*/
@@ -468,17 +533,6 @@ public:
* Interlaced gifs are an example.
*/
kOutOfOrder_SkScanlineOrder,
-
- /*
- * Indicates that the entire image must be decoded in order to output
- * any amount of scanlines. In this case, it is a REALLY BAD IDEA to
- * request scanlines 1-by-1 or in small chunks. The client should
- * determine which scanlines are needed and ask for all of them in
- * a single call to getScanlines().
- *
- * Interlaced pngs are an example.
- */
- kNone_SkScanlineOrder,
};
/**
@@ -627,11 +681,6 @@ protected:
*/
virtual SkScanlineOrder onGetScanlineOrder() const { return kTopDown_SkScanlineOrder; }
- /**
- * Update the current scanline. Used by interlaced png.
- */
- void updateCurrScanline(int newY) { fCurrScanline = newY; }
-
const SkImageInfo& dstInfo() const { return fDstInfo; }
const SkCodec::Options& options() const { return fOptions; }
@@ -658,6 +707,7 @@ private:
SkImageInfo fDstInfo;
SkCodec::Options fOptions;
int fCurrScanline;
+ bool fStartedIncrementalDecode;
/**
* Return whether these dimensions are supported as a scale.
@@ -678,6 +728,16 @@ private:
return kUnimplemented;
}
+ virtual Result onStartIncrementalDecode(const SkImageInfo& /*dstInfo*/, void*, size_t,
+ const SkCodec::Options&, SkPMColor*, int*) {
+ return kUnimplemented;
+ }
+
+ virtual Result onIncrementalDecode(int*) {
+ return kUnimplemented;
+ }
+
+
virtual bool onSkipScanlines(int /*countLines*/) { return false; }
virtual int onGetScanlines(void* /*dst*/, int /*countLines*/, size_t /*rowBytes*/) { return 0; }
@@ -709,6 +769,7 @@ private:
*/
virtual SkSampler* getSampler(bool /*createIfNecessary*/) { return nullptr; }
+ friend class DM::CodecSrc; // for fillIncompleteImage
friend class SkSampledCodec;
friend class SkIcoCodec;
};