aboutsummaryrefslogtreecommitdiffhomepage
path: root/include/codec
diff options
context:
space:
mode:
authorGravatar scroggo <scroggo@chromium.org>2016-06-02 14:16:43 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-06-02 14:16:43 -0700
commit6fb2391b2cc83ee2160b4e994faa8128975acc1f (patch)
treec27833e424302058ef076f50a0b6760079bc1cea /include/codec
parent3965825b97a5809454f5810f7e603cbd02daa036 (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 Committed: https://skia.googlesource.com/skia/+/30e78c9737ff4861dc4e3fa1e4cd010680ed6965 Review-Url: https://codereview.chromium.org/1997703003
Diffstat (limited to 'include/codec')
-rw-r--r--include/codec/SkCodec.h96
1 files changed, 76 insertions, 20 deletions
diff --git a/include/codec/SkCodec.h b/include/codec/SkCodec.h
index a2bea14d59..f931f2bb12 100644
--- a/include/codec/SkCodec.h
+++ b/include/codec/SkCodec.h
@@ -24,10 +24,10 @@ class SkPngChunkReader;
class SkSampler;
namespace DM {
+class CodecSrc;
class ColorCodecSrc;
}
-
/**
* Abstraction layer directly on top of an image codec.
*/
@@ -258,8 +258,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
@@ -354,6 +354,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.
*/
@@ -473,17 +534,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,
};
/**
@@ -632,11 +682,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; }
@@ -668,6 +713,7 @@ private:
SkImageInfo fDstInfo;
SkCodec::Options fOptions;
int fCurrScanline;
+ bool fStartedIncrementalDecode;
/**
* Return whether these dimensions are supported as a scale.
@@ -688,6 +734,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; }
@@ -722,7 +778,7 @@ private:
// For testing with qcms
// FIXME: Remove this when we are done comparing with qcms.
friend class DM::ColorCodecSrc;
-
+ friend class DM::CodecSrc; // for fillIncompleteImage
friend class SkSampledCodec;
friend class SkIcoCodec;
};