Color Models

RGB isn't the only game in town, at least when it comes to color models. Bruce examines alternatives to RGB, including CMY, HSV, HLS, and YIQ, and discusses how you get from one to another. Harry Smith adds insight on the HVC color model.


July 01, 1993
URL:http://www.drdobbs.com/windows/color-models/184409033

Figure 1


Figure 2


Copyright © 1993, Dr. Dobb's Journal

Figure 3


Copyright © 1993, Dr. Dobb's Journal

Figure 3


Copyright © 1993, Dr. Dobb's Journal

Figure 3


Copyright © 1993, Dr. Dobb's Journal

Figure 1


Copyright © 1993, Dr. Dobb's Journal

Figure 2


Copyright © 1993, Dr. Dobb's Journal

Figure 3


Copyright © 1993, Dr. Dobb's Journal

JUL93: Color Models

Color Models

RGB isn't the only game in town

Bruce Schneier

Bruce is the author of Applied Cryptography: Protocols, Algorithms, and Source Code in C (John Wiley & Sons, 1993) and can be contacted at 730 Fair Oaks Ave., Oak Park, IL 60302.


What's so great about red, green, and blue? Why not orange, yellow, and violet? Or, for that matter, why not turquoise, ochre, and periwinkle? Why not two colors? Or four?

The answers to these questions involve the human eye. Our perception of color begins when light passes through visual pigments in the retinal cones. There are three pigments-red, green, and blue-that are optimally perceived at wavelengths of approximately 580, 545, and 440 nanometers, respectively.

In 1931, the Comission Internationale de l'Eclairage, or CIE (also known as the International Commission on Illumination) established a color standard, deciding that all colors should be defined in terms of three principal colors: red, green, and blue (RGB). The standard was first used in color television, and eventually in computers. Not every color can be reproduced with this red/green/blue color model (or any other color model for that matter) but it suffices. More colors could be added, but the payoff would not be worth the extra bits. RGB is here to stay.

Still, RGB isn't the only game in town. There are several other color models, each with its strengths and weaknesses. Among those discussed in this article are CMY, HSV, HLS, and YIQ. Additionally, there's the HVC model, described in the text box "Putting Colors in Order." But let's start by reviewing RGB.

RGB

Think of a three-dimensional unit cube, with red along the x axis, green along the y axis, and blue along the z axis; see Figure 1. All colors are defined within this cube according to the degree of red, green, and blue in them. The origin is (0,0,0) and is black. The vertex is (1,1,1) and is white. Red is (1,0,0), blue is (0,0,1), and green is (0,1,0). Yellow, which is red plus green, is (1,1,0). And so on. The important thing is that the color model is additive. Red and green are added together to produce yellow. Red, green, and blue are added together to produce white.

CMY

Computer monitors are additive, but color printers are generally subtractive. Instead of combining light from phosphors, printers coat paper with colored pigments. The eye sees colors by reflected light, which is a subtractive process.

Cyan, magenta, and yellow (CMY) are the complements of red, green, and blue. For example, cyan is everything that isn't red. When white light is reflected off cyan-colored ink, the red light is absorbed, or subtracted, and the reflected light has no red component. To get the color red, you have to deposit magenta (which absorbs green) and yellow (which absorbs blue), leaving only red light to be reflected into the human eyeball.

The CMY cube is the opposite of the RGB cube. White is (0,0,0) and black is (1,1,1). Cyan is (1,0,0), magenta is (0,1,0), green is (1,0,1), and so on.

Converting from RGB to CMY is easy:

C=1-R

M=1-G

Y=1-B

Many printers use a four-color process by adding black because in real life the combination of CMY pigments produces something more akin to gray than black. The CMYK color model, for cyan-magenta-yellow-black, is defined as:

K=minimum (C,M,Y)

C=C-K

M=M-K

Y=Y-K

HSV

Red, green, and blue may be how the human eye perceives light, but it isn't the way the human mind perceives color. Instead, we see the color, or hue, which is the frequency of the light. We see the luminance, or brightness, which is a measure of the intensity of the light. The higher the intensity of the light, the brighter it appears. We also see the saturation, or purity, of the light. Bold primaries are very pure. Pastels are not.

Figure 2 shows a hexcone, a graphical representation of the hue, saturation, and value (HSV) model (sometimes called hue, saturation, and brightness, or HSB). H is represented as an angle about the vertical access, from 0 to 360 degrees. S and V vary from 0 to 1. Pure red, which is (1,0,0) in the RGB model, is (0 degrees,1,1) in HSV; pure green is (120 degrees,1,1) in HSV. Listing One (page 96) provides routines in Pascal that convert from RGB to HSV and back.

The HSV color model is a more intuitive way to choose colors. Starting with a pure hue, you can add white and black by changing the S and V parameters, until the color is perfect. If you have Microsoft Windows, pull up the color-palette dialog and play with the HSV color model.

HSV is also good for reducing the amount of memory required to store color information. With 24-bit color, 8 bits are used to store each of the R, G, and B parameters. With HSV, things are easier. The human eye can only distinguish about 128 different hues and 130 different saturation levels. At the yellow end of the spectrum, the human eye can only distinguish about 23 different shades; at the blue end it's even less. That means that humans can only really distinguish 128x130x23=382,720 different colors. A program could allocate 14 bits to color information: 7 for hue, 3 for saturation, and 4 for brightness. Add a lookup table for quick conversion to RGB for display on a monitor, and you're done.

HLS

The hue, lightness, and saturation (HLS) color model is quite similar to the HSV model, and neither has any marked advantage over the other. H is the same in both models. L ranges from 0 (black) to 1 (white). S still specifies the relative purity of the color, but the purity is slightly different in this case. Pure red is (0 degrees,0.5,1) and pure green is (120 degrees,0.5,1). Conversion routines are also provided in Listing Two (page 96).

YIQ

YIQ is the color model used for U.S. commercial television. It was designed to be backwards-compatible with black-and-white TV sets, and thus may seem a bit odd. Y stands for luminance, or brightness-the only variable that black-and-white television sets display. (Note that this Y is slightly different from the V in the HSV color model and the L in the HLS model.) I and Q contain color information, and are called the "chromaticity." You can convert from RGB to YIQ using the following formulas:

Y=030*R+0.59*G+0.11*B

I=060*R-0.28*G-0.32*B

Q=021*R-0.53*G+0.31*B

These equations assume the standard RGB NTSC phosphor, whose CIE numbers are exactly defined. If you're finicky enough about the particular characteristics of your monitor for this to make a difference, consult Computer Graphics: Principles and Practice, second edition by Foley, van Dam, et al. (Addison-Wesley, 1992) or another good graphics text.

It is interesting to note that according to the first equation of the RGB-to-YIQ set, green is much more important in determining luminosity than blue. In fact, the human eye is far less sensitive to blue light than it is to red or green light. That's why in 8-bit color RGB models, three bits each are used to store the red and green values, while only two bits are used to store the blue value.

Putting Colors in Order

Harry J. Smith

Harry is an engineer specializing in satellite-telemetry data processing. He can be reached at 19628 Via Monte Drive, Saratoga, CA 95070.


In any software or hardware interface to a color display, there must be a way of specifying the various colors that can be displayed. However, specifying many colors (say 64, 256, or 256,000) in an orderly, understandable fashion can become a significant problem. This article discusses a method of converting an RGB (red, green, and blue) specification to another color specification-HVC (hue, value, and chroma). HVC has an advantage over RGB, in that colors can be ordered by dominant frequency (hue), luminance (value), and the amount of color (chroma).

This method of converting RGB to HVC is based on a paradigm I developed that consists of a geometric model for visualizing a color specification. The model is illustrated in the two-dimensional graph in Figure 3. On this graph, each color is represented as three points, equally spaced around the circumference of a circle, with vertical coordinates between 0.0 and 1.0. These coordinates are considered to be the relative intensity of the three phosphor colors: red, green, and blue. The vertical coordinate of the center of the circle constitutes the color's Value parameter. The angle between the radius from the center to the green point and a vertical base line is considered the Hue of the color, and the circle's radius is the Chroma.

Given an RGB triplet or vector, it's not easy to figure out how to plot them so that they lie on a circle, so I'll develop the equations here.

To derive the model, I'll first start with an HVC triplet and derive equations for computing RGB. Then I'll find the inverse of this transformation.

In Figure 3, notice that the angle from the vertical base to R is H+120 degrees; the angle G is H and the angle to B is H-120 degrees. It's easy to see that R, G, and B can be described by the equations in Example 1(a).

This set of three equations can be solved for HVC, as shown in Example 1(b), where atan2 is the arc-tangent function of two arguments (y,x), which is equal to the arc-tangent of y/x but resolves the result to be in the proper quadrant. This set of equations can be simplified for computations if V is computed first, as in Example 1(c).

Looking at Figure 3, you can think of a color as a bubble floating in two-dimensional space. If the bubble rotates through 360 degrees without changing its position or size, it will travel through all color hues without changing its amount of luminance or color. If it rises without rotating or changing its size, it will be the same color hue and have the same amount of color, but will have more white and be brighter. If it expands in size without rotating and keeps its center fixed, it will be the same color hue and the same luminance but will have more color and less grayness.

Once you master this way of looking at color as a two-dimensional bubble floating above a horizontal line-rotating, rising, falling, expanding, and contracting-it becomes relatively easy to travel through color space in an orderly manner.

The accompanying source code implements these concepts. The implementation language is Turbo Pascal 5.0. Listing Three (page 96) shows a procedure for converting RGB to HVC. Listing Four (page 96) contains a procedure for converting HVC to RGB.

Figure 1: The three-dimensional RGB cube.

Figure 2: Single-hexcone HSV color model.

Figure 3: The model is a two-dimensional color bubble.

Example 1: Color-conversion equations.

 (a)   R = V - C cos(H + 120 degrees)
       G = V - C cos(H)
       B = V - C cos(H - 120 degrees)

 (b)   H = atan2( R - B, (sqrt(3) / 3)(R - 2G + B))
       V = (R + G + B) / 3
       C = (R - 2G + B) / (3 cos(H)
       or
       C = (R - B) / (sqrt(3) sin(H))

 (c)   V = (R + G + B) / 3
       H = atan2(R - B, sqrt(3)(V - G))
       C = (V - G) / cos(H)               if |cos(H)| > 0.2
       C = (R - B) / (sqrt(3) sin(H))      if |cos(H)| <= 0.2

 (d)   V = (1.0 + 0.25 + 0.75) / 3 = 0.6667
       H = atan2(0.25, sqrt(3)(0.4167)) = 19.1066 degrees
       C = 0.4167 / cos(19.1066 degrees) = 0.4410

[LISTING ONE] (Text begins on page 38.)


{---- RGB -> HSV by Bruce Schneier ----}
procedure RGB_to_HSV (r,g,b : real; var h,s,v : real)
   var min, delta : real;
   begin
      v := maximum(r,g,b);
      min := minimum(r,g,b);
      if v<>0 then s := (v - min)/min else s := 0;
      if s := 0
         then h := UNDEFINED;
         else
            begin
               delta := v - min;
               if r = v then h := (g - b)/delta

               else if g = v then h := (b - r)/delta
               else if b = v then h := (r - g)/delta;
               h := h*60;
               if h<0 then h := h + 360
            end
   end;
prodcedure HSV_to_RGB (h,s,v : real; var r,g,b : real)
   var i, f, j, k, l : real;
   begin
      if h = 360 then h := 0;
      h := h/60;
      i := floor(h)  {Floor returns the greatest integer <= h}
      f := h - i;  {f is the fractional part of h}
      j := v * (1 - s);
      k := v * (1 - (s * f));
      l := v * (1 - (s * (1 - f)));
      case i of
         0 : begin r := v; g := l; b := j end;
         1 : begin r := k; g := v; b := j end;
         2 : begin r := j; g := v; b := l end;
         3 : begin r := j; g := k; b := v end;
         4 : begin r := l; g := j; b := v end;
         5 : begin r := v; g := j; b := k end
      end
   end;

[LISTING TWO]


{---- RGB -> HLS by Bruce Schneier ----}
procedure RGB_to_HLS (r,g,b : real; var h,l,s, : real)
   var min, max, delta : real;
   begin
      max := maximum(r,g,b);
      min := minimum(r,g,b);
      l := (max + min)/2;
      if max = min
         then begin s:= 0; h := UNDEFINED end
         else
            begin
               if l <= 0.5
                  then s := (max - min)/(max + min)

                  else s := (max - min)/(2 - max - min);
               delta := max - min;
               if r = max then h := (g - b)/delta
               else if g = max then h := 2 + (b - r)/delta
               else if b = max then h := 4 + (r - g)/delta;
               h := h*60;
               if h<0 then h := h + 360
            end
   end;
procedure HLS_to_RGB (h,l,s : real; var r,g,b : real)
   var m,n : real;
   int function value (a,b,hue : real)
      begin
         if hue > 360 then hue := hue - 360
         else if hue < 0 then hue := hue + 360;
         if hue < 60 then value := a + (b-a) * hue/60
         else if hue < 180 then value := b
         else if hue < 240 then value := a + (b - a)*(240-hue)/60
         else value := a
      end
   begin
      if l <= 0.5
         then n := l * (l + s)
         else n := l + s + l * s;
      m := 2 * l - n;
      if s = 0
         then begin r := l; g := l; b := l end
         else
            begin
               r := value (m,n,h+120);
               g := value (m,n,h);
               b := value (m,n,h-120)
           end
   end;

[LISTING THREE]


{---- HVC -> RGB  by Harry Smith ----}

procedure Hvc2Rgb( H, V, C : Double; var R, G, B : Double);
  { Converts H-hue, V-value, C-chroma to R-red, G-green, B-blue }
const
  Pi    = 3.14159265358979324;
  Pi2o3 = 2.0 * Pi / 3.0;
  DpR   = 180.0 / Pi;          { Degrees per Radian }
var
  HRad : Double;
begin
  HRad:= H / DpR;
  R:= V - C * Cos( HRad + Pi2o3);
  G:= V - C * Cos( HRad);
  B:= V - C * Cos( HRad - Pi2o3);
end; { Hvc2Rgb }

[LISTING FOUR]


{----  RGB -> HVC by Harry Smith ----}
function ATan2( Y, X : Double) : Double;
  { Arc Tangent of Y over X }
  { -Pi < ATan2 <= Pi }
const
  Pi   = 3.14159265358979324;
  Pio2 = Pi / 2.0;
var
  Temp : Double;
begin
  if X = 0 then begin
    if Y > 0 then  ATan2:= Pio2
    else if Y < 0 then  ATan2:= -Pio2
    else  ATan2:= 0;
  end
  else begin
    Temp:= ArcTan( Y / X);
    if X > 0 then  ATan2:= Temp
    else if Y >= 0 then  ATan2:= Temp + Pi
    else  ATan2:= Temp - Pi;
  end;
end; { ATan2 }
{--------------------------------------}
procedure Rgb2Hvc( R, G, B : Double; var H, V, C : Double);
  { Converts R-red, G-green B-blue, to H-hue, V-value, C-chroma }
const
  Pi    = 3.14159265358979324;
  Pi2   = 2.0 * Pi;
  DpR   = 180.0 / Pi;          { Degrees per Radian }
  SqRt3 = 1.73205080756887719; { Square root of 3.0 }
var
  CosHue : Double;
  HRad   : Double;
begin
  V:= (R + G + B) / 3.0;
  HRad:= ATan2( R - B, SqRt3 * (V - G));
  CosHue:= Cos( HRad);
  if abs( CosHue) > 0.2 then
    C:= (V - G) / CosHue
  else
    C:= (R - B) / (SqRt3 * Sin( HRad));
  H:= HRad * DpR;
  if H < 0.0 then  H:= H + 360.0;
end; { Rgb2Hvc }
End Listings


Copyright © 1993, Dr. Dobb's Journal

Terms of Service | Privacy Statement | Copyright © 2024 UBM Tech, All rights reserved.