You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I store original source rgb colors in an array variable, which are taken from the Rgb color space. I then have a user interface that allows a user to manipulate these source colors in the Oklch color space, which then renders the user-manipulated colors back in the Rgb color space.
The problem is that the target never ends up equaling its source even when there is no manipulation of hue, chroma, or luminosity as shown here:
With using clampRgb:
`
culori.clampRgb(culori.rgb(culori.oklch({
"mode": "rgb",
"r": 1,
"g": 1,
"b": 1
})))
{mode: 'rgb', r: 0.9999999608276361, g: 1, b: 1} // Result: expected value of r = 1, but got a value < 1
`
Without using clampRgb:
`
culori.rgb(culori.oklch({
"mode": "rgb",
"r": 1,
"g": 1,
"b": 1
}))
{mode: 'rgb', r: 0.9999999608276361, g: 1.00000000005861, b: 1.0000001062495965} // Result: expected value of g < 1 and b < 1, but got g and b values > 1
`
Why does this matter? Because when a user increases the chroma of pure white, I would expect pure white to stay pure white since it is achromatic. But because of this issue, white can becomes a color (often magenta) when chroma is added.
The text was updated successfully, but these errors were encountered:
The results you’re seeing are caused by the fact that a roundtrip from sRGB to Oklch and back introduces subtle precision errors. They are, to some extent, unavoidable and unfortunately need to be actively managed depending on the usage.
I believe we are currently using the matrices from the original Oklab article, while the CSS Color Level 4 spec has updated them (see this discussion). It offers better roundtripping but does not completely eliminate these sort of small errors.
You may want to experiment with rounding these small values to a number of decimals that make practical sense for your use case. Culori has the culori.round() helper for that:
(As a sidenote, you may also want to look at culori.mapper as a way to apply round() to all components in a color)
In the specific case of Oklch colors, you may want to consider colors with a very small chroma to be achromatic:
import{rgb,oklch}from'culori';constcolor=oklch(rgb(oklch('white')));// => { mode: "oklch", l: 0.9999999934735458, c: 1.5700924586837752e-16, h: 135 }// make color with infinitely small chroma achromatic.if(color.c<1e-8){color.c=0;deletecolor.h;}
I store original source rgb colors in an array variable, which are taken from the Rgb color space. I then have a user interface that allows a user to manipulate these source colors in the Oklch color space, which then renders the user-manipulated colors back in the Rgb color space.
The problem is that the target never ends up equaling its source even when there is no manipulation of hue, chroma, or luminosity as shown here:
With using
clampRgb
:`
culori.clampRgb(culori.rgb(culori.oklch({
"mode": "rgb",
"r": 1,
"g": 1,
"b": 1
})))
Without using
clampRgb
:`
culori.rgb(culori.oklch({
"mode": "rgb",
"r": 1,
"g": 1,
"b": 1
}))
Why does this matter? Because when a user increases the chroma of pure white, I would expect pure white to stay pure white since it is achromatic. But because of this issue, white can becomes a color (often magenta) when chroma is added.
The text was updated successfully, but these errors were encountered: