dbuenzli / gg

Basic types for computer graphics in OCaml
http://erratique.ch/software/gg/
Other
42 stars 9 forks source link

Out of gammut colors on Color.{to,of}_lch_uv round trips #8

Open Guyslain opened 7 years ago

Guyslain commented 7 years ago
utop # Color.red |> Color.to_lch_uv |> Color.of_lch_uv;;
- : v4 = (1 -9.96856e-09 -1.70861e-08 1) 

Colors with negative components are not rendered as far as I tested.

It seems to be quite easy to get invalid colors, here is another example with a larger negative component.

utop # V4.v 80. 120. 2. 1. |> Color.of_lch_uv;;
- : v4 = (0.198288 0.741156 -0.0747728 1)

I even got some components bigger than 1. on some examples.

dbuenzli commented 7 years ago

This is not really surprising as the gamut of linear sRGB (i.e. the space of Gg.color values) is much smaller than that of L*C*h.

This was written a long time ago but I think the reasoning behind this behaviour was that the client is in a better position to know what it wants to do with out of gamut colors. In your case it seems you simply want to use Color.clamp on the result.

I should however update the docs to make it clear that this can happen.

(/cc @edwintorok who authored the color conversion functions)

edwintorok commented 7 years ago

Handling of out of gamut colors should be documented I agree, but the initial example is not out of gamut: there is just loss of precision due to floating point multiplication/division and in a roundtrip you don't get back exactly the value you started out with. It would be nice if users shouldn't be concerned with out-of-gamut colors during a roundtrip, perhaps the conversion functions should also include rounding, at least when converting to sRGB. What do you think?

dbuenzli commented 7 years ago

It would be nice if users shouldn't be concerned with out-of-gamut colors during a roundtrip,

Sure but hacks for nicing floating point inaccuracies tend to lead to slippery slopes. It's seems however that the code is already doing a bit of epsilon testing. So yeah maybe we could try to see if there's an uniform way of making sure results round trip on sRGB boundaries.

edwintorok commented 7 years ago

FWIW the code in test.ml uses an epsilon of 2. ** -23. for round-trips, I'll have to check if its possible to increase the precision of the matrixes and constants I used in gg.ml to match gg_eps = 1e-9, although maybe just doing some additional additional gg_eps testing around 0. and 1. would be enough.

Guyslain commented 7 years ago

Thanks for the answers, clamp is sufficient for my needs.

Still, I made an experiment, displaying all colors at lightness 70, with and without clamp. Can you confirm the result is as expected?

colors_hcl.zip

dbuenzli commented 7 years ago

I added a warning to the docs. It would still be nice to see if we can do something about round trips.