This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
Quality loss when quantizing an image that already has (fewer than) 256 colors #2861
Closed
4 tasks done
Labels
Prerequisites
DEBUG
andRELEASE
modeImageSharp version
3.1.6
Other ImageSharp packages and versions
n/a
Environment (Operating system, version and so on)
Windows 10
.NET Framework version
.NET 8
Description
I've been saving 256-color images as 8-bit indexed pngs, gifs and bmps, using a
PaletteQuantizer
. In theory, they should not be negatively affected by quantization, because the images already contain 256 or fewer colors. In practice, I'm occasionally seeing quality loss, with output images not making use of the full palette.This appears to be caused by the
EuclideanPixelMap
(specifically itsColorDistanceCache
) thatPaletteQuantizer
is using. The color distance cache is lopping off the lowest 3 bits of the RGB values, which is quite troublesome for gradients. From the discussion in #1350 I understand that this is a memory usage optimization, but in my case a simple dictionary would work just fine, because all colors are already present in the palette anyway. If a trade-off has to be made, perhaps it should be configurable?I also know that it's possible to create a custom
IQuantizer
implementation, but there are two problems with that:IndexedImageFrame<TPixel>
doesn't have a public constructor. It's possible to create an instance using reflection, but that's brittle.PngEncoderCore
andGifEncoderCore
only use the given quantizer for the first frame. For subsequent frames, they use aPaletteQuantizer
, which re-introduces the quality loss problem.What I actually want to achieve is a bit more strict: I want to preserve the exact index data of the original image, even when a palette contains duplicate colors. I don't expect a standard quantizer to handle such a niche scenario, but it would be very useful if encoders would use the given quantizer for all frames, not just the first frame.
Steps to Reproduce
Images
Expected output:

Actual output (zoom in to see the banding):

The text was updated successfully, but these errors were encountered: