Opened 21 months ago
Last modified 11 months ago
#2454 new defect
image_filter resize is not working correctly with some PNG files.(nginx is changing background color)
Reported by: | Owned by: | ||
---|---|---|---|
Priority: | minor | Milestone: | |
Component: | nginx-module | Version: | 1.23.x |
Keywords: | image resize, image filter | Cc: | walidlaggoune159@… |
uname -a: | Linux 5fc57c61112f 5.15.0-60-generic #66-Ubuntu SMP Fri Jan 20 14:29:49 UTC 2023 x86_64 GNU/Linux | ||
nginx -V: | nginx version: nginx/1.23.2 |
Description
Attachments (1)
Change History (7)
follow-ups: 2 3 comment:1 by , 21 months ago
comment:2 by , 21 months ago
Replying to Roman Arutyunyan:
Just tried this with this image and everything seems to be ok, the background is just fine. Try updating libgd. Mine is: gd2 @2.3.3_2.
How i can check my libgd version ? (i am using nginx image with docker)
comment:3 by , 21 months ago
Replying to Roman Arutyunyan:
Just tried this with this image and everything seems to be ok, the background is just fine. Try updating libgd. Mine is: gd2 @2.3.3_2.
Finaly it worked (no yellow background), with nginx:1.23.3-alpine (before it was nginx:1.23.3).
but another bug appears :
original image : https://ibb.co/Br6rRqS
after resize : https://ibb.co/xgVhY6Q
comment:4 by , 21 months ago
It looks like starting with libgd 2.2.3, specifically this change, it is no longer possible to reset transparency with gdImageColorTransparent(-1)
. In particular, the corresponding color is still marked as transparent in the palette.
In libgd 2.3.1 there was an attempt to fix associated bugs, yet incomplete: the palette color is still marked as transparent after calling gdImageColorTransparent(-1)
.
Since nginx removes single-color transparency when resizing images (and restores it after resizing), the above behaviour breaks transparency in images using indexed colors with libgd from 2.2.3 to 2.3.0. Starting with libgd 2.3.1 things mostly work, though the mentioned issue might result in other bugs. Does not look like an nginx issue though.
As for the image from comment:3, it seems to be unrelated to the original issue as initially reported, and works identically in all libgd versions I've tested. The root cause is that the image is using black color both as a transparent color and a non-transparent color. That is, the image palette contains both rgba(0, 0, 0, 0)
and rgba(0, 0, 0, 127)
. Since these colors are indistinguishable after removing transparency, both become transparent after resizing.
One possible solution would be to resize such images as truecolor (with proper alpha channel) and convert them back to indexed colors later, similarly to how we do with image_filter_transparency off;
. Not sure it's a good solution though.
by , 11 months ago
Attachment: | image_filter_scale.patch added |
---|
proof of concept patch to use gdImageScale
comment:6 by , 11 months ago
This issue was also reported to libgd at https://github.com/libgd/libgd/pull/639 and a libgd developer said it may be better to use gdImageScale()
instead of gdImageCopyResampled()
.
I created a proof of concept of this (patch against nginx_1.18.0-6ubuntu14.4 ubuntu package, Ubuntu 22.04). The patch adds a new configuration option image_filter_use_scale_function
that makes it use gdImageScale()
if enabled. This appeared to fix the issue on the one PNG image with a palette and partial transparency that I tested it against.
A side effect is that the resized image is truecolour and therefore has a larger file size than necessary. For our use, this is probably not a major issue since our current workaround is to ensure the source images are truecolour (not palette-based).
By the way, ngx_http_image_filter_module does not incorporate the configuration options into the ETag, so changes to them may not be reflected in a browser unless its cache is explicitly cleared or the image is explicitly reloaded.
Just tried this with this image and everything seems to be ok, the background is just fine. Try updating libgd. Mine is: gd2 @2.3.3_2.