Opened 7 months ago

Last modified 5 months ago

#2454 new defect

image_filter resize is not working correctly with some PNG files.(nginx is changing background color)

Reported by: walidlaggoune159@… 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

Hello, this is my configuration for image resizing

location ~ (?<width>\d+)\/storage\/(?<folder>.+)\/(?<image>.+)$ {
    alias /var/www/html/web/storage/app/public/$folder/$image;
    image_filter resize $width $width;
    image_filter_jpeg_quality 80;
    image_filter_buffer 20M;
}

before resize :
https://preview.redd.it/pysc1bturyfa1.png

After resize:
https://preview.redd.it/w2ku9mvzryfa1.png

Change History (5)

comment:1 by Roman Arutyunyan, 7 months ago

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.

in reply to:  1 comment:2 by walidlaggoune159@…, 7 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)

in reply to:  1 comment:3 by walidlaggoune159@…, 7 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 Maxim Dounin, 7 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.

comment:5 by maxim, 5 months ago

Milestone: nginx-1.23

Ticket retargeted after milestone closed

Note: See TracTickets for help on using tickets.