weserv / images

Source code of wsrv.nl (formerly images.weserv.nl), to be used on your own server(s).
https://wsrv.nl/
BSD 3-Clause "New" or "Revised" License
1.86k stars 187 forks source link

Disable/reduce gif quantization? #293

Open sudofox opened 3 years ago

sudofox commented 3 years ago

Input image: https://www.hatena.ne.jp/images/what/what-riyo-img.gif

image

255 colors in image

Output image: https://images.weserv.nl/?url=https://www.hatena.ne.jp/images/what/what-riyo-img.gif

image

254 colors in image. Visible degradation in the frog. I like quantization, but I can't find any option to change how it behaves for GIFs. (also the fact that it didn't just chose one of the lesser-used colors while quantizing bugs me slightly)

kleisauke commented 3 years ago

It looks like ImageMagick applies by default a Riemersma dither during GIF encoding. https://github.com/ImageMagick/ImageMagick6/blob/94026fbfb045d27576799d84ee63320ba7cbc7aa/magick/quantize.c#L2260-L2261

Dithers introduces by definition distributed distortion, but you're right, there's currently no way to change it (e.g. using Floyd-Steinberg dithering) or to turn if off (which could be useful for GIF to GIF processing). This requires adding an additional parameter in vips_magicksave that controls the dithering.

As for this particular image, I was able to reproduce this with the ImageMagick's convert tool, so maybe it's a bug there.

# Convert to PNG first to ensure *magick enables dithering
$ convert x.gif x.png
# Convert the PNG to GIF with a various set of dithers
$ convert x.png -dither None none.gif
$ convert x.png -dither Riemersma riemersma.gif
$ convert x.png -dither FloydSteinberg floyd-steinberg.gif
none.gif riemersma.gif floyd-steinberg.gif
none riemersma floyd-steinberg
kleisauke commented 2 years ago

We're now A/B testing libvips 8.12 in production, which includes a new gifsave operation that doesn't use ImageMagick for saving GIF images. This particular quantization bug seems to be fixed now, but please report if you see anything strange.

There's some discussion to add indexed read/write support to libvips. This would avoid unpacking to RGB(A) and re-quantization for GIF images that are processed without performing any operations on the image (like this example), but it's not there yet.