Open adrian5 opened 2 years ago
I noticed this as well when converting from RGB to LCH.
Input: #421AFD
Output:
lch(33.789% 122.345 301.987)
lch(35.959% 125.517 306.756)
Most noticeable is the +5 to the hue, which skews the colour closer to purple
as far as I understand it. the conversion depends on the white-point.
CIELAB is calculated relative to a reference white, for which the CIE recommends the use of CIE Standard Illuminant D65.[1] D65 is used in the vast majority industries and applications, with the notable exception being the printing industry which uses D50
https://en.wikipedia.org/wiki/CIELAB_color_space#Cylindrical_representation:_CIELCh_or_CIEHLC
So you would have to know what white-point each library is using to be able to compare its results.
It looks like colord uses W3C sample code for making the conversion from RGB → LAB: https://github.com/omgovich/colord/blob/master/src/colorModels/lab.ts#L45 https://www.w3.org/TR/css-color-4/#color-conversion-code
The W3C draft specifies the D50 whitepoint:
Convert from a D65 whitepoint (used by sRGB) to the D50 whitepoint used in Lab
https://www.w3.org/TR/css-color-4/#rgb-to-lab
d3-color uses their own algorithm and also uses D50 as the whitepoint: https://github.com/d3/d3-color/blob/main/src/lab.js#L5 https://observablehq.com/@mbostock/lab-and-rgb
And chroma.js uses D65 here: https://github.com/gka/chroma.js/blob/master/src/io/lab/lab-constants.js#L6
So this looks to be the reason for the difference
https://css.land/lch seems to use https://drafts.csswg.org/css-color-4/utilities.js for converting between sRGB and LCH, which document the steps like this:
function sRGB_to_LCH(RGB) {
// convert an array of gamma-corrected sRGB values
// in the 0.0 to 1.0 range
// to linear-light sRGB, then to CIE XYZ,
// then adapt from D65 to D50,
// then convert XYZ to CIE Lab
// and finally, convert to CIE LCH
function LCH_to_sRGB(LCH) {
// convert an array of CIE LCH values
// to CIE Lab, and then to XYZ,
// adapt from D50 to D65,
// then convert XYZ to linear-light sRGB
// and finally to gamma corrected sRGB
// for in-gamut colors, components are in the 0.0 to 1.0 range
// out of gamut colors may have negative components
// or components greater than 1.0
// so check for that :)
I do not know what steps chroma.js uses, but it would be interesting to know and hear the reasons for the difference in steps taken.
This library looks wonderfully feature rich, but playing with the demo page I noticed that it produces a different RGB color than other libraries, given LCH input.
Input:
{ l: 59.6, c: 61.3, h: 24.3 }
Output:
#ec5f67
#ec5f67
#ec5f67
#ec5f67
#ef6066
Is this due to differences in the transformation stages, or maybe LCHab vs LCHuv? I have very limited knowledge of this topic, so I couldn't say.