From b2a867c03812bfbb4dbe04bbe349788436e6d68c Mon Sep 17 00:00:00 2001 From: Yannis Guyon Date: Tue, 25 Sep 2018 13:02:30 +0200 Subject: cwebp: Don't premultiply during -resize if -exact Fix issue where color data is discarded in fully transparent areas when -resize -exact. BUG=webp:397 Change-Id: I58ce8d5ae172d5d0f0138e07c7df3a3c6cbd0019 --- examples/cwebp.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/examples/cwebp.c b/examples/cwebp.c index 3b1e1171..7b1836d3 100644 --- a/examples/cwebp.c +++ b/examples/cwebp.c @@ -1012,10 +1012,53 @@ int main(int argc, const char *argv[]) { } } if ((resize_w | resize_h) > 0) { + WebPPicture picture_no_alpha; + if (config.exact) { + // If -exact, we can't premultiply RGB by A otherwise RGB is lost if A=0. + // We rescale an opaque copy and assemble scaled A and non-premultiplied + // RGB channels. This is slower but it's a very uncommon use case. Color + // leak at sharp alpha edges is possible. + if (!WebPPictureCopy(&picture, &picture_no_alpha)) { + fprintf(stderr, "Error! Cannot copy temporary picture\n"); + goto Error; + } + + // We enforced picture.use_argb = 1 above. Now, remove the alpha values. + { + int x, y; + uint32_t* argb_no_alpha = picture_no_alpha.argb; + for (y = 0; y < picture_no_alpha.height; ++y) { + for (x = 0; x < picture_no_alpha.width; ++x) { + argb_no_alpha[x] |= 0xff000000; // Opaque copy. + } + argb_no_alpha += picture_no_alpha.argb_stride; + } + } + + if (!WebPPictureRescale(&picture_no_alpha, resize_w, resize_h)) { + fprintf(stderr, "Error! Cannot resize temporary picture\n"); + goto Error; + } + } + if (!WebPPictureRescale(&picture, resize_w, resize_h)) { fprintf(stderr, "Error! Cannot resize picture\n"); goto Error; } + + if (config.exact) { // Put back the alpha information. + int x, y; + uint32_t* argb_no_alpha = picture_no_alpha.argb; + uint32_t* argb = picture.argb; + for (y = 0; y < picture_no_alpha.height; ++y) { + for (x = 0; x < picture_no_alpha.width; ++x) { + argb[x] = (argb[x] & 0xff000000) | (argb_no_alpha[x] & 0x00ffffff); + } + argb_no_alpha += picture_no_alpha.argb_stride; + argb += picture.argb_stride; + } + WebPPictureFree(&picture_no_alpha); + } } if (verbose && (crop != 0 || (resize_w | resize_h) > 0)) { const double preproc_time = StopwatchReadAndReset(&stop_watch); -- cgit v1.2.1