d3 / d3-color

Color spaces! RGB, HSL, Cubehelix, CIELAB, and more.
https://d3js.org/d3-color
ISC License
398 stars 91 forks source link

L*a*b* chromatic adaptation #42

Closed danburzo closed 6 years ago

danburzo commented 6 years ago

While investigating why d3's lab() method gives subtly different results than, for example, Wolfram Alpha, I came to understand d3-color is missing a chromatic adaptation between the D65 (sRGB) and D50 (Lab) illuminants:

The process should be: Lab ↔ XYZ (D50) ↔ XYZ(D65) ↔ RGB

I'm not sure how important this adaptation is to the purpose of the library, but it boils down to using the matrices from this page:

const d50_to_d6 = ({ x, y, z }) => ({
    x: x * 0.9555766 - y * 0.0230393 + z * 0.0631636,
    y: x * -0.0282895 + y * 1.0099416 + z * 0.0210077,
    z: x * 0.0122982 - y * 0.0204830 + z * 1.3299098
});

const d65_to_d50 = ({ x, y, z }) => ({
    x: x * 1.0478112 + y * 0.0228866 - z * 0.0501270,
    y: x * 0.0295424 + y * 0.9904844 - z * 0.0170491,
    z: x * -0.0092345 + y * 0.0150436 + z * 0.7521316
});
mbostock commented 6 years ago

Wow, CSS will include lab and lch color spaces! Nice of them to include detailed descriptions and reference implementations. Changing d3-color to match the specification would be great.

danburzo commented 6 years ago

The current CSS specification for Lab / LCH leaves some legroom to the choice of matrices / precision when transforming sRGB to Lab, but the intent is to have the Lab be relative to the standard D50 white point. In the pull request above, I'm skipping some intermediary steps from the reference implementation and using a single matrix for linear RGBXYZD50 from the same web page they cite in their code.

The output closely matches Matlab's rgb2lab and lab2rgb fucntions, so I think this may be a wrap until the CSS Color Module Level 4 spec gets fleshed out :)

mbostock commented 6 years ago

Fixed in #46.