Skip to content

Commit

Permalink
Add OkLrab and OkLrCh
Browse files Browse the repository at this point in the history
Resolves #505
  • Loading branch information
facelessuser committed May 2, 2024
1 parent a77e080 commit 02d9fc8
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 3 deletions.
2 changes: 2 additions & 0 deletions src/spaces/index-fn.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ export {default as REC_2020_Linear} from "./rec2020-linear.js";
export {default as REC_2020} from "./rec2020.js";
export {default as OKLab} from "./oklab.js";
export {default as OKLCH} from "./oklch.js";
export {default as OKLrab} from "./oklrab.js";
export {default as OKLrCH} from "./oklrch.js";
export {default as Okhsl} from "./okhsl.js";
export {default as Okhsv} from "./okhsv.js";
export {default as CAM16_JMh} from "./cam16.js";
Expand Down
36 changes: 36 additions & 0 deletions src/spaces/oklrab.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import ColorSpace from "../space.js";
import OKLab from "./oklab.js";
import {toe, toeInv} from "./okhsl.js";

export default new ColorSpace({
id: "oklrab",
name: "Oklrab",
coords: {
l: {
refRange: [0, 1],
name: "Lightness",
},
a: {
refRange: [-0.4, 0.4],
},
b: {
refRange: [-0.4, 0.4],
},
},

// Note that XYZ is relative to D65
white: "D65",
base: OKLab,
fromBase (oklab) {
return [toe(oklab[0]), oklab[1], oklab[2]];
},
toBase (oklrab) {
return [toeInv(oklrab[0]), oklrab[1], oklrab[2]];
},

formats: {
"color": {
coords: ["<percentage> | <number>", "<number> | <percentage>[-1,1]", "<number> | <percentage>[-1,1]"],
},
},
});
70 changes: 70 additions & 0 deletions src/spaces/oklrch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import ColorSpace from "../space.js";
import OKLrab from "./oklrab.js";
import {toe, toeInv} from "./okhsl.js";
import {constrain as constrainAngle} from "../angles.js";
import {isNone} from "../util.js";

export default new ColorSpace({
id: "oklrch",
name: "Oklrch",
coords: {
l: {
refRange: [0, 1],
name: "Lightness",
},
c: {
refRange: [0, 0.4],
name: "Chroma",
},
h: {
refRange: [0, 360],
type: "angle",
name: "Hue",
},
},
white: "D65",

base: OKLrab,
fromBase (oklab) {
// Convert to polar form
let [L, a, b] = oklab;
let h;
const ε = 0.0002; // chromatic components much smaller than a,b

if (Math.abs(a) < ε && Math.abs(b) < ε) {
h = NaN;
}
else {
h = Math.atan2(b, a) * 180 / Math.PI;
}

return [
L, // OKLab L is still L
Math.sqrt(a ** 2 + b ** 2), // Chroma
constrainAngle(h), // Hue, in degrees [0 to 360)
];
},
// Convert from polar form
toBase (oklch) {
let [L, C, h] = oklch;
let a, b;

// check for NaN hue
if (isNone(h)) {
a = 0;
b = 0;
}
else {
a = C * Math.cos(h * Math.PI / 180);
b = C * Math.sin(h * Math.PI / 180);
}

return [ L, a, b ];
},

formats: {
"color": {
coords: ["<percentage> | <number>", "<number> | <percentage>[0,1]", "<number> | <angle>"],
},
},
});
62 changes: 59 additions & 3 deletions test/conversions.js
Original file line number Diff line number Diff line change
Expand Up @@ -434,22 +434,78 @@ const tests = {
expect: [1.0, 0.0, NaN],
},
{
name: "sRGB red (D65) to OKlab",
name: "sRGB red (D65) to OKlch",
args: "red",
expect: [0.6279553639214311, 0.2576833038053608, 29.23388027962784],
},
{
name: "sRGB lime (D65) to OKlab",
name: "sRGB lime (D65) to OKlch",
args: "lime",
expect: [0.8664396175234368, 0.2948272245426958, 142.4953450414439],
},
{
name: "sRGB blue (D65) to OKlab",
name: "sRGB blue (D65) to OKlch",
args: "blue",
expect: [0.45201371817442365, 0.3132143886344849, 264.0520226163699],
},
],
},
{
name: "OKLrab",
data: {
toSpace: "oklrab",
},
tests: [
{
name: "sRGB white (D65) to OKlrab",
args: "white",
expect: [ 1.0000000000000002, -4.996003610813204e-16, 0 ],
},
{
name: "sRGB red (D65) to OKlrab",
args: "red",
expect: [ 0.5680846563197034, 0.2248630684262744, 0.125846277330585 ],
},
{
name: "sRGB lime (D65) to OKlrab",
args: "lime",
expect: [ 0.8445289714936317, -0.23388758093655815, 0.1794984451609376 ],
},
{
name: "sRGB blue (D65) to OKlrab",
args: "blue",
expect: [ 0.3665653391870817, -0.03245697517079771, -0.3115281656775778 ],
},
],
},
{
name: "OKLrCh",
data: {
toSpace: "oklrch",
},
tests: [
{
name: "sRGB white (D65) to OKlrch",
args: "white",
expect: [1.0, 0.0, NaN],
},
{
name: "sRGB red (D65) to OKlrch",
args: "red",
expect: [0.5680846563197034, 0.2576833038053608, 29.23388027962784],
},
{
name: "sRGB lime (D65) to OKlrch",
args: "lime",
expect: [0.8445289714936317, 0.2948272245426958, 142.4953450414439],
},
{
name: "sRGB blue (D65) to OKlrch",
args: "blue",
expect: [0.3665653391870817, 0.3132143886344849, 264.0520226163699],
},
],
},
{
name: "Linear-light sRGB",
data: {
Expand Down
2 changes: 2 additions & 0 deletions types/src/space-coord-accessors.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ declare class SpaceAccessors {
okhsv: SpaceAccessor;
oklab: SpaceAccessor;
oklch: SpaceAccessor;
oklrab: SpaceAccessor;
oklrch: SpaceAccessor;
p3: SpaceAccessor;
p3_linear: SpaceAccessor;
prophoto: SpaceAccessor;
Expand Down
3 changes: 3 additions & 0 deletions types/src/spaces/oklrab.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import ColorSpace from "../space.js";
declare const _default: ColorSpace;
export default _default;
3 changes: 3 additions & 0 deletions types/src/spaces/oklrch.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import ColorSpace from "../space.js";
declare const _default: ColorSpace;
export default _default;

0 comments on commit 02d9fc8

Please sign in to comment.