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: