mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-25 02:07:09 -06:00
Indexed export (GIF, PNG-8, BMP, TIFF) finds each pixel's nearest palette entry with a linear scan, and the k-means refinement in median cut does the same once per cell per pass. With the 256-entry palettes this code produces, that is 256 distance evaluations per query. PaletteIndex is an exact nearest-neighbour kd-tree over the palette, balanced at the widest weighted axis, with tight channel bounds in every subtree so branch-and-bound can skip whole boxes. Small palettes (12 or fewer entries) keep the scan, which is cheaper than tree traversal. Results match the linear scan exactly, including ties: an equal-distance entry with a smaller index still wins. The bound uses the same weighted squared f32 form as dist() rather than a transformed space, so rounding cannot change which entry is chosen. Three tests: randomized parity against the original scan across palette sizes spanning the cutoff, three weight vectors, duplicate colours and fractional query points; explicit tie-breaking cases; and an opt-in benchmark comparing 100k queries at both, behind -- --ignored.