-
-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Gamut Mapping Lch vs Oklch #118
Comments
I'm not saying Oklch can't be used to do gamut mapping, but I think the current algorithm isn't quite working so well. |
I've rolled back to using Lch for now. Oklab is still the default interpolation space as it works much better, but Lch seems to give more expected results when it comes to gamut mapping in gradients and such. The cost of running ∆E2000 is of course a bit more expensive, but we are visually getting colors that make more sense. I'll leave this issue open to see how conversations go in regards to the CSS specification.
Generally, I've tried to sort of match the CSS specification where it makes sense, but I'd rather give good results for gamut mapping rather than blindly adopt the CSS approach, especially since we are in the very early stages. Things could certainly change in the future as is often the case with the CSS spec. |
I've been looking into this, and it appears that some colors that are outside the spectral locus do not quite map back in Oklch as one would normally expect. This is most likely because the calculations are optimal for colors within the spectral locus. As you push outside that range, I imagine, in some hues, the calculations go off the rails. This doesn't make the model bad, just not ideal for these extreme cases. I think LCH just deals better with these cases. I'm looking at taking some of the earlier CSS simplifications to the gamut mapping algorithm and applying them to our LCH implementation. This would remove our ∆E2000 usage and greatly increase gamut mapping speed. Originally, I thought the algorithm was just not that good because Oklch gamut mapping was already not great in some cases, but overall, it doesn't seem that bad or that different than what we are already doing. The one exception is their shortcut out of the binary search that uses color distancing. It doesn't create "bad" colors, just more choppy results in interpolations. We'll probably leave the shortcut out. |
I think I understand better why the distancing is incorporated in the algorithm. It helps yellow and cyan not to have super low chroma. But it does make some interpolations a little choppier, but you get better yellow and cyan in CIE LCH at a quicker speed. Our current algorithm does a good job keeping the chroma pretty high for yellow and cyan, giving smooth transitions but is more expensive as we rely heavier on the distancing. |
I still think our current MINDE gives better results. I think we'll eat the cost of speed for now. |
Spent a little more time on this as I'd really like us to get some of the speed boosts. The CSS algorithm overcorrects the chroma too much in some cases by being too aggressive in the chroma reduction. The current algorithm we use is a bit too heavy on the delta E checks causing major slow downs. I think I've found a way to blend the two algorithms to give us a very noticeable speed boost, but prevent us from overcorrecting the chroma quite as much. Basically, aside from relying on LCH instead of Oklch, we follow the CSS algorithm in the beginning:
The key is that the CSS algorithm sometimes returns very low under the JND. When this happens, chroma reduction can be quite aggressive. On the other hand, our current algorithm waited until the high and low chroma boundaries converged, and since we performed delta E checks on every iteration, it was a bit more expensive. Now we avoid doing delta E checks when in gamut increasing speed. Once both our low and high boundary are out of gamut, we tune the chroma in order to get as close to the JND as possible keep hue close enough without forcing chroma too low. We pick up additional speed by kicking out when delta E is close to JND instead of waiting for chroma boundaries to converge. In testing, we can see we are not as fast as the CSS algorithm, but are faster than our old algorithm by a noticeable amount. We also have results close to the old method giving us a less aggressive chroma reduction, giving us better results in general. Here we see the conversion of a display P3 yellow to LCH: >>> Color('color(display-p3 1 1 0)').convert('lch')
color(--lch 97.366 123.27 98.13 / 1) Below are the timings of various implementations
The New way is about twice as fast as the old way, but obviously the CSS algorithm is twice as fast as the new way, but results aren't quite as good due to over correction of the chroma. Here we see the results of fitting it with the old algorithm: >>> Color('color(display-p3 1 1 0)').convert('lch').fit('srgb')
color(--lch 97.248 94.365 99.221 / 1) Here we see the CSS results: >>> Color('color(display-p3 1 1 0)').convert('lch').fit('srgb')
color(--lch 97.004 61.39 99.806 / 1) Here we see the new method: >>> Color('color(display-p3 1 1 0)').convert('lch').fit('srgb')
color(--lch 97.247 94.364 99.22 / 1) We can see the new method is much faster than the old one but more on par with chroma reduction not being quite as aggressive. |
Removed milestone. We have a current, CSS-compatible GMA. Will it be the final one? 🤷🏻 Either way, we have something that works well, and people can use the CSS if they like. We can always add new ones and deprecate old ones. This shouldn't block our 1.0 release. |
I think Oklch is an excellent interpolation space. It doesn't have the weird purple shifts that Lch does, and it just seems to do a better job.
What I am questioning is whether Oklch is a better gamut mapping algorithm. I'm considering backing out the use of Oklch for gamut mapping. I'd argue that generally, Lch gives me visually what I would expect as far as gamut mapping is concerned, but Oklch/Oklab gives me better interpolation results compared to Lch/Lab.
w3c/csswg-drafts#7071
The text was updated successfully, but these errors were encountered: