Repository navigation
[V4] Keep decoded palette colors exact when encoding - #3274
Merged
Merged
Conversation
The PNG, GIF and icon encoders reuse a decoded palette without dithering to keep the original colors. They used the default coarse color matching, which maps colors that share a 5-bit bucket to one entry. They now use exact matching. The first GIF frame quantized with the encoder options instead of the options of the decoded global palette, so it dithered against that palette. It now uses the palette options. The 1-, 2- and 4-bit BMP paths built new quantizer options from the dither settings only. They dropped the color matching mode, the transparent color mode and the transparency threshold of the configured quantizer. They now clone the quantizer options and set only the color count. The Issue2866 reference frames are updated. Against the decoded source, the new output has less error on each compared frame, and frame 0 is exact.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Prerequisites
Description
This PR fixes three faults that change colors when an encoder reuses a palette or a configured quantizer.
Coarse matching of decoded palettes
The PNG, GIF and icon encoders reuse a decoded palette without dithering, to keep the original colors. They used the default
ColorMatchingMode.Coarse. The coarse cache keeps 5 bits of each channel, so palette colors that share a bucket map to one entry. For example, the red values 8 and 12 map to the same entry. These paths now useColorMatchingMode.Exact:PngEncoderCore: the palette fromPngMetadata.ColorTable.GifEncoderCore: the global color table, and the local color table with and without a reserved transparent index.IconEncoderCore: the palette from the icon frame metadata.GIF first frame
When the GIF encoder reuses the decoded global color table, the first frame quantized with the encoder options, not the options of the palette quantizer. So the first frame dithered against the decoded palette, although the comment says that it does not. The palette branch now replaces the options, so the first frame uses them.
BMP 1-, 2- and 4-bit options
These paths built new quantizer options from
DitherandDitherScaleonly. They droppedColorMatchingMode,TransparentColorModeandTransparencyThresholdof the configured quantizer. They now clone the quantizer options and set onlyMaxColors.Tests
NearColorPalette: a two-color image whose colors share one coarse bucket. Only exact matching keeps both colors.PaletteQuantizeras the configured quantizer.Reference images
The
GifEncoder_CanDecode_AndEncode_Issue2866reference frames are updated. The fixture uses local color tables, so coarse matching changed some colors before. I measured the mean RGB error against the decoded source on the 15 compared frames:The tests pass on
net10.0andnet8.0.