Oklab color space in JavaScript
Oklab is a color space suitable for color manipulation and image processing. Based on public domain C++ code published by Björn Ottosson.
The main attraction is a pair of functions to convert between linear SRGB and Oklab:
import {linearSrgbToOklab, oklabToLinearSrgb} from 'oklab';
const greenSrgb = {r: 0, g: 1, b: 0};
// Convert from linear SRGB to Oklab and back
// (Expect a small precision error on a roundtrip like this)
const greenOklab = linearSrgbToOklab(greenSrgb);
// {L: 0.866439…, a: -0.233920…, b: 0.179423…}
oklabToLinearSrgb(greenOklab);
// {r: 0.000000…, g: 1.000000…, b: 0.000000…}
Linear SRGB color is represented as an object {r, g, b}
, with channels between 0
and 1
.
Oklab is represented as an object {L, a, b}
where L
is between 0
and 1
for normal SRGB colors. a
and b
have a less clearly defined range, but will normally be between -0.5
and +0.5
. Neutral gray colors will have a
and b
at zero (or very close).
To convert SRGB to grayscale with Oklab, you only need L
(lightness). linearSrgbToOklabLightness()
returns the value of L
directly:
import {linearSrgbToOklabLightness} from 'oklab';
linearSrgbToOklabLightness({r: 0, g: 1, b: 0});
// 0.866439…
For convenience, there's also mixOklab()
which takes two Oklab {L, a, b}
objects and blends them by a factor 0
-1
(defaults to 0.5
).
import {linearSrgbToOklab, oklabToLinearSrgb, mixOklab} from 'oklab';
const white = linearSrgbToOklab({r: 1, g: 1, b: 1});
const blue = linearSrgbToOklab({r: 0, g: 0, b: 1});
const mix25 = mixOklab(white, blue, 0.25);
// {L: 0.862998…, a: -0.008088…, b: -0.077993…}
const mix50 = mixOklab(white, blue);
// {L: 0.726009…, a: -0.016185…, b: -0.155868…}
const mix75 = mixOklab(white, blue, 0.75);
// {L: 0.589019…, a: -0.024281…, b: -0.233744…}
oklabToLinearSrgb(mix50);
// {r: 0.173162…, g: 0.364795…, b: 1.083732…}
As you can see in the blue channel in the last example, mixing two colors in gamut can create colors that are out of gamut.