-
Notifications
You must be signed in to change notification settings - Fork 35
Closed
Description
The issue came up in #236 that sRGB / Oklch roundtripping is not perfect for achromatic colors. We are using the Oklab matrices from Björn Ottosson’s original article, but css-color-4 has updated them based on this discussion. The conversion code at the time of writing:
// OKLab and OKLCH
// https://bottosson.github.io/posts/oklab/
// XYZ <-> LMS matrices recalculated for consistent reference white
// see https://github.com/w3c/csswg-drafts/issues/6642#issuecomment-943521484
// recalculated for 64bit precision
// see https://github.com/color-js/color.js/pull/357
function XYZ_to_OKLab(XYZ) {
// Given XYZ relative to D65, convert to OKLab
var XYZtoLMS = [
[ 0.8190224379967030, 0.3619062600528904, -0.1288737815209879 ],
[ 0.0329836539323885, 0.9292868615863434, 0.0361446663506424 ],
[ 0.0481771893596242, 0.2642395317527308, 0.6335478284694309 ]
];
var LMStoOKLab = [
[ 0.2104542683093140, 0.7936177747023054, -0.0040720430116193 ],
[ 1.9779985324311684, -2.4285922420485799, 0.4505937096174110 ],
[ 0.0259040424655478, 0.7827717124575296, -0.8086757549230774 ]
];
var LMS = multiplyMatrices(XYZtoLMS, XYZ);
// JavaScript Math.cbrt returns a sign-matched cube root
// beware if porting to other languages
// especially if tempted to use a general power function
return multiplyMatrices(LMStoOKLab, LMS.map(c => Math.cbrt(c)));
// L in range [0,1]. For use in CSS, multiply by 100 and add a percent
}
function OKLab_to_XYZ(OKLab) {
// Given OKLab, convert to XYZ relative to D65
var LMStoXYZ = [
[ 1.2268798758459243, -0.5578149944602171, 0.2813910456659647 ],
[ -0.0405757452148008, 1.1122868032803170, -0.0717110580655164 ],
[ -0.0763729366746601, -0.4214933324022432, 1.5869240198367816 ]
];
var OKLabtoLMS = [
[ 1.0000000000000000, 0.3963377773761749, 0.2158037573099136 ],
[ 1.0000000000000000, -0.1055613458156586, -0.0638541728258133 ],
[ 1.0000000000000000, -0.0894841775298119, -1.2914855480194092 ]
];
var LMSnl = multiplyMatrices(OKLabtoLMS, OKLab);
return multiplyMatrices(LMStoXYZ, LMSnl.map(c => c ** 3));
}The updated matrices seem to result in improved round-tripping.
prjctimg
Metadata
Metadata
Assignees
Labels
No labels