colorjs.io
Version:
Color space agnostic color manipulation library
79 lines (68 loc) • 2.02 kB
JavaScript
import Color from "./../color.js";
Color.defineSpace({
id: "lab",
name: "Lab",
coords: {
L: [0, 100],
a: [-100, 100],
b: [-100, 100]
},
inGamut: coords => true,
// Assuming XYZ is relative to D50, convert to CIE Lab
// from CIE standard, which now defines these as a rational fraction
white: Color.whites.D50,
ε: 216/24389, // 6^3/29^3
κ: 24389/27, // 29^3/3^3
fromXYZ(XYZ) {
const {κ, ε, white} = this;
// compute xyz, which is XYZ scaled relative to reference white
let xyz = XYZ.map((value, i) => value / white[i]);
// now compute f
let f = xyz.map(value => value > ε ? Math.cbrt(value) : (κ * value + 16)/116);
return [
(116 * f[1]) - 16, // L
500 * (f[0] - f[1]), // a
200 * (f[1] - f[2]) // b
];
},
toXYZ(Lab) {
// Convert Lab to D50-adapted XYZ
// http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html
const {κ, ε, white} = this;
// compute f, starting with the luminance-related term
let f = [];
f[1] = (Lab[0] + 16)/116;
f[0] = Lab[1]/500 + f[1];
f[2] = f[1] - Lab[2]/200;
// compute xyz
var xyz = [
Math.pow(f[0], 3) > ε ? Math.pow(f[0], 3) : (116*f[0]-16)/κ,
Lab[0] > κ * ε ? Math.pow((Lab[0]+16)/116, 3) : Lab[0]/κ,
Math.pow(f[2], 3) > ε ? Math.pow(f[2], 3) : (116*f[2]-16)/κ
];
// Compute XYZ by scaling xyz by reference white
return xyz.map((value, i) => value * white[i]);
},
parse (str, parsed = Color.parseFunction(str)) {
if (parsed && parsed.name === "lab") {
let L = parsed.args[0];
// Percentages in lab() don't translate to a 0-1 range, but a 0-100 range
if (L.percentage) {
parsed.args[0] = L * 100;
}
return {
spaceId: "lab",
coords: parsed.args.slice(0, 3),
alpha: parsed.args.slice(3)[0]
};
}
},
instance: {
toString ({format, ...rest} = {}) {
if (!format) {
format = (c, i) => i === 0? c + "%" : c;
}
return Color.prototype.toString.call(this, {name: "lab", format, ...rest});
}
}
});