chroma-js
Version:
JavaScript library for color conversions
102 lines (85 loc) • 2.95 kB
JavaScript
import LAB_CONSTANTS from './lab-constants.js';
import { unpack } from '../../utils/index.js';
/*
* L* [0..100]
* a [-100..100]
* b [-100..100]
*/
const lab2rgb = (...args) => {
args = unpack(args, 'lab');
const [L, a, b] = args;
const [x, y, z] = lab2xyz(L, a, b);
const [r, g, b_] = xyz2rgb(x, y, z);
return [r, g, b_, args.length > 3 ? args[3] : 1];
};
const lab2xyz = (L, a, b) => {
const { kE, kK, kKE, Xn, Yn, Zn } = LAB_CONSTANTS;
const fy = (L + 16.0) / 116.0;
const fx = 0.002 * a + fy;
const fz = fy - 0.005 * b;
const fx3 = fx * fx * fx;
const fz3 = fz * fz * fz;
const xr = fx3 > kE ? fx3 : (116.0 * fx - 16.0) / kK;
const yr = L > kKE ? Math.pow((L + 16.0) / 116.0, 3.0) : L / kK;
const zr = fz3 > kE ? fz3 : (116.0 * fz - 16.0) / kK;
const x = xr * Xn;
const y = yr * Yn;
const z = zr * Zn;
return [x, y, z];
};
const compand = (linear) => {
/* sRGB */
const sign = Math.sign(linear);
linear = Math.abs(linear);
return (
(linear <= 0.0031308
? linear * 12.92
: 1.055 * Math.pow(linear, 1.0 / 2.4) - 0.055) * sign
);
};
const xyz2rgb = (x, y, z) => {
const { MtxAdaptMa, MtxAdaptMaI, MtxXYZ2RGB, RefWhiteRGB, Xn, Yn, Zn } =
LAB_CONSTANTS;
const As = Xn * MtxAdaptMa.m00 + Yn * MtxAdaptMa.m10 + Zn * MtxAdaptMa.m20;
const Bs = Xn * MtxAdaptMa.m01 + Yn * MtxAdaptMa.m11 + Zn * MtxAdaptMa.m21;
const Cs = Xn * MtxAdaptMa.m02 + Yn * MtxAdaptMa.m12 + Zn * MtxAdaptMa.m22;
const Ad =
RefWhiteRGB.X * MtxAdaptMa.m00 +
RefWhiteRGB.Y * MtxAdaptMa.m10 +
RefWhiteRGB.Z * MtxAdaptMa.m20;
const Bd =
RefWhiteRGB.X * MtxAdaptMa.m01 +
RefWhiteRGB.Y * MtxAdaptMa.m11 +
RefWhiteRGB.Z * MtxAdaptMa.m21;
const Cd =
RefWhiteRGB.X * MtxAdaptMa.m02 +
RefWhiteRGB.Y * MtxAdaptMa.m12 +
RefWhiteRGB.Z * MtxAdaptMa.m22;
const X1 =
(x * MtxAdaptMa.m00 + y * MtxAdaptMa.m10 + z * MtxAdaptMa.m20) *
(Ad / As);
const Y1 =
(x * MtxAdaptMa.m01 + y * MtxAdaptMa.m11 + z * MtxAdaptMa.m21) *
(Bd / Bs);
const Z1 =
(x * MtxAdaptMa.m02 + y * MtxAdaptMa.m12 + z * MtxAdaptMa.m22) *
(Cd / Cs);
const X2 =
X1 * MtxAdaptMaI.m00 + Y1 * MtxAdaptMaI.m10 + Z1 * MtxAdaptMaI.m20;
const Y2 =
X1 * MtxAdaptMaI.m01 + Y1 * MtxAdaptMaI.m11 + Z1 * MtxAdaptMaI.m21;
const Z2 =
X1 * MtxAdaptMaI.m02 + Y1 * MtxAdaptMaI.m12 + Z1 * MtxAdaptMaI.m22;
const r = compand(
X2 * MtxXYZ2RGB.m00 + Y2 * MtxXYZ2RGB.m10 + Z2 * MtxXYZ2RGB.m20
);
const g = compand(
X2 * MtxXYZ2RGB.m01 + Y2 * MtxXYZ2RGB.m11 + Z2 * MtxXYZ2RGB.m21
);
const b = compand(
X2 * MtxXYZ2RGB.m02 + Y2 * MtxXYZ2RGB.m12 + Z2 * MtxXYZ2RGB.m22
);
return [r * 255, g * 255, b * 255];
};
export default lab2rgb;
export { xyz2rgb };