Alexei Boronine's blog, resume & projects.

Color Spaces for Human Beings

A color space is a mathematical model for describing color as a tuple of values. Some color spaces, like RGB and CMYK, are based on display technology. Some are based on human physiology, some are derived for certain useful characteristics. In this post I will briefly explain how humans see color, why HSL is often the wrong tool for the job as well as provide an alternative to HSL.

Cones and Waves

Light starts off as a fairly even mixture of waves of different wavelengths. When it bounces off an object, some wavelengths are absorbed, while others are reflected into your eye. Which ones? You’ll never know for sure, but you can get some useful information by asking your three photoreceptors: S-, M- and L-cones. Each of them is sensitive to a certain range of wavelengths.

What is the definition of green? Green is when the M-cones are being stimulated more than the L-cones, while the S-cones are hardly stimulated at all. Reverse that relationship and you get red. Add some S-cone stimulation and you get purple. Colors are defined by cone stimulation, not wavelengths. In fact, there is no single wavelength that will produce the color purple.

The more types of cones you have, the more colors you can see. 1% of males don’t have any L-cones. Red and green light stimulates their remaining cones in an identical way, so to them they are the same color. Similarly, an alien with four types of cones will consider all of humanity color blind.

RGB and HSL

It is easy to see from the above that a single color can be created in many different ways. In fact, we can choose just three primaries and combine them to create most humanly visible colors. Define red, green and blue to be within the [0, 1] range and you get the RGB color space, which can be naturally visualized as a cube.

RGB is used ubiquitously in computing because it happens to be the way most monitors output color. Even though its primaries correspond somewhat to our three types of cones, RGB is meaningless for us. Naturally, we tend to think of color in terms of hue, saturation and lightness — turns out there is a simple way to get these out of RGB.

Image derived from Jacob Rus’ original work

Behold, HSL. A cylindrical color space, hue represented by angle around the center vertical axis, saturation by distance from the axis and lightness by distance along the axis.

HSL is a Lemon

Do these colors really have the same lightness?

HSL(250, 100%, 50%)
HSL(250, 100%, 50%)
HSL(60, 100%, 50%)
HSL(60, 100%, 50%)

HSL’s lightness is only meaningful for a single color. If you try to compare the lightness of one color with the lightness of another using HSL, you will get terrible results. Please don’t do it.

And these, are they really equally saturated?

HSL(0, 90%, 40%)
HSL(0, 90%, 40%)
HSL(0, 90%, 80%)
HSL(0, 90%, 80%)

HSL’s saturation has the same problem. When you change the hue or the lightness of a color, its saturation measurement changes. Do not try to extract any meaning from comparing the saturation values of two different colors using HSL.

To make things even worse, HSL’s hue value is not very perceptually uniform. To illustrate, HSL says that the hue difference between these colors

HSL(30, 100%, 50%)
HSL(30, 100%, 50%)
HSL(50, 100%, 50%)
HSL(50, 100%, 50%)

… is the same as the hue difference between these two colors.

HSL(230, 100%, 50%)
HSL(230, 100%, 50%)
HSL(250, 100%, 50%)
HSL(250, 100%, 50%)

Let’s take a step back and list a few things you should not do with HSL:

  • Find contrast between two colors
  • Find complementary colors
  • Adjust the lightness of an image
  • Adjust the saturation of an image
  • Shift the hue of an image

In summary, HSL sucks. The reason it sucks is its simplicity, this is also the reason it grew popular in the 70s, when a more sophisticated model would have been too computationally expensive.

Good News Everyone!

Let’s go back to the late 20s, when W. David Wright and John Guild independently conducted a series of experiments on human sight. They showed their test subjects colors and asked them to match these colors by combining three primaries. If you plot how much of each primaries it took to duplicate the color of pure single-wavelength light, you get the RGB color matching functions.

In 1931, the International Commission on Illumination used these color matching functions to create a new color space, CIE XYZ. It was designed in such a way that its Y component represented the brightness of the color.

In 1976, CIE presented two color spaces derived from CIE XYZ: CIE Lab and CIE LUV, both attempting perceptual uniformity. They were adopted simultaneously when no consensus was formed in favor of one or the other. Some recommend CIE Lab for printing purposes and CIE LUV for light-emitting displays.

If we take CIE LUV and convert it to polar coordinates, we get CIE LChuv, an alternative to HSL, with L representing lightness, C representing chroma (saturation) and h representing hue. Below is a color picker that utilizes this color space.

Move the slider to change lightness:

What’s with the wacky shape? Well, as it turns out, some colors you might expect to see there simply don’t exist. For instance, there is no such thing as a dark saturated yellow. It is an impossibility. Yes, this makes the color space harder to use, but this is a necessary trade off.

In Conclusion…

Update (May 18, 2012): Since writing this blog post, I’ve created a color space designed as an alternative to HSL: HUSL.

Know your color spaces! Do not use any of HSL’s components as an absolute value, do not use HSL to compare colors or to manipulate images unless you need real-time speed. If you want to use CIE LChuv or one of many other color spaces in your CoffeeScript of JavaScript projects, check out colorspaces.js, my tiny Node.js and jQuery library.