Color
HueSaturationByValue.gif (5695 bytes) HSV  Lab Report
Display Colors by Red-Green-Blue or Hue-Saturation-Value
ScreenHSV.jpg (66076 bytes)

Purpose
The purpose of this program is to select and display colors either by specifying Red-Green-Blue or Hue-Saturation-Value quantities.

Materials and Equipment

Software Requirements
Windows 95/98
Delphi 3 or 4 (to recompile)
HSV.EXE

Hardware Requirements
Best when run on 800 x 600 pixel (or higher) monitor in high color or true color display mode.

Procedure

  1. Double click on the HSV.EXE icon to start the program.
  2. Change any of the Red-Green-Blue Trackbars on the right, just like in the RGBColors Lab Report.  When any RGB TrackBar  changes, the color box at the top is updated, the HSV TrackBars are updated, and the Hue-Saturation Color Circle is updated at the lower left.
  3. Move the Hue Trackbar to the left or right.  The color box at the top is updated as are the RGB Trackbars at the right.  Note the black radius line moves in the Hue-Saturation Color Circle to indicate the hue angle.  The color box above the Saturation Trackbar is updated to show all saturations for the given hue and value.   The Value Trackbar color box is updated to show all values for the given hue and saturation. 
  4. Move the Saturation Trackbar to the left or right.  The color box at the top is updated, as are the appropriate RGB Trackbars.  The gray circle is updated in the Hue-Saturation Color Circle to indicate the Saturation level from 0.0 at the circle center to 1.0 at the outer edge.  The color box above the Hue Trackbar is updated to show all hues for the given saturation and value.  The Value Trackbar is updated to show all values for the given hue and saturation. 
  5. Move the Value Trackbar to the left or right.  The color box at the top is updated, as are the appropriate RGB Trackbars.  The color boxes above the hue and saturation Trackbars are updated.  The Hue-Saturation circle is updated for the specified Value level.
  6. Click (and optionally drag) inside the Hue-Saturation circle to select HS values for a given Value.

Discussion
There are a number of color spaces in addition to the Red-Green-Blue (RGB) color space.  One non-RGB color space that is often used in computer graphics is the Hue-Saturation-Value (HSV) color space.  [For information about other color spaces, look for "Color Conversion" and "Color Spaces, Color Models" on efg's Color page.]

Here's a diagram of HSV color space:

In HSV color space, Hue is measured by an angle with Red starting at 0 degrees, Green at 120 degrees and Blue at 240 degrees.  Complementary colors are in-between:  Yellow is at 60 degrees, Cyan is at 180 degrees, and Magenta is at 300 degrees.  The black line in the diagram at the lower left on the screen shows the hue angle.

Saturation, S, is a ratio that ranges from 0.0 along the center line of the cone (the V axis) to 1 on the edge of the cone.  The gray circle above in the diagram at the lower left of the screen shows the position of the saturation value.  The colors along this saturation circle are shown in the color box above the hue trackbar.   The colors along the saturation radius are shown in the color box above the saturation trackbar.

Value, V, ranges from 0.0 (dark) to 1.0 (bright). 

Pure Red is at H= 0, S=1, V=1.

Shades of gray all have S=0, with various values of V from 0.0 (black) to 1.0 (white).   For S = 0, Hue is undefined.

When  R, G, and B as well as S and V are defined over the range 0.0 to 1.0, these values are often represented in 8 bits with an integer value ranging from 0 to 255.

Foley, et al, in Computer Graphics Principles and Practice (Amazon link) [pages 590-593] describe the HSV color model as a single hexcone (versus the double-hexcone of the Hue-Lightness-Saturation color model).  While the text describes the space as a hexcone, the color plates (II.7 and II.8) show a circular   cone.


Implementation Details

The RGB/HSV conversions are in the HSVLibrary unit.  There are two sets of conversion routines.  When only a one-way conversion is needed from HSV to RGB, and the result is to be a TRGBTriple, the function  HSVtoRGBTriple can be used.  For a one-way conversion from a RGBTriple back to HSV quantities, use the RGBTripletoHSV.   These are "one-way" routines since the converted values are treated as integers.  See the actual code for implementation of these routines.

The RGBtoHSV and HSVtoRGB routines can be used when "reversible" conversions are needed.  Sometimes conversion from RGB to HSV is needed for some sort of HSV manipulation.  When complete, the HSV values must be converted back to RGB.  If floating-point values are not used to represent the converted values, integer truncation is not always desirable.

The "general" conversion routines are shown below (see the actual code for complete details):

RGBtoHSV

USES
  Math,        // MaxValue
  IEEE754,  // NaN, IsNaN
  SysUtils;    // Exception

TYPE
  EColorError = CLASS(Exception);
  TReal = DOUBLE;

...

// RGB, each 0 to 255, to HSV.
// H = 0.0 to 360.0 (corresponding to 0..360.0 degrees around hexcone)
// S = 0.0 (shade of gray) to 1.0 (pure color)
// V = 0.0 (black) to 1.0 {white)

// Based on C Code in "Computer Graphics -- Principles and Practice,"
// Foley et al, 1996, p. 592.

PROCEDURE RGBToHSV (CONST R,G,B: TReal; VAR H,S,V: TReal);
  VAR
    Delta: TReal;
    Min : TReal;
BEGIN
  Min := MinValue( [R, G, B] );    // USES Math
  V := MaxValue( [R, G, B] );

  Delta := V - Min;

  // Calculate saturation: saturation is 0 if r, g and b are all 0
  IF       V = 0.0
  THEN S := 0
  ELSE S := Delta / V;

  IF       S = 0.0
  THEN H := NaN    // Achromatic: When s = 0, h is undefined
  ELSE BEGIN       // Chromatic
    IF       R = V
    THEN // between yellow and magenta [degrees]
      H := 60.0 * (G - B) / Delta
    ELSE
      IF       G = V
      THEN // between cyan and yellow
        H := 120.0 + 60.0 * (B - R) / Delta
      ELSE
        IF       B = V
        THEN // between magenta and cyan
          H := 240.0 + 60.0 * (R - G) / Delta;

    IF H < 0.0
    THEN H := H + 360.0
  END
END {RGBtoHSV};

 

HSVtoRGB

// Based on C Code in "Computer Graphics -- Principles and Practice,"
// Foley et al, 1996, p. 593.
//
// H = 0.0 to 360.0 (corresponding to 0..360 degrees around hexcone)
// NaN (undefined) for S = 0
// S = 0.0 (shade of gray) to 1.0 (pure color)
// V = 0.0 (black) to 1.0 (white)

PROCEDURE HSVtoRGB (CONST H,S,V: TReal; VAR R,G,B: TReal);
  VAR
    f : TReal;
    i : INTEGER;
    hTemp: TReal; // since H is CONST parameter
    p,q,t: TReal;
BEGIN
  IF       S = 0.0    // color is on black-and-white center line
  THEN BEGIN
    IF       IsNaN(H)
    THEN BEGIN
      R := V;           // achromatic: shades of gray
      G := V;
      B := V
    END
    ELSE RAISE EColorError.Create('HSVtoRGB: S = 0 and H has a value');
  END

  ELSE BEGIN // chromatic color
    IF       H = 360.0         // 360 degrees same as 0 degrees
    THEN hTemp := 0.0
    ELSE hTemp := H;

    hTemp := hTemp / 60;     // h is now IN [0,6)
    i := TRUNC(hTemp);        // largest integer <= h
    f := hTemp - i;                  // fractional part of h

    p := V * (1.0 - S);
    q := V * (1.0 - (S * f));
    t := V * (1.0 - (S * (1.0 - f)));

    CASE i OF
      0: BEGIN R := V; G := t;  B := p  END;
      1: BEGIN R := q; G := V; B := p  END;
      2: BEGIN R := p; G := V; B := t   END;
      3: BEGIN R := p; G := q; B := V  END;
      4: BEGIN R := t;  G := p; B := V  END;
      5: BEGIN R := V; G := p; B := q  END
    END
  END
END {HSVtoRGB};

The behavior of TTrackbars changed in a subtle way between Delphi 3 and Delphi 4.  In the original Delphi 3 version of this program, the position of trackbars was changed in code.  For example, any change in R,G,B values often required changes in all three of the H, S, V TTrackbars.  This was done in a straightforward way in Delphi 3.  Setting the TTrackBar.Position did not trigger an OnChange event.  BUT in Delphi 4, OnChange events are triggered and without the existing "kludge" in the code, setting the position of one of the RGB TTrackBars triggered the OnChange in the HSV TTrackBars, which triggered an OnChange in the RGB TTrackBars, and so on.  I am not sure whether this is a Delphi 4 bug or feature -- I'll wait and see what happens in Delphi 5.

The CreateHueSaturationCircle in the HSVLibrary unit can be used to create a TBitmap that contains a Hue-Saturation circle of any size.

The UpdateHueSaturationfromMouse routine is used to respond to mouse click (or mouse down followed by mouse move) events.

The Range radio box can be used to change the format of how values are displayed.   This can either be the range 0 to 255, or the range 0.0 to 1.0 -- except for Hue values that are always 0 to 360 degrees. 

Conclusions
HSV is an interesting alternative color space that is very useful in a variety of problems.

For example, see efg's Color Range Lab Report for how to extract the "yellow" part of a tulip image using Hue and Value.


Keywords
RGB, HSV, Color Space, ArcTan2, TTrackBar, CreateHSVGradient, CreateRGBGradient, CreateHueSaturationCircle,  IsPaletteDevice, High Color, True Color,  NaN, IsNan, IEEE754, MouseDown, MouseMove, ShellExecute, pRGBTripleArray, Scanline, EColorError, RGBtoHSV, HSVtoRGB, RGBtoRGBTriple, HSVtoRGBTriple, RGBTripleToHSV

Files
Delphi 3 Source Only (136 KB):  HSV.ZIP


Alexei Puzikov's HSV/RGB Color Chooser Project
based on the above Lab Report

PuzikovColorChooser.jpg (24553 bytes)

Thanks, Alexei, for contributing your Color Chooser
(and the CoolBtn component it uses).


Using a background thread to compute and display a Mandelbrot set using HSVcolor scheme, Delphi in a Nutshell, pp. 148-151

Adventures in HSV Space - July, 2001 - A detailed paper on when and how to use the Hue, Saturation, and Value color space. It includes C code for converting RGB values to and from HSV Space. It is in PDF format.


Updated 26 Feb 2005


since 5 Jul 1999