aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/codec
diff options
context:
space:
mode:
Diffstat (limited to 'src/codec')
-rw-r--r--src/codec/SkCodec_libbmp.cpp4
-rw-r--r--src/codec/SkCodec_libgif.cpp4
-rw-r--r--src/codec/SkCodec_libico.cpp4
-rw-r--r--src/codec/SkCodec_libpng.cpp4
-rw-r--r--src/codec/SkCodec_wbmp.cpp6
-rw-r--r--src/codec/SkJpegCodec.cpp5
-rw-r--r--src/codec/SkWebpCodec.cpp64
-rw-r--r--src/codec/SkWebpCodec.h2
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*);