mathr / blog / #

An obscure colour space for saturation adjustment

vector scope

I stumbled across Susan Roberta Curtis' 1982 MSc thesis: Saturation and Luminance Control in Color Image Processing. This defines an LC1C2 colour space with some interesting properties that make it more useful than either RGB or YUV.

RGB is a pain at the best of times, but YUV isn't much better. The problem with YUV is that the "constant saturation curve" is not a circle, but a skew ellipse, which makes setting absolute saturation very tricky. This is generally shown best on a vector scope.

The constant saturation curves in the LC1C2 colour space seems to be more circular than in YUV, I haven't measured it yet but the results are pleasing. Here's a fragment of GLSL code that sets the saturation of an RGB colour:

   // inputs
   vec3 in;
   float saturation;
   // outputs
   vec3 out;
   // conversion matrices
   mat3 rgb2lcc = mat3(
      0.299,  0.621,  0.080,
      0.498, -0.442, -0.056,
     -0.162, -0.336,  0.498
  mat3 lcc2rgb = mat3(
      1.0,  1.407,  0.0,
      1.0, -0.677, -0.236,
      1.0,  0.0,    1.848
   // saturation bashing
   vec3 lcc1 = in * rgb2lcc;
   float l  = lcc1.x;
   float c1 = lcc1.y;
   float c2 = lcc1.z;
   float sat = saturation/sqrt(c1*c1+c2*c2);
   vec3 lcc2 = vec3(l, sat*c1, sat*c2);
   vec3 out = lcc2 * lcc2rgb;

Next step is to investigate LC1C2 more scientifically.