HCL color space

Chroma
Hue
View the full source.
Luminance
Mark out-of-gamut region

The HCL color space is an alternative to the traditional device-centric HSV and HSL. HSL and HSV are attractive because of the easy explanations behind the coordinates, but they are not perceptually uniform: changes in one coordinate will tend to change your perception of the value along the other coordinate.

The Luv color space, on the other hand, is explicitly designed to be perceptually uniform, but its uv coordinates are not very intuitive. The HCL colorspace preserves the L(uminance) axis of Luv, but tranforms uv to polar coordinates, where the distance from zero has a nice interpretation in terms of "chroma" ("saturation" in the HSL and HSV colorspaces), and the phase is our familiar hue.

HCL, however, is not as simple as HSV, and this interactive experiment shows why. HCL tends to specify colors outside of the RGB gamut, which means that some sensible choices of HCL values will generate values outside the (0,0,0)-(1,1,1) RGB cube. More worryingly, the HCL->RGB transformation is discontinuous. Although it lies outside the RGB gamut, clamping the transform to the closest RGB point does not patch the seam in the color space. The discontinuity is fairly obvious for low luminances.

The first potential solution is to find a simple slice of the HCL parameter space that is all in-gamut for RGB. Limiting the chroma as a function of luminance can do that, and there's a simple function which is the minimum of two linear ramps which works. This has the problem of eliminating some valid in-gamut mappings: for example, some highly chromatic yellows and greens are not reachable.

The other solution is to clamp the transformation differently. Instead of using the closest point inside the RGB gamut after transform, the alternative is to use the transform of the closest point in HCL space that still transforms inside the RGB gamut. But this seems hard to implement, because the RGB gamut boundary in HCL is a complicated surface, defined only implicitly through the conversion chain HCL->LUV->XYZ->RGB.

Back to the index.