From d1094847a3f6fe73133487bb62175b7b0be449db Mon Sep 17 00:00:00 2001 From: John Cupitt Date: Thu, 27 Jun 2019 16:37:11 +0100 Subject: [PATCH] remove no-alpha webp support We used to try to spot webp images with no alpha and load them as plain RGB, but it turns out this is difficult to do reliably, especially for animated images. This patch simply removes support, so all webp images now load as RGBA. See https://github.com/libvips/libvips/issues/1351 --- ChangeLog | 1 + libvips/foreign/webp2vips.c | 25 ++++++++++--------------- test/test-suite/test_foreign.py | 11 ++++++----- 3 files changed, 17 insertions(+), 20 deletions(-) diff --git a/ChangeLog b/ChangeLog index bf0e16f0..b759536d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,6 @@ 20/6/19 started 8.9.0 - add vips_image_get/set_array_int() +- remove support for no-alpha webp images, it didn't work well 24/5/19 started 8.8.1 - improve realpath() use on older libc diff --git a/libvips/foreign/webp2vips.c b/libvips/foreign/webp2vips.c index 695e87c1..95bc8056 100644 --- a/libvips/foreign/webp2vips.c +++ b/libvips/foreign/webp2vips.c @@ -20,6 +20,9 @@ * 30/4/19 * - deprecate shrink, use scale instead, and make it a double ... this * lets us do faster and more accurate thumbnailing + * 27/6/19 + * - remove non-alpha output: it's very hard to decide if a webp image + * really has zero transparency */ /* @@ -107,10 +110,6 @@ typedef struct { int frame_width; int frame_height; - /* TRUE for RGBA. - */ - int alpha; - /* Number of frames in file. */ int frame_count; @@ -446,11 +445,10 @@ read_header( Read *read, VipsImage *out ) flags = WebPDemuxGetI( read->demux, WEBP_FF_FORMAT_FLAGS ); - read->alpha = flags & ALPHA_FLAG; - if( read->alpha ) - read->config.output.colorspace = MODE_RGBA; - else - read->config.output.colorspace = MODE_RGB; + /* The alpha flag says if this square of pixels in this frame has an + * alpha, not if our output image should have an alpha. + */ + read->config.output.colorspace = MODE_RGBA; if( flags & ANIMATION_FLAG ) { int loop_count; @@ -534,8 +532,7 @@ read_header( Read *read, VipsImage *out ) read->frame = vips_image_new_memory(); vips_image_init_fields( read->frame, - read->frame_width, read->frame_height, - read->alpha ? 4 : 3, + read->frame_width, read->frame_height, 4, VIPS_FORMAT_UCHAR, VIPS_CODING_NONE, VIPS_INTERPRETATION_sRGB, 1.0, 1.0 ); @@ -545,8 +542,7 @@ read_header( Read *read, VipsImage *out ) return( -1 ); vips_image_init_fields( out, - read->width, read->height, - read->alpha ? 4 : 3, + read->width, read->height, 4, VIPS_FORMAT_UCHAR, VIPS_CODING_NONE, VIPS_INTERPRETATION_sRGB, 1.0, 1.0 ); @@ -598,8 +594,7 @@ read_frame( Read *read, frame = vips_image_new_memory(); vips_image_init_fields( frame, - width, height, - read->alpha ? 4 : 3, + width, height, 4, VIPS_FORMAT_UCHAR, VIPS_CODING_NONE, VIPS_INTERPRETATION_sRGB, 1.0, 1.0 ); diff --git a/test/test-suite/test_foreign.py b/test/test-suite/test_foreign.py index b260705a..5383040c 100644 --- a/test/test-suite/test_foreign.py +++ b/test/test-suite/test_foreign.py @@ -23,6 +23,7 @@ class TestForeign: cls.tempdir = tempfile.mkdtemp() cls.colour = pyvips.Image.jpegload(JPEG_FILE) + cls.rgba = cls.colour.bandjoin(255) cls.mono = cls.colour.extract_band(1) # we remove the ICC profile: the RGB one will no longer be appropriate cls.mono.remove("icc-profile-data") @@ -463,22 +464,22 @@ class TestForeign: def test_webp(self): def webp_valid(im): a = im(10, 10) - assert_almost_equal_objects(a, [71, 166, 236]) + assert_almost_equal_objects(a, [70, 165, 235, 255]) assert im.width == 550 assert im.height == 368 - assert im.bands == 3 + assert im.bands == 4 self.file_loader("webpload", WEBP_FILE, webp_valid) self.buffer_loader("webpload_buffer", WEBP_FILE, webp_valid) self.save_load_buffer("webpsave_buffer", "webpload_buffer", - self.colour, 60) - self.save_load("%s.webp", self.colour) + self.rgba, 60) + self.save_load("%s.webp", self.rgba) # test lossless mode im = pyvips.Image.new_from_file(WEBP_FILE) buf = im.webpsave_buffer(lossless=True) im2 = pyvips.Image.new_from_buffer(buf, "") - assert im.avg() == im2.avg() + assert abs(im.avg() - im2.avg()) < 1 # higher Q should mean a bigger buffer b1 = im.webpsave_buffer(Q=10)