Skip to content

Commit

Permalink
Handle missing components in gamut mapping functions
Browse files Browse the repository at this point in the history
  • Loading branch information
danburzo committed Jan 18, 2024
1 parent 01ae144 commit da5d072
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 11 deletions.
24 changes: 13 additions & 11 deletions src/clamp.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ const rgb = converter('rgb');
const fixup_rgb = c => {
const res = {
mode: c.mode,
r: Math.max(0, Math.min(c.r, 1)),
g: Math.max(0, Math.min(c.g, 1)),
b: Math.max(0, Math.min(c.b, 1))
r: Math.max(0, Math.min(c.r !== undefined ? c.r : 0, 1)),
g: Math.max(0, Math.min(c.g !== undefined ? c.g : 0, 1)),
b: Math.max(0, Math.min(c.b !== undefined ? c.b : 0, 1))
};
if (c.alpha !== undefined) {
res.alpha = c.alpha;
Expand All @@ -22,12 +22,9 @@ const to_displayable_srgb = c => fixup_rgb(rgb(c));
const inrange_rgb = c => {
return (
c !== undefined &&
c.r >= 0 &&
c.r <= 1 &&
c.g >= 0 &&
c.g <= 1 &&
c.b >= 0 &&
c.b <= 1
(c.r === undefined || (c.r >= 0 && c.r <= 1)) &&
(c.g === undefined || (c.g >= 0 && c.g <= 1)) &&
(c.b === undefined || (c.b >= 0 && c.b <= 1))
);
};

Expand Down Expand Up @@ -146,10 +143,10 @@ export function clampChroma(color, mode = 'lch', rgbGamut = 'rgb') {
// By this time we know chroma = 0 is displayable and our current chroma is not.
// Find the displayable chroma through the bisection method.
let start = 0;
let end = color.c;
let end = color.c !== undefined ? color.c : 0;
let range = getMode(mode).ranges.c;
let resolution = (range[1] - range[0]) / Math.pow(2, 13);
let _last_good_c;
let _last_good_c = clamped.c;

while (end - start > resolution) {
clamped.c = start + (end - start) * 0.5;
Expand Down Expand Up @@ -215,6 +212,11 @@ export function toGamut(
return undefined;
}
const candidate = { ...ucs(color) };

// account for missing components
if (candidate.l === undefined) candidate.l = 0;
if (candidate.c === undefined) candidate.c = 0;

if (candidate.l >= ranges.l[1]) {
const res = { ...destMode.white, mode: dest };
if (color.alpha !== undefined) {
Expand Down
90 changes: 90 additions & 0 deletions test/clamp.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
clampChroma,
displayable,
inGamut,
clampRgb,
clampGamut,
formatCss,
toGamut,
Expand Down Expand Up @@ -48,6 +49,21 @@ tape('clampChroma (lch)', function (test) {
h: 5
});
test.equal(displayable(clampChroma('lch(50% 120 5)')), true);
test.deepEqual(
clampChroma({
mode: 'lch',
l: 0,
c: 100,
h: 30
}),
{
mode: 'lch',
l: 0,
c: 0,
h: 30
},
'for l = 0, only c = 0 is in gamut'
);
test.end();
});

Expand Down Expand Up @@ -176,3 +192,77 @@ tape('toGamut()', t => {

t.end();
});

tape('missing components', t => {
t.ok(displayable('rgb(none none none)'), 'displayable');

t.ok(inGamut('p3')('color(display-p3 none none none)'), 'inGamut');

t.deepEqual(
clampRgb('rgb(none 300 none)'),
{
mode: 'rgb',
r: 0,
g: 1,
b: 0
},
'clampRgb'
);

t.deepEqual(
clampGamut('p3')('color(display-p3 none 3 none)'),
{
mode: 'p3',
r: 0,
g: 1,
b: 0
},
'clampGamut'
);

t.deepEqual(
clampChroma({
mode: 'lch',
l: 120
}),
{
mode: 'lch',
l: 100.00000139649632,
c: 0
},
'clampChroma, lch color (no conversion)'
);

t.deepEqual(
clampChroma('color(srgb 1.1 none none)'),
{
mode: 'rgb',
r: 0.9999762593315072,
g: 0.3000275449561938,
b: 0.17168509121325368
},
'clampChroma, rgb color'
);

t.deepEqual(
toGamut()({
mode: 'lch',
l: 120
}),
{ r: 1, g: 1, b: 1, mode: 'rgb' },
'toGamut(), oklch color (no conversion)'
);

t.deepEqual(
toGamut()('color(srgb 1.1 none none)'),
{
mode: 'rgb',
r: 0.9999999999999994,
g: 0.24780803212382269,
b: 0.18935507566673854
},
'toGamut(), rgb color'
);

t.end();
});

0 comments on commit da5d072

Please sign in to comment.