[x] I have verified that I am running the latest version of ImageSharp
[x] I have verified if the problem exist in both DEBUG and RELEASE mode
[x] I have searched open and closed issues to ensure it has not already been reported
Description
Running the ErrorDiffusionPaletteProcessor on a quantized image with the same palette that was used for quantization modifies the image. This is not desirable since the point of dithering is to improve visual fidelity with the limited palette, while in this case a perfectly faithful quantized image is modified and image quality is degraded.
Of course a dithering algorithm can't work well for 100% of cases, but bad quality on perfectly quantized images can prove an issue in practice. With a two-pass quantization algorithm on an image with few distinct colors this results in bad image quality.
Since all references I found just got the closest color in the palette, I tried changing the implementation to get only the closest color. I didn't see worse visual quality in the test images I ran the diffusion on, though I must say I don't have a trained eye (and I guess this might be subjective too).
The single-pixel implementation also provides a major performance benefit compared to the current implementation. When dithering we can check if there is no error and skip the dither for the pixel. For images that have few colors or all colors in the palette this provides a major speed boost. I added some tests to the benchmark project with 3 images; the lake image from the test set (lots of colors), the lake image quantized with 256 colors and processed with a palette of 128 colors, and the lake image quantized and processed with the full quantization palette.
In the sample code below I used the jpeg444.jpg that's included in the test folder. It looks like this:
The sample uses the web palette quantizer. It can be run in the Sandbox project.
var path = Path.Combine(TestEnvironment.InputImagesDirectoryFullPath, TestImages.Jpeg.Baseline.Jpeg444);
var image = Image.Load<Rgba32>(path);
var frameQuantizer = new PaletteQuantizer(false).CreateFrameQuantizer<Rgba32>();
var quantizedFrame = frameQuantizer.QuantizeFrame(image.Frames[0]);
var quantized = QuantizedFrameToImage(quantizedFrame);
var diffused = quantized.Clone(c => c.Diffuse(KnownDiffusers.FloydSteinberg, .5f, quantizedFrame.Palette));
ImageComparer.Exact.VerifySimilarity(quantized, diffused); // I expected this to hold
Prerequisites
DEBUG
andRELEASE
modeDescription
Running the
ErrorDiffusionPaletteProcessor
on a quantized image with the same palette that was used for quantization modifies the image. This is not desirable since the point of dithering is to improve visual fidelity with the limited palette, while in this case a perfectly faithful quantized image is modified and image quality is degraded.Of course a dithering algorithm can't work well for 100% of cases, but bad quality on perfectly quantized images can prove an issue in practice. With a two-pass quantization algorithm on an image with few distinct colors this results in bad image quality.
The code responsible is here:
Since all references I found just got the closest color in the palette, I tried changing the implementation to get only the closest color. I didn't see worse visual quality in the test images I ran the diffusion on, though I must say I don't have a trained eye (and I guess this might be subjective too).
The single-pixel implementation also provides a major performance benefit compared to the current implementation. When dithering we can check if there is no error and skip the dither for the pixel. For images that have few colors or all colors in the palette this provides a major speed boost. I added some tests to the benchmark project with 3 images; the lake image from the test set (lots of colors), the lake image quantized with 256 colors and processed with a palette of 128 colors, and the lake image quantized and processed with the full quantization palette.
Results before:
Results after:
My branch with the benchmark added (under Processing/Dither.cs) can be found at
Jjagg/ImageSharp/diffuse-palette
.Steps to Reproduce
In the sample code below I used the
jpeg444.jpg
that's included in the test folder. It looks like this:The sample uses the web palette quantizer. It can be run in the Sandbox project.
After quantization:
After diffusion:
System Configuration