Skip to content
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

oklab / oklch? #87

Open
Fil opened this issue Dec 30, 2020 · 9 comments
Open

oklab / oklch? #87

Fil opened this issue Dec 30, 2020 · 9 comments
Labels
enhancement New feature or request

Comments

@Fil
Copy link
Member

Fil commented Dec 30, 2020

https://bottosson.github.io/posts/oklab/

Here's a list of the design choices behind oklab:

  • Should be an opponent color space, similar to for example CIELAB.
  • Should predict lightness, chroma and hue well. LL, CC and hh should be perceived as orthogonal, so one can be altered without affecting the other two. This is useful for things like turning an image black and white and increasing colorfulness without introducing hue shifts etc.
  • Blending two colors should result in even transitions. The transition colors should appear to be in between the blended colors (e.g. passing through a warmer color than either original color is not good).
  • Should assume a D65 whitepoint. This is what common color spaces like sRGB, rec2020 and Display P3 uses.
  • Should behave well numerically. The model should be easy to compute, numerically stable and differentiable.
  • Should assume normal well lit viewing conditions. The complexity of supporting different viewing conditions is not practical in most applications. Other models could be used in conjunction if this is needed in some case.
  • If the scale/exposure of colors are changed, the perceptual coordinates should just be scaled by a factor. More complex models that depend on absolute luminance should be avoided since the viewing conditions can not be accurately controlled and incorrect behavior would be confusing.
@Fil
Copy link
Member Author

Fil commented Dec 31, 2020

I've tried to implement it in this notebook — not 100% sure I got it correctly.

@danburzo
Copy link
Contributor

danburzo commented Jan 1, 2021

The implementation looks good to me. Maybe a and b can be halved in the notebook so the a/b plot doesn't look as clipped? I found these approximate ranges for colors in the sRGB gamut: l ∈ [0, 1], a ∈ [-0.233, 0.276], b ∈ [-0.311, 0.198]. (sRGB white actually has an annoying L = 0.99998 :P)

@Fil
Copy link
Member Author

Fil commented Jan 2, 2021

I'm sorry I'm not sure I understand. Halving a and b would result in diverging from the original proposal, thus making our implementation incompatible? I agree that it would be nice to fix the computation to L=1 but that too should be done upstream?

@danburzo
Copy link
Contributor

danburzo commented Jan 2, 2021

Oops, sorry — I was a bit cryptic. I meant halving the interval for a and b on the a/b plot in the notebook, not a change in the implementation. The plot has a and b running in the interval [-0.5, 0.5], which makes the plot show more colors that are outside of the sRGB gamut:

Screenshot 2021-01-02 at 19 59 24

With a and b in [-0.25, 0.25] the plot looks smoother, as fewer colors end up being clamped:

Screenshot 2021-01-02 at 20 01 06

I agree that it would be nice to fix the computation to L=1 but that too should be done upstream?

In some discussion related to the original post, Jacob Rus mentions maybe rounding off the matrices to fewer digits... in my experiments, fewer digits in Oklab's M1 multiplied with the sRGB to XYZ matrix lands it much closer to 1, but it seems more and more implementations are cropping up and choosing to use the original values.

@Fil
Copy link
Member Author

Fil commented Jan 2, 2021

Thanks for the clarification and the references. I've updated the notebook accordingly.

@mbostock mbostock added the enhancement New feature or request label Mar 28, 2022
@shadow-identity
Copy link

OKLCH could be even more interesting as it simplifies color manipulation and makes it more consistent for a human eye.

@Fil
Copy link
Member Author

Fil commented Apr 3, 2023

@electro-logic
Copy link

electro-logic commented Nov 10, 2023

oklab.plane.mp4

@danburzo @Fil
About the White point that differs from L=1.0

I think that the issue here is the simplified matrix that Björn gave in his blog.
If you look at the math expression, to go from Oklab to LMS we need to invert M2, so we have:

inv(M2)=[
0.99999999845, 0.39633779217, 0.21580375806,
1.00000000888, -0.10556134232, -0.06385417477,
1.00000005467, -0.08948418209, -1.29148553786]

But in the code you have the simplified formula:

const l_ = L + 0.3963377774 * a + 0.2158037573 * b;
const m_ = L - 0.1055613458 * a - 0.0638541728 * b;
const s_ = L - 0.0894841775 * a - 1.2914855480 * b;

that uses rounded values. For better accuracy I suggest you to use unrounded values directly from the inverted matrix.

Cheers,
Leonardo

PS: Attached my implementation of the srgb ab plane when L is changing. When L=0 or L=1 I get a single point (RGB 0,0,0 and RGB 255,255,255).

@curran
Copy link
Contributor

curran commented Aug 26, 2024

It would be awesome to have this color space available in D3!

I'm interested in prototyping a color picker based on this space, in the same spirit as these old color picker examples

image

https://blocks.roadtolarissa.com/mbostock/ba8d75e45794c27168b5

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Development

No branches or pull requests

6 participants