Skip to content

Make .quantize(palette=...) use exact colors when possible - #9829

Draft
akx wants to merge 13 commits into
python-pillow:mainfrom
akx:palettize-fixes
Draft

Make .quantize(palette=...) use exact colors when possible#9829
akx wants to merge 13 commits into
python-pillow:mainfrom
akx:palettize-fixes

Conversation

@akx

@akx akx commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Stacked on #9831 so we're measuring the right things...

Refs #1852 (fixes the reproducer bug, but we're still not necessarily selecting the mathematically nearest color when quantizing to a given palette).

  • Refactors the topalette() conversion function to a separate file for ease of understanding
  • Refactors the topalette() function to multiple functions for less nesting and ease of reading
  • Improves internal documentation/constants around palettes
  • Fixes a couple possible but implausible NULL pointer derefs (that could occur if there was less than ~1100 bytes of memory available for Python)
  • The usual™️ hoist + restrict optimizations for internals
  • Adds benchmarks for quantize-into-palette

... and then the main thing:

  • Adds a small linear-probing hash table for finding exact matches in the palette before looking a close-enough one up in the cache "cube" in the palette. In other words, if a palette specifies a color, we will use it, guaranteed.
  • ImagingPaletteCache* functions are made private, since the structure of the cache was undocumented and private anyway; we need to add a new flag in the cache entries to have a better guess of when we might have an exact match for a color.

EDIT: Edited away the benchmark results, there's something off here still :)

akx added 2 commits July 29, 2026 10:29
The old image was (e.g. in the case of palette optimization) pessimal in some cases.
@akx
akx force-pushed the palettize-fixes branch 2 times, most recently from c0ecde9 to 7708c8a Compare July 29, 2026 08:20
@akx
akx force-pushed the palettize-fixes branch from 7708c8a to 3eb5509 Compare July 29, 2026 08:42
@codspeed-hq

codspeed-hq Bot commented Jul 29, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 29.29%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 1 improved benchmark
❌ 1 regressed benchmark
✅ 343 untouched benchmarks
🆕 26 new benchmarks
⏩ 2 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
test_quantize[1024x1024-RGB] 234.1 ms 527.7 ms -55.65%
test_scale[1024x1024-RGB-0.01-NEAREST] 68.3 µs 60.6 µs +12.73%
🆕 test_quantize_grayscale_to_palette[1024x1024-P] N/A 1.1 ms N/A
🆕 test_quantize_grayscale_to_palette[1024x1024-PA] N/A 6.6 ms N/A
🆕 test_quantize_to_palette[1024x1024-exact-flower2-P-floyd-steinberg] N/A 56.7 ms N/A
🆕 test_quantize_to_palette[1024x1024-exact-flower2-P-none] N/A 24 ms N/A
🆕 test_quantize_to_palette[1024x1024-exact-flower2-PA-floyd-steinberg] N/A 60.8 ms N/A
🆕 test_quantize_to_palette[1024x1024-exact-flower2-PA-none] N/A 27.5 ms N/A
🆕 test_quantize_to_palette[1024x1024-exact-synthetic-P-floyd-steinberg] N/A 56.5 ms N/A
🆕 test_quantize_to_palette[1024x1024-exact-synthetic-P-none] N/A 23.8 ms N/A
🆕 test_quantize_to_palette[1024x1024-exact-synthetic-PA-floyd-steinberg] N/A 60.6 ms N/A
🆕 test_quantize_to_palette[1024x1024-exact-synthetic-PA-none] N/A 27.2 ms N/A
🆕 test_quantize_to_palette[1024x1024-grayscale-flower2-P-floyd-steinberg] N/A 49.3 ms N/A
🆕 test_quantize_to_palette[1024x1024-grayscale-flower2-P-none] N/A 16.7 ms N/A
🆕 test_quantize_to_palette[1024x1024-grayscale-flower2-PA-floyd-steinberg] N/A 53.3 ms N/A
🆕 test_quantize_to_palette[1024x1024-grayscale-flower2-PA-none] N/A 20.2 ms N/A
🆕 test_quantize_to_palette[1024x1024-grayscale-synthetic-P-floyd-steinberg] N/A 49.7 ms N/A
🆕 test_quantize_to_palette[1024x1024-grayscale-synthetic-P-none] N/A 16.9 ms N/A
🆕 test_quantize_to_palette[1024x1024-grayscale-synthetic-PA-floyd-steinberg] N/A 53.8 ms N/A
🆕 test_quantize_to_palette[1024x1024-grayscale-synthetic-PA-none] N/A 20.4 ms N/A
... ... ... ... ...

ℹ️ Only the first 20 benchmarks are displayed. Go to the app to view all benchmarks.

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing akx:palettize-fixes (3eb5509) with main (abb8ba0)

Open in CodSpeed

Footnotes

  1. 2 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants