This is not a bug, but more a limitation of the ray trace algorithm. As such, there is no requirement this be addressed, but if a performant way were discovered that could alleviate this issue, it would be nice to have.
Luv, when using adaptive lightness above 0.05 can cause non-ideal results in the dark blue region. This is a corner case that is exposed due to having chroma reduction paths that have more extreme bends, often buried within the RGB surface.
The ray trace algorithm works well with constant lightness due to the gentle curves that constant lightness creates. In most color spaces, even with adaptive lightness, we still get fairly gentle curves, and when we do get heavier bends in the chroma reduction path, the bend often presents outside the RGB surface. This is true 99% of the time.
Luv is unique in that when using higher adaptive lightness values you can get a more severe bend, and it can often occur below the RGB surface. This causes the algorithm to have issues correcting colors back onto the chroma reduction path using projection. It can cause a correction with a lightness out of range. When the lightness falls below range, it can actually stress the color space as some do not convert low lightness and high chroma very well. Luv is one of these spaces and can cause the hue to rotate 180˚ at times when converting back to an RGB space.
We can see here when we use an adaptive value of 5 on color(rec2020 0 0 0.5) that the main bend is beneath the RGB service and is a bit more sharp. We've disabled dynamically adjusting the anchor closer to the RGB surface as it makes the example a little more confusing.
When we break it down, we can see better what goes wrong. We get corrected values outside the lightness range with very high chroma. What is particularly troublesome is the low lightness with high chroma as it falls upon the chroma reduction path past the achromatic point. Luv does not handle this well and takes the low light, high chroma color(--lchuv 9.24 69.251 263.58 / 1) and converts it to RGB and flips the RGB hue so that blue is now negative color(srgb-linear 0.05651 0.03396 -0.36014 / 1). The next round LChuv yielding hues of 83 instead of 263 which flips us into a more yellow color. Everything is off the rails at that point.
Logically, there is nothing wrong with what we are doing, but it presents a non-ideal situation. To solve this, we can identify when we are projecting the color onto the chroma reduction path that it will be an extreme case and clamp the correction such that when we project the color onto the chroma reduction path vector we avoid this extreme case. This prevents the reduction from going off into the weeds and ends up an under-corrected value, but a more sane value that is at least in the ballpark. That is what we currently do.
This is indeed a corner case, one that so far only crops up with Luv/LChuv and only with hue-independent adaptive lightness at high values. But I imagine some spaces in the future could do something similar. I think this is more exposing a limitation in ray tracing, one that in most cases will never be hit, but can still surface.
This issue is simply to track the possibility of finding a performant way to mitigate this issue even better if possible, if there is no way, it's fine to simply note this as an edge case that exposes the limitation of the algorithm. This by no means diminishes the usefulness of the ray trace approach, but it just pushes it a little further than it can handle.
This is not a bug, but more a limitation of the ray trace algorithm. As such, there is no requirement this be addressed, but if a performant way were discovered that could alleviate this issue, it would be nice to have.
Luv, when using adaptive lightness above 0.05 can cause non-ideal results in the dark blue region. This is a corner case that is exposed due to having chroma reduction paths that have more extreme bends, often buried within the RGB surface.
The ray trace algorithm works well with constant lightness due to the gentle curves that constant lightness creates. In most color spaces, even with adaptive lightness, we still get fairly gentle curves, and when we do get heavier bends in the chroma reduction path, the bend often presents outside the RGB surface. This is true 99% of the time.
Luv is unique in that when using higher adaptive lightness values you can get a more severe bend, and it can often occur below the RGB surface. This causes the algorithm to have issues correcting colors back onto the chroma reduction path using projection. It can cause a correction with a lightness out of range. When the lightness falls below range, it can actually stress the color space as some do not convert low lightness and high chroma very well. Luv is one of these spaces and can cause the hue to rotate 180˚ at times when converting back to an RGB space.
We can see here when we use an adaptive value of 5 on
color(rec2020 0 0 0.5)
that the main bend is beneath the RGB service and is a bit more sharp. We've disabled dynamically adjusting the anchor closer to the RGB surface as it makes the example a little more confusing.When we break it down, we can see better what goes wrong. We get corrected values outside the lightness range with very high chroma. What is particularly troublesome is the low lightness with high chroma as it falls upon the chroma reduction path past the achromatic point. Luv does not handle this well and takes the low light, high chroma
color(--lchuv 9.24 69.251 263.58 / 1)
and converts it to RGB and flips the RGB hue so that blue is now negativecolor(srgb-linear 0.05651 0.03396 -0.36014 / 1)
. The next round LChuv yielding hues of 83 instead of 263 which flips us into a more yellow color. Everything is off the rails at that point.Logically, there is nothing wrong with what we are doing, but it presents a non-ideal situation. To solve this, we can identify when we are projecting the color onto the chroma reduction path that it will be an extreme case and clamp the correction such that when we project the color onto the chroma reduction path vector we avoid this extreme case. This prevents the reduction from going off into the weeds and ends up an under-corrected value, but a more sane value that is at least in the ballpark. That is what we currently do.
This is indeed a corner case, one that so far only crops up with Luv/LChuv and only with hue-independent adaptive lightness at high values. But I imagine some spaces in the future could do something similar. I think this is more exposing a limitation in ray tracing, one that in most cases will never be hit, but can still surface.
This issue is simply to track the possibility of finding a performant way to mitigate this issue even better if possible, if there is no way, it's fine to simply note this as an edge case that exposes the limitation of the algorithm. This by no means diminishes the usefulness of the ray trace approach, but it just pushes it a little further than it can handle.