Skip to content

Instantly share code, notes, and snippets.

@denis-bz
Last active March 26, 2022 14:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save denis-bz/ec601823dc52666812a3e27b88772a84 to your computer and use it in GitHub Desktop.
Save denis-bz/ec601823dc52666812a3e27b88772a84 to your computer and use it in GitHub Desktop.
HUSL rgb_to_lch is not CIELCh

HUSL rgb_to_lch is for CIELuv, not CIELab

Keywords: color-space HUSL HSLuv CIELCh CIELuv CIELab max-chroma everyone-knows

Whenever something can be done in two ways, someone will be confused.

22mar-husl-wall-imshow2

There are two quite different color spaces:
CIELab aka L*a*b* is widely used, and fairly uniform
CIELuv is used in HSLuv aka HUSL, "a human-friendly alternative to HSL".
These have equivalent versions in polar coordinates, CIELCh <--> CIELab and CIELChuv <--> CIELuv:
C = radius = sqrt( a² + b² ) or sqrt( u² + u² )
hue = angle 0 to 360 degrees = atan2( b / a ) or atan2( v / u ).

CIELCh_uv is not CIELCh

The function rgb_to_lch( rgb ) in seaborn husl.py or nphusl calculates the CIELCh_uv based on CIELuv, NOT the CIELCh based on CIELab.

Notes

Does it matter -- for what purpose ? See the excellent Seaborn Choosing color palettes, in particular the plot of Luminance and Saturation of 6 standard palettes.

MacEvoy's "modern color models" on handprint says

CIELUV has been discarded as the basis for future work".

colorspacious has a nice graph of color spaces, CIELab <--> XYZ100 <--> sRGB1-linear ... (Beware: cspace_convert( x, anyspace, "sRGB1" ) can land waaay outside RGB 0 .. 1 -- it's up to you to check.)

colorio

The sRGB gamut is a perfect cube in sRGB space, and takes curious shapes when translated into other color spaces. The above images show the sRGB gamut in different color spaces.

Finding CIELuv max_chroma( L, hue ) is fast in nphusl, but finding CIELab max_chroma seems to be not so easy, see https://github.com/endolith/complex_colormap . (What's the "boundary" or "edge" of a discrete point cloud, e.g. 2^24 RGB points in an oddly-shaped color space ?)

A simple test, corners of the RGB cobe -> Luv and Lab

rgb: (8, 3) 
[[  0   0   0   0 255 255 255 255]
 [  0   0 255 255   0   0 255 255]
 [  0 255   0 255   0 255   0 255]] 

{ nphusl__rgb_to_lch  max 179 at [1 0 0] 
[[  0  32  88  91  53  60  97 100]
 [  0 130 135  72 179 137 107   0]
 [  0 266 128 192  12 308  86  20]]
}

{ cspace_rgb_LCh  max 133 at [0 0 1] 
[[  0  32  88  91  53  60  97 100]
 [  0 133 119  50 104 115  96   0]
 [  0 306 136 196  40 328 103 302]]
}

{ cspace_rgb_JCh  max 111 at [1 0 0] 
[[  0  21  80  84  47  54  96 100]
 [  0  90 106  59 111  97  80   3]
 [  0 258 137 198  32 330 106 211]]
}

cheers
-- denis-bz-py@t-online.de 25 March 2022

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment