ENG | Creative Coding: Crafting Beautiful Color Gradients Using CIE LCH
Exploring gradients in various colorspaces.
While creating slime mold simulation, I tried to add some nice color gradients. I’m aware that RGB is one of many ways how to describe colors and there are ones which claim to be wastly superior.
There are basically these methods how to describe color
- Mixing ratio of red, green, blue light
- Angle on color wheel (hue), saturation/chroma, brightness/value/intensity/luminance
- Luminance and two color components (such as blue- vs yellow+, purple- vs green+)
Main details are
- Are red, green, blue, intensity perceptually linear or exponential (for RGB they are not and gamma correction is applied - not many people know this and naively blurring image makes it darker, using RGB in 3d rendering creates too dark shadows,… no, #808080 is not 50% gray.)
- Does angle on color wheel keep saturation and brightness constant? In HSV, blue and yellow are obviously not perceived as equaly bright.
- Are same anglular distances perceived as the same difference in color (difference between orange and yellow-green is huge, difference between blue with red and green tint is not)
Well known formats are
- RGB
- HSL, HSV - Quite intuitive colorpickers with wheel and triangle.
Lesser known are
- sRGB (linear intensity)
- YUV (image and video compression - intensity + two color components)
- XYZ - I don’t know but it’s often used as intermediate format for conversion to LAB
- CIE LAB - tries to achieve uniform intensity (luminance), A,B are color components. Distance from center is saturation (chroma), angle from center to point at a, b is hue.
- CIE LCH - see above - literally L stays,
H=atan(b,a)
,C=sqrt(a^2 + b^2)
,a=C*cos(H)
,b=C*sin(H)
I was aware that these exists. I was also known that many palettes in scientific visualization tool such as matplotlib
, seaborn
use palettes defined by Beziér curves in likely CIE LAB color space. And I knew that using RGB for color interpolation is not the best idea cause it gives weird gradients such as red -> dark brown -> bright green or blue -> gray -> yellow. So I asked some LLM (I think it was ChatGPT) if it can write RGB to LAB conversion in C++ and checked it against OpenCV documentation. Doing conversion to LCH was easy.
I added linear interpolation and result was almost better than I expected. I was able to get good looking gradients, similar to colormaps from matplotlib using three control points.
![Gradients]
Links
- github code