Skip to content

Instantly share code, notes, and snippets.

@demurgos
Created February 7, 2020 14:42
Show Gist options
  • Save demurgos/e0d8d6c4b49a2dd242c3c296f50c359e to your computer and use it in GitHub Desktop.
Save demurgos/e0d8d6c4b49a2dd242c3c296f50c359e to your computer and use it in GitHub Desktop.
interface LinearRgb {
r: number;
g: number;
b: number;
}
interface Srgb {
r: number;
g: number;
b: number;
}
interface StraightSrgba {
r: number;
g: number;
b: number;
a: number;
}
interface Lab {
l: number;
a: number;
b: number;
}
interface Xyz {
x: number;
y: number;
z: number;
}
function srgbToLab(srgb: Srgb): Lab {
const lrgb: LinearRgb = srgbToLinearRgb(srgb);
return lrgbToLab(lrgb);
}
function labToSrgb(lab: Lab): Srgb {
const lrgb: LinearRgb = labToLrgb(lab);
return linearRgbToSrgb(lrgb);
}
function lrgbToLab(lrgb: LinearRgb): Lab {
const xyz: Xyz = linearRgbToXyz(lrgb);
return xyzToLab(xyz);
}
function labToLrgb(lab: Lab): LinearRgb {
const xyz: Xyz = labToXyz(lab);
return xyzToLinearRgb(xyz);
}
function linearRgbToSrgb({r, g, b}: LinearRgb): Srgb {
return {
r: linearRgbComponentToSrgb(r),
g: linearRgbComponentToSrgb(g),
b: linearRgbComponentToSrgb(b),
};
}
function srgbToLinearRgb({r, g, b}: Srgb): LinearRgb {
return {
r: sRgbComponentToLinearRgb(r),
g: sRgbComponentToLinearRgb(g),
b: sRgbComponentToLinearRgb(b),
};
}
function sRgbComponentToLinearRgb(u: number): number {
if (u <= 0.04045) {
return 25 * u / 323;
} else {
return Math.pow((200 * u + 11) / 211, 12 / 5);
}
}
function linearRgbComponentToSrgb(u: number): number {
if (u <= 0.0031308) {
return 323 * u / 25;
} else {
return (211 * Math.pow(u, 5 / 12) - 11) / 200;
}
}
function linearRgbToXyz({r, g, b}: LinearRgb): Xyz {
return {
x: 0.4124 * r + 0.3576 * g + 0.1805 * b,
y: 0.2126 * r + 0.7152 * g + 0.0722 * b,
z: 0.0193 * r + 0.1192 * g + 0.9505 * b,
};
}
function xyzToLinearRgb({x, y, z}: Xyz): LinearRgb {
return {
r: (+3.2406 * x) + (-1.5372 * y) + (-0.4986 * z),
g: (-0.9689 * x) + (+1.8758 * y) + (+0.0415 * z),
b: (+0.0557 * x) + (-0.2040 * y) + (+1.0570 * z),
};
}
function xyzToLab({x, y, z}: Xyz): Lab {
return {
l: 1.16 * f(y) - 0.16,
a: 5 * (f(x) - f(y)),
b: 2 * (f(y) - f(z)),
};
function f(t: number): number {
const DELTA: number = 6 / 29;
if (t > Math.pow(DELTA, 3)) {
return Math.pow(t, 1 / 3);
} else {
return t / (3 * Math.pow(DELTA, 2)) + 4 / 29;
}
}
}
function labToXyz({l, a, b}: Lab): Xyz {
return {
x: fInv((l + 0.16) / 1.16 + a / 5),
y: fInv((l + 0.16) / 1.16),
z: fInv((l + 0.16) / 1.16 - b / 2),
};
function fInv(t: number): number {
const DELTA: number = 6 / 29;
if (t > DELTA) {
return Math.pow(t, 3);
} else {
return 3 * Math.pow(DELTA, 2) * (t - 4 / 29);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment