diff options
Diffstat (limited to 'src/codec')
-rw-r--r-- | src/codec/SkCodec_libbmp.cpp | 4 | ||||
-rw-r--r-- | src/codec/SkCodec_libgif.cpp | 4 | ||||
-rw-r--r-- | src/codec/SkCodec_libico.cpp | 4 | ||||
-rw-r--r-- | src/codec/SkCodec_libpng.cpp | 4 | ||||
-rw-r--r-- | src/codec/SkCodec_wbmp.cpp | 6 | ||||
-rw-r--r-- | src/codec/SkJpegCodec.cpp | 5 | ||||
-rw-r--r-- | src/codec/SkWebpCodec.cpp | 64 | ||||
-rw-r--r-- | src/codec/SkWebpCodec.h | 2 |
8 files changed, 87 insertions, 6 deletions
diff --git a/src/codec/SkCodec_libbmp.cpp b/src/codec/SkCodec_libbmp.cpp index 3ac4b0b8ab..bd5d2ca7c5 100644 --- a/src/codec/SkCodec_libbmp.cpp +++ b/src/codec/SkCodec_libbmp.cpp @@ -585,6 +585,10 @@ SkCodec::Result SkBmpCodec::onGetPixels(const SkImageInfo& dstInfo, return kCouldNotRewind; } } + if (opts.fSubset) { + // Subsets are not supported. + return kUnimplemented; + } if (dstInfo.dimensions() != this->getInfo().dimensions()) { SkCodecPrintf("Error: scaling not supported.\n"); return kInvalidScale; diff --git a/src/codec/SkCodec_libgif.cpp b/src/codec/SkCodec_libgif.cpp index fb578f2bea..9b15151f10 100644 --- a/src/codec/SkCodec_libgif.cpp +++ b/src/codec/SkCodec_libgif.cpp @@ -257,6 +257,10 @@ SkCodec::Result SkGifCodec::onGetPixels(const SkImageInfo& dstInfo, } // Check for valid input parameters + if (opts.fSubset) { + // Subsets are not supported. + return kUnimplemented; + } if (dstInfo.dimensions() != this->getInfo().dimensions()) { return gif_error("Scaling not supported.\n", kInvalidScale); } diff --git a/src/codec/SkCodec_libico.cpp b/src/codec/SkCodec_libico.cpp index 97404afed0..7df4879442 100644 --- a/src/codec/SkCodec_libico.cpp +++ b/src/codec/SkCodec_libico.cpp @@ -229,6 +229,10 @@ SkCodec::Result SkIcoCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, const Options& opts, SkPMColor* ct, int* ptr) { + if (opts.fSubset) { + // Subsets are not supported. + return kUnimplemented; + } // We return invalid scale if there is no candidate image with matching // dimensions. Result result = kInvalidScale; diff --git a/src/codec/SkCodec_libpng.cpp b/src/codec/SkCodec_libpng.cpp index 7f9aeaa091..553233de12 100644 --- a/src/codec/SkCodec_libpng.cpp +++ b/src/codec/SkCodec_libpng.cpp @@ -517,6 +517,10 @@ SkCodec::Result SkPngCodec::onGetPixels(const SkImageInfo& requestedInfo, void* if (!conversion_possible(requestedInfo, this->getInfo())) { return kInvalidConversion; } + if (options.fSubset) { + // Subsets are not supported. + return kUnimplemented; + } if (requestedInfo.dimensions() != this->getInfo().dimensions()) { return kInvalidScale; } diff --git a/src/codec/SkCodec_wbmp.cpp b/src/codec/SkCodec_wbmp.cpp index 9709a689b1..35ac808219 100644 --- a/src/codec/SkCodec_wbmp.cpp +++ b/src/codec/SkCodec_wbmp.cpp @@ -103,7 +103,7 @@ SkEncodedFormat SkWbmpCodec::onGetEncodedFormat() const { SkCodec::Result SkWbmpCodec::onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, - const Options&, + const Options& options, SkPMColor ctable[], int* ctableCount) { SkCodec::RewindState rewindState = this->rewindIfNeeded(); @@ -112,6 +112,10 @@ SkCodec::Result SkWbmpCodec::onGetPixels(const SkImageInfo& info, } else if (rewindState == kRewound_RewindState) { (void)read_header(this->stream(), NULL); } + if (options.fSubset) { + // Subsets are not supported. + return kUnimplemented; + } if (info.dimensions() != this->getInfo().dimensions()) { return kInvalidScale; } diff --git a/src/codec/SkJpegCodec.cpp b/src/codec/SkJpegCodec.cpp index 28e1e12bfc..5acc0b396c 100644 --- a/src/codec/SkJpegCodec.cpp +++ b/src/codec/SkJpegCodec.cpp @@ -308,6 +308,11 @@ SkCodec::Result SkJpegCodec::onGetPixels(const SkImageInfo& dstInfo, return fDecoderMgr->returnFailure("could not rewind stream", kCouldNotRewind); } + if (options.fSubset) { + // Subsets are not supported. + return kUnimplemented; + } + // Get a pointer to the decompress info since we will use it quite frequently jpeg_decompress_struct* dinfo = fDecoderMgr->dinfo(); diff --git a/src/codec/SkWebpCodec.cpp b/src/codec/SkWebpCodec.cpp index 32a8b78b14..fea557d21e 100644 --- a/src/codec/SkWebpCodec.cpp +++ b/src/codec/SkWebpCodec.cpp @@ -125,8 +125,26 @@ static WEBP_CSP_MODE webp_decode_mode(SkColorType ct, bool premultiply) { // is arbitrary. static const size_t BUFFER_SIZE = 4096; +bool SkWebpCodec::onGetValidSubset(SkIRect* desiredSubset) const { + if (!desiredSubset) { + return false; + } + + SkIRect bounds = SkIRect::MakeSize(this->getInfo().dimensions()); + if (!desiredSubset->intersect(bounds)) { + return false; + } + + // As stated below, libwebp snaps to even left and top. Make sure top and left are even, so we + // decode this exact subset. + // Leave right and bottom unmodified, so we suggest a slightly larger subset than requested. + desiredSubset->fLeft = (desiredSubset->fLeft >> 1) << 1; + desiredSubset->fTop = (desiredSubset->fTop >> 1) << 1; + return true; +} + SkCodec::Result SkWebpCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst, size_t rowBytes, - const Options&, SkPMColor*, int*) { + const Options& options, SkPMColor*, int*) { switch (this->rewindIfNeeded()) { case kCouldNotRewind_RewindState: return kCouldNotRewind; @@ -153,12 +171,48 @@ SkCodec::Result SkWebpCodec::onGetPixels(const SkImageInfo& dstInfo, void* dst, // Free any memory associated with the buffer. Must be called last, so we declare it first. SkAutoTCallVProc<WebPDecBuffer, WebPFreeDecBuffer> autoFree(&(config.output)); - SkISize dimensions = dstInfo.dimensions(); - if (this->getInfo().dimensions() != dimensions) { + SkIRect bounds = SkIRect::MakeSize(this->getInfo().dimensions()); + if (options.fSubset) { + // Caller is requesting a subset. + if (!bounds.contains(*options.fSubset)) { + // The subset is out of bounds. + return kInvalidParameters; + } + + bounds = *options.fSubset; + + // This is tricky. libwebp snaps the top and left to even values. We could let libwebp + // do the snap, and return a subset which is a different one than requested. The problem + // with that approach is that the caller may try to stitch subsets together, and if we + // returned different subsets than requested, there would be artifacts at the boundaries. + // Instead, we report that we cannot support odd values for top and left.. + if (!SkIsAlign2(bounds.fLeft) || !SkIsAlign2(bounds.fTop)) { + return kInvalidParameters; + } + +#ifdef SK_DEBUG + { + // Make a copy, since getValidSubset can change its input. + SkIRect subset(bounds); + // That said, getValidSubset should *not* change its input, in this case; otherwise + // getValidSubset does not match the actual subsets we can do. + SkASSERT(this->getValidSubset(&subset) && subset == bounds); + } +#endif + + config.options.use_cropping = 1; + config.options.crop_left = bounds.fLeft; + config.options.crop_top = bounds.fTop; + config.options.crop_width = bounds.width(); + config.options.crop_height = bounds.height(); + } + + SkISize dstDimensions = dstInfo.dimensions(); + if (bounds.size() != dstDimensions) { // Caller is requesting scaling. config.options.use_scaling = 1; - config.options.scaled_width = dimensions.width(); - config.options.scaled_height = dimensions.height(); + config.options.scaled_width = dstDimensions.width(); + config.options.scaled_height = dstDimensions.height(); } config.output.colorspace = webp_decode_mode(dstInfo.colorType(), diff --git a/src/codec/SkWebpCodec.h b/src/codec/SkWebpCodec.h index 9ea6a94ecb..1fd3acbd16 100644 --- a/src/codec/SkWebpCodec.h +++ b/src/codec/SkWebpCodec.h @@ -30,6 +30,8 @@ protected: } SkISize onGetScaledDimensions(float desiredScale) const override; + + bool onGetValidSubset(SkIRect* /* desiredSubset */) const override; private: SkWebpCodec(const SkImageInfo&, SkStream*); |