Skip to content

Commit cf5f15e

Browse files
authored
Ensure Okhsl and Okhsv return undefined hues for achromatic colors (#517)
* Ensure Okhsl and Okhsv return undefined hues for achromatic colors Fixes #516 * Provide variables for epsilon values * Update to use null and rework Okhsl saturation handling
1 parent fcb5436 commit cf5f15e

File tree

4 files changed

+43
-15
lines changed

4 files changed

+43
-15
lines changed

package-lock.json

+4-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/spaces/okhsl.js

+22-3
Original file line numberDiff line numberDiff line change
@@ -376,8 +376,8 @@ function okhslToOklab (hsl, lmsToRgb, okCoeff) {
376376

377377
let [h, s, l] = hsl;
378378
let L = toeInv(l);
379-
let a = 0.0;
380-
let b = 0.0;
379+
let a = null;
380+
let b = null;
381381
h = constrain(h) / 360.0;
382382

383383
if (L !== 0.0 && L !== 1.0 && s !== 0) {
@@ -423,6 +423,10 @@ function okhslToOklab (hsl, lmsToRgb, okCoeff) {
423423
function oklabToOkhsl (lab, lmsToRgb, okCoeff) {
424424
// Oklab to Okhsl.
425425

426+
// Epsilon for lightness should approach close to 32 bit lightness
427+
// Epsilon for saturation just needs to be sufficiently close when denoting achromatic
428+
let εL = 1e-7;
429+
let εS = 1e-4;
426430
let L = lab[0];
427431
let s = 0.0;
428432
let l = toe(L);
@@ -458,7 +462,22 @@ function oklabToOkhsl (lab, lmsToRgb, okCoeff) {
458462
}
459463
}
460464

461-
return [constrain(h * 360), s, l];
465+
const achromatic = Math.abs(s) < εS;
466+
if (achromatic || l === 0.0 || Math.abs(1 - l) < εL) {
467+
h = null;
468+
// Due to floating point imprecision near lightness of 1, we can end up
469+
// with really high around white, this is to provide consistency as
470+
// saturation can be really high for white due this imprecision.
471+
if (!achromatic) {
472+
s = 0.0;
473+
}
474+
}
475+
476+
else {
477+
h = constrain(h * 360);
478+
}
479+
480+
return [h, s, l];
462481
}
463482

464483

src/spaces/okhsv.js

+13-3
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ function okhsvToOklab (hsv, lmsToRgb, okCoeff) {
4747
h = constrain(h) / 360.0;
4848

4949
let l = toeInv(v);
50-
let a = 0.0;
51-
let b = 0.0;
50+
let a = null;
51+
let b = null;
5252

5353
// Avoid processing gray or colors with undefined hues
5454
if (l !== 0.0 && s !== 0.0) {
@@ -95,6 +95,8 @@ function okhsvToOklab (hsv, lmsToRgb, okCoeff) {
9595
function oklabToOkhsv (lab, lmsToRgb, okCoeff) {
9696
// Oklab to Okhsv.
9797

98+
// Epsilon for saturation just needs to be sufficiently close when denoting achromatic
99+
let ε = 1e-4;
98100
let l = lab[0];
99101
let s = 0.0;
100102
let v = toe(l);
@@ -134,7 +136,15 @@ function oklabToOkhsv (lab, lmsToRgb, okCoeff) {
134136
s = (s0 + tMax) * cv / ((tMax * s0) + tMax * k * cv);
135137
}
136138

137-
return [constrain(h * 360), s, v];
139+
if (Math.abs(s) < ε || v === 0.0) {
140+
h = null;
141+
}
142+
143+
else {
144+
h = constrain(h * 360);
145+
}
146+
147+
return [h, s, v];
138148
}
139149

140150

test/conversions.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -965,7 +965,7 @@ const tests = {
965965
{
966966
name: "sRGB white to Okhsl",
967967
args: "white",
968-
expect: [180, 0.6519721306444567, 1.0000000000000002],
968+
expect: [ null, 0.0, 1.0000000000000002 ],
969969
},
970970
{
971971
name: "sRGB red to Okhsl",
@@ -1000,7 +1000,7 @@ const tests = {
10001000
{
10011001
name: "sRGB black to Okhsl",
10021002
args: "black",
1003-
expect: [0.0, 0.0, 0.0],
1003+
expect: [ null, 0.0, 0.0 ],
10041004
},
10051005
],
10061006
},
@@ -1013,7 +1013,7 @@ const tests = {
10131013
{
10141014
name: "sRGB white to Okhsv",
10151015
args: "white",
1016-
expect: [ 180, 1.3189507366749435e-15, 1.0000000000000007 ],
1016+
expect: [ null, 1.3189507366749435e-15, 1.0000000000000007 ],
10171017
},
10181018
{
10191019
name: "sRGB red to Okhsv",
@@ -1048,7 +1048,7 @@ const tests = {
10481048
{
10491049
name: "sRGB black to Okhsv",
10501050
args: "black",
1051-
expect: [0.0, 0.0, 0.0],
1051+
expect: [ null, 0.0, 0.0],
10521052
},
10531053
],
10541054
},

0 commit comments

Comments
 (0)