Last Updated: February 25, 2016
· mzungu777

Using CIE-LCh for better color blending

Transitioning or blending colors can be a bit of a problem. For a lot of interface animations, a simple RGB interpolation (interpolating the red, green, and blue components linearly) will work, because you're simply lightening, darkening, or slightly altering the color. However, in games, experimental interfaces, or other visual programming, sometimes you need to transition between dramatically different colors.

RGB color space

If you view the RGB color space as a circle, you'll see that the center is desaturated. If you're transitioning from one side of the color space to the other side, you'll be going through the middle, resulting in a grey or muddy colors in the middle of the transition.

To try to solve this in the past, I (and countless others) have tried using HSV (or HSB), since it seems like it should work nicely. However, because of the way our eyes perceive color, simply interpolating the hue, saturation, and value (brightness) doesn't work out either - some hues, while sharing the same saturation and brightness, appear brighter than others.

So, how do we handle color blending without resulting in gross colors? The CIE-LCh color space. What are the components of the CIE-LCh color space? I don't know, but you really don't need to care. What matters is that if you convert your color from RGB to its CIE-LCh alternative, then linearly interpolate each of its three components, you get a smooth blend that evenly transitions hue, perceived saturation and perceived brightness.

Blend using RGB
Blend using RGB

Blend using HSV
Blend using HSV

Blend using CIE-LCh
Blend using CIE-LCh

(Images from Stuart Denman's blog post)

One final note - the only drawback is that the conversion between RGB and CIE-LCh involves exponents, which are more computationally expensive than other mathematical operations. If you're animating, you may not want to be converting back and forth between RGB and CIE-LCh on every render loop. Instead, I'd recommend calculating some number of intermediate color values with CIE-LCh - say, 5 or 6 intermediate values - and then interpolating between those values with the RGB color space for a rough (but very good) approximation of a true CIE-LCh blend.

For more information, check out Stuart Denman's original blog post

For a Javascript implementation, see my blog post