Treat kWEBP encode with quality=100 as lossless
In SkEncodeImage and friends, treat quality of 100 as a lossless encode
when using kWEBP. This seems a good fit for the intent - which is
presumably to save the highest quality image. This also matches
Chromium's blink::ImageEncoder::ComputeWebpOptions, which treats a
quality of 1 (on a float scale from 0 to 1) as a lossless encode.
FWIW, Chromium has had this behavior since
https://codereview.chromium.org/1937433002, in response to
crbug.com/523098. The goal is to "maintain sharpness to
match the JPEG encoder behavior (use WEBP lossless encoding)".
Add a test to verify the new behavior. This requires making tests
depend on libwebp to use WebPGetFeatures, since the Skia API does not
provide a way to determine whether an encoded webp file was encoded
lossless-ly or lossily.
Bug: skia:8586
Change-Id: Ie9e09c2f7414ab701d696c4ad9edf405868a716f
Reviewed-on: https://skia-review.googlesource.com/c/175823
Commit-Queue: Leon Scroggins <scroggo@google.com>
Reviewed-by: Derek Sollenberger <djsollen@google.com>
Reviewed-by: Mike Reed <reed@google.com>
diff --git a/src/images/SkImageEncoder.cpp b/src/images/SkImageEncoder.cpp
index 946a67f..d5cf2ec 100644
--- a/src/images/SkImageEncoder.cpp
+++ b/src/images/SkImageEncoder.cpp
@@ -48,8 +48,25 @@
}
case SkEncodedImageFormat::kWEBP: {
SkWebpEncoder::Options opts;
- opts.fCompression = SkWebpEncoder::Compression::kLossy;
- opts.fQuality = quality;
+ if (quality == 100) {
+ opts.fCompression = SkWebpEncoder::Compression::kLossless;
+ // Note: SkEncodeImage treats 0 quality as the lowest quality
+ // (greatest compression) and 100 as the highest quality (least
+ // compression). For kLossy, this matches libwebp's
+ // interpretation, so it is passed directly to libwebp. But
+ // with kLossless, libwebp always creates the highest quality
+ // image. In this case, fQuality is reinterpreted as how much
+ // effort (time) to put into making a smaller file. This API
+ // does not provide a way to specify this value (though it can
+ // be specified by using SkWebpEncoder::Encode) so we have to
+ // pick one arbitrarily. This value matches that chosen by
+ // blink::ImageEncoder::ComputeWebpOptions as well
+ // WebPConfigInit.
+ opts.fQuality = 75;
+ } else {
+ opts.fCompression = SkWebpEncoder::Compression::kLossy;
+ opts.fQuality = quality;
+ }
return SkWebpEncoder::Encode(dst, src, opts);
}
default: