Colour should match colour-science
The python colour-science package is a defacto standard for open-source accurate color computation and a good reference for rigorous definitions, mostly, including possible tuning knobs that aren't strictly defined and listings of standardized parameter sets (primaries, whitepoints, transfer functions, stimulus curves, etc.)
We should do our best to match our own computation to values from this crate, investigating any deviation as a bug.
Correct:
- [x] Converting sRGB to Oklab is fine albeit newer versions round differently.
Known issues:
- [x] ~~Converting between sRGB and ITU.BT2020 is inaccurate.~~
This was a problem at user level, conversion requires us setting// theirs: [255, 255, 0], array([ 243.96840205, 252.09511243, 26.61725637]) // ours: ([255, 255, 0], [249, 254, 76])apply_cctf_decodingas we pass everything in encoded form but their default is assuming linear primary space. - [x] ~~
sRGBto Luma does not correspond toxyY.Yvalue as evaluated.~~ Same as above
Test coverage, Transfers:
- [x] BT709 (#74)
- [ ] Bt470-M
- [x] Bt470 (pure gamma 2.8) (#74)
- [x] Implement this first (#74)
- [x] Bt601 (aka BT709) (#74)
- [x] Smpte240 (#74)
- [ ] Linear
- [x] Srgb (#74)
- [ ] Bt2020_10bit quantized (not in colour-science)
- [ ] Bt2020_12bit quantized (not in colour-science)
- [x] Bt2020 unquantized (#76)
- [x] Smpte2084 (#76)
- [ ] https://github.com/image-rs/canvas/pull/76#discussion_r2160426000
- [ ] Bt2100Pq
- [ ] Bt2100Hlg
- [ ] Bt2100Scene
So far so good. The biggest issue found after fixing coefficient bugs in transfer functions is that the conversion to XYZ and back is using multiplication in 32-bit floats and since this is a matrix multiplication it is a dot product. This has the potential of ugly inaccuracies from different cancellation between bit widths. We should switch to a more exact matrix-vector form, given we know the matrix sizes that can be done very precisely without too much overhead (particular on x86 AVX with DPPS though I'd recheck rounding modes).