aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/codec/SkIcoCodec.cpp
diff options
context:
space:
mode:
authorGravatar scroggo <scroggo@chromium.org>2016-05-31 06:30:14 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-05-31 06:30:14 -0700
commita4b09a117d4d1ba5dda372e6a2323e653766539e (patch)
tree5ce65adf8481bb9a6f5ea24cfcbf0b208264750f /src/codec/SkIcoCodec.cpp
parent3eb7d76b9c3072c33ca8a158bc78ba864521e0f0 (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 Review-Url: https://codereview.chromium.org/1997703003
Diffstat (limited to 'src/codec/SkIcoCodec.cpp')
-rw-r--r--src/codec/SkIcoCodec.cpp81
1 files changed, 77 insertions, 4 deletions
diff --git a/src/codec/SkIcoCodec.cpp b/src/codec/SkIcoCodec.cpp
index 0e81b72407..a80b9df3cf 100644
--- a/src/codec/SkIcoCodec.cpp
+++ b/src/codec/SkIcoCodec.cpp
@@ -15,6 +15,7 @@
#include "SkTDArray.h"
#include "SkTSort.h"
+#ifdef SK_HAS_PNG_LIBRARY
/*
* Checks the start of the stream to see if the image is an Ico or Cur
*/
@@ -186,6 +187,7 @@ SkIcoCodec::SkIcoCodec(int width, int height, const SkEncodedInfo& info,
: INHERITED(width, height, info, nullptr)
, fEmbeddedCodecs(codecs)
, fCurrScanlineCodec(nullptr)
+ , fCurrIncrementalCodec(nullptr)
{}
/*
@@ -289,6 +291,7 @@ SkCodec::Result SkIcoCodec::onStartScanlineDecode(const SkImageInfo& dstInfo,
result = embeddedCodec->startScanlineDecode(dstInfo, &options, colorTable, colorCount);
if (kSuccess == result) {
fCurrScanlineCodec = embeddedCodec;
+ fCurrIncrementalCodec = nullptr;
return result;
}
@@ -309,13 +312,83 @@ bool SkIcoCodec::onSkipScanlines(int count) {
return fCurrScanlineCodec->skipScanlines(count);
}
+SkCodec::Result SkIcoCodec::onStartIncrementalDecode(const SkImageInfo& dstInfo,
+ void* pixels, size_t rowBytes, const SkCodec::Options& options,
+ SkPMColor* colorTable, int* colorCount) {
+ int index = 0;
+ while (true) {
+ index = this->chooseCodec(dstInfo.dimensions(), index);
+ if (index < 0) {
+ break;
+ }
+
+ SkCodec* embeddedCodec = fEmbeddedCodecs->operator[](index);
+ switch (embeddedCodec->startIncrementalDecode(dstInfo,
+ pixels, rowBytes, &options, colorTable, colorCount)) {
+ case kSuccess:
+ fCurrIncrementalCodec = embeddedCodec;
+ fCurrScanlineCodec = nullptr;
+ return kSuccess;
+ case kUnimplemented:
+ // FIXME: embeddedCodec is a BMP. If scanline decoding would work,
+ // return kUnimplemented so that SkSampledCodec will fall through
+ // to use the scanline decoder.
+ // Note that calling startScanlineDecode will require an extra
+ // rewind. The embedded codec has an SkMemoryStream, which is
+ // cheap to rewind, though it will do extra work re-reading the
+ // header.
+ // Also note that we pass nullptr for Options. This is because
+ // Options that are valid for incremental decoding may not be
+ // valid for scanline decoding.
+ // Once BMP supports incremental decoding this workaround can go
+ // away.
+ if (embeddedCodec->startScanlineDecode(dstInfo, nullptr,
+ colorTable, colorCount) == kSuccess) {
+ return kUnimplemented;
+ }
+ // Move on to the next embedded codec.
+ break;
+ default:
+ break;
+ }
+
+ index++;
+ }
+
+ SkCodecPrintf("Error: No matching candidate image in ico.\n");
+ return kInvalidScale;
+}
+
+SkCodec::Result SkIcoCodec::onIncrementalDecode(int* rowsDecoded) {
+ SkASSERT(fCurrIncrementalCodec);
+ return fCurrIncrementalCodec->incrementalDecode(rowsDecoded);
+}
+
SkCodec::SkScanlineOrder SkIcoCodec::onGetScanlineOrder() const {
// FIXME: This function will possibly return the wrong value if it is called
- // before startScanlineDecode().
- return fCurrScanlineCodec ? fCurrScanlineCodec->getScanlineOrder() :
- INHERITED::onGetScanlineOrder();
+ // before startScanlineDecode()/startIncrementalDecode().
+ if (fCurrScanlineCodec) {
+ SkASSERT(!fCurrIncrementalCodec);
+ return fCurrScanlineCodec->getScanlineOrder();
+ }
+
+ if (fCurrIncrementalCodec) {
+ return fCurrIncrementalCodec->getScanlineOrder();
+ }
+
+ return INHERITED::onGetScanlineOrder();
}
SkSampler* SkIcoCodec::getSampler(bool createIfNecessary) {
- return fCurrScanlineCodec ? fCurrScanlineCodec->getSampler(createIfNecessary) : nullptr;
+ if (fCurrScanlineCodec) {
+ SkASSERT(!fCurrIncrementalCodec);
+ return fCurrScanlineCodec->getSampler(createIfNecessary);
+ }
+
+ if (fCurrIncrementalCodec) {
+ return fCurrIncrementalCodec->getSampler(createIfNecessary);
+ }
+
+ return nullptr;
}
+#endif // SK_HAS_PNG_LIBRARY