facelessuser / coloraide

A library to aid in using colors
https://facelessuser.github.io/coloraide
MIT License
195 stars 12 forks source link

HCT speed up translation back to CAM16 #292

Closed facelessuser closed 1 year ago

facelessuser commented 1 year ago

While not the most pressing issue, we should work on a shortcut to help HCT get back to CAM16 faster.

Currently, the whole thing uses bisecting to figure out the best J to use that satisfies the current L*Ch which is actually what HCT is. You can't get back to CAM16 without the right J, and J isn't used in the calculation for L* since it's from a completely different color space. Bisecting alone isn't nearly efficient enough.

The whole color space is weird in that since. It tries to take the best of CAM16 and Lab and magnifies the worst parts of CAM16, the slow conversion.

facelessuser commented 1 year ago

Doing some experimentation, I was able to speed up HCT conversion back to CAM16, in some cases greater than 50%.

Instead of bisecting, we take a different approach. We take the current T (of HCT) and calculate our target Y (of XYZ D65). Then we can take some J (while using our current C and h) and calculate our current Y. If the delta between our current and target is too great, we convert that XYZ to Lab and then set L* to our original T. Convert that back to CAM16 and get our new J.

At first glance, this feels like more work, but we actually converge on average much faster. We do less iterations which means less expensive CAM16 calculations. We sometimes converge in as few as 4 iterations. There are some cases where overall time may be closer to bisecting, but those are surprisingly rare.

There may be even faster approaches, but I think this is a good start for now. When you can have some conversions go from 265us to 95us, that's a pretty good return.

Currently, we cap at about 15 iterations just to be safe and prevent an infinite loop. Our least performant area is right around blue, so more iterations are needed right in this area.