1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374moduletypeM=sigtypet(* variant of colour names *)valof_string:string->tvalto_code:t->intvalto_color:t->Gg.v4valcolor_list:Gg.v4listvalnearest:Gg.v4->Gg.v4endexceptionInvalidColorNameofstringmoduleOkt=Oktree.Make(Gg.V3)(*
Runtime index used by generated palette modules for fast nearest-color lookup.
We index colors in LAB space (L-star, a-star, b-star) because Euclidean distance there is
a much better approximation of perceptual difference than Euclidean RGB.
The octree stores only 3D LAB points, so we keep a reverse lookup map from
each LAB point tuple back to its original RGBA color value.
*)typenearest_index={tree:Okt.t;by_lab:((float*float*float),Gg.v4)Hashtbl.t;}(*
Convert an RGBA color to the 3 LAB coordinates used for nearest-neighbor
search. Alpha is intentionally ignored in the distance metric.
*)letlab3_of_colorcolor=letlab=Gg.Color.to_labcolorinGg.V3.v(Gg.V4.xlab)(Gg.V4.ylab)(Gg.V4.zlab)(*
Build the nearest-neighbor index (oktree + RGB:LAB map) once from a palette color list.
- [points] is the LAB point cloud used to build the octree.
- [by_lab] lets us recover the exact palette color after octree nearest
returns a LAB point.
*)letnearest_index_of_color_list?leaf_sizecolor_list=letby_lab=Hashtbl.create(List.lengthcolor_list)inletpoints=List.map(funcolor->letlab=lab3_of_colorcolorinHashtbl.replaceby_lab(Gg.V3.to_tuplelab)color;lab)color_listinlettree=Okt.of_list?leaf_sizepointsin{tree;by_lab}(*
Query path:
1. project target color to LAB
2. find nearest LAB point in octree
3. map that point back to the original palette color
*)letnearest_with_indexindextarget=letnearest_lab=Okt.nearestindex.tree(lab3_of_colortarget)inHashtbl.findindex.by_lab(Gg.V3.to_tuplenearest_lab)(* Precompute index once, return a reusable nearest lookup function. *)letnearest_of_list?leaf_sizecolor_list=letindex=nearest_index_of_color_list?leaf_sizecolor_listinfuntarget->nearest_with_indexindextarget