W3C home > Mailing lists > Public > www-style@w3.org > December 1997

color specification in Cascading Style Sheets

From: Blair MacIntyre <bm@cs.columbia.edu>
Date: Sat, 6 Dec 1997 17:34:10 -0500 (EST)
To: www-style@w3.org
Message-ID: <Pine.GSO.3.96.971206173354.29391I-100000@renoir.cs.columbia.edu>

I've recently read the color part of the CSS specification.

While I'm very happy that you are specifying colors in sRGB, so that we
may start to expect some sort of uniformity across displays, I am dismayed
to see that only an RGB notation is going to be supported. 

While RGB is convenient for machines, and often useful for people who have
become accustomed to it, in many situations, either the HSV or (even
better) HSL notations are more useful. Both of these notations are simple
transformations of the RGB color space, but represent more intuitive
spaces for general use by the average non-technologist.  For example,
consider the following activities:
- selecting a range of similar colors, for shadows or highlighting.
  Using these spaces, we simply change the value/lightness or saturation,
  but keep the hue the same.
- Selecting a set of colors for a group of objects.
  By keeping the value/lightness and saturation constant, and varying 
  the hue, we get colors that are more balanced in terms of intensity and
  saturation than we might get by manual fiddling with RGB values.

These represent the kinds of things people do constantly when designed
color schemes for the web, and are can be extremely difficult to do with
RGB notation. 

Obviously, those of us who program or have been doing computer graphics
for a while are relatively comfortable using RGB, since we have
significant experience with it.  But, specifying RGB colors is
non-intuitive for people who do not have significant experience with RGB
or computers. 

While it may appear simpler to not include extra specifications in the
standard, there is really no good reason not to include support for one of
these spaces, especially because the HLS and HSV models are trivial to
convert to/from RGB.  For example, I am appending my C code for converting
between HLS and RGB and back, which came from Graphics Gems, p. 764. 

I urge you to consider including HLS in the standard.  It will allow a
richer and more varied and pleasing set of colors to be used by people on
the Web.

   Sincerely,
     Blair MacIntyre

------------
#define HUE_UNDEFINED (-1.0)
typedef struct { double r,g,b; }      CLR_RGB;
typedef struct { double h,l,s; }      CLR_HLS;

CLR_HLS 
CLR_rgb_to_hls(rgb)
    CLR_RGB rgb;
{
    CLR_HLS hls;
    double  max,min,delta;

    max = MAX3(rgb.r, rgb.g, rgb.b);
    min = MIN3(rgb.r, rgb.g, rgb.b);

    /* calculate the lightness */
    hls.l = (max + min)/2.0;
    
    if (max == min)
    {
	/* Achromatic case, r=b=g */
	hls.s = 0.0;
	hls.h = HUE_UNDEFINED;
    } 
    else 
    {
	/* Chromatic case.  First, the saturation */
	if (hls.l <= 0.5)
	    hls.s = (max - min)/(max + min);
	else
	    hls.s = (max - min)/(2 - max - min);

	/* Next, the hue */
	delta = max - min;
	if (rgb.r == max)
	    hls.h = (rgb.g - rgb.b)/delta;
	else if (rgb.g == max)
	    hls.h = 2 + (rgb.b - rgb.r)/delta;
	else if (rgb.b == max)
	    hls.h = 4 + (rgb.r - rgb.g)/delta;
	hls.h *= 60.0;
	
	if (hls.h < 0.0)
	    hls.h += 360.0;
    }

    return hls;
}

CLR_RGB
CLR_hls_to_rgb(hls)
    CLR_HLS hls;
{
    CLR_RGB rgb;
    double value;

    /* the algorithm calls for hue in the range [0,1], while we are
     * using values in the range [0,360], so scale it
     */
    hls.h /= 360.0;

    value = (hls.l <= 0.5) ? (hls.l * (1.0 + hls.s)) : 
	(hls.l + hls.s - hls.l * hls.s);

    if (value <= 0)
    {
	rgb.r = rgb.g = rgb.b = 0.0;
    }
    else
    {
	double m;
	double sv;
	int sextant;
	double fract, vsf, mid1, mid2;

	m = hls.l + hls.l - value;
	sv = (value - m)/value;
	hls.h *= 6.0;
	sextant = hls.h;
	fract = hls.h - sextant;
	vsf = value * sv * fract;
	mid1 = m + vsf;
	mid2 = value - vsf;

	switch (sextant)
	{
	  case 0: 
	    rgb.r = value;
	    rgb.g = mid1;
	    rgb.b = m;
	    break;
	  case 1:
	    rgb.r = mid2;
	    rgb.g = value;
	    rgb.b = m;
	    break;
	  case 2:
	    rgb.r = m;
	    rgb.g = value;
	    rgb.b = mid1;
	    break;
	  case 3:
	    rgb.r = m;
	    rgb.g = mid2;
	    rgb.b = value;
	    break;
	  case 4:
	    rgb.r = mid1;
	    rgb.g = m;
	    rgb.b = value;
	    break;
	  case 5:
	    rgb.r = value;
	    rgb.g = m;
	    rgb.b = mid2;
	    break;
	}
    }
    return rgb;
}
Received on Saturday, 6 December 1997 17:34:28 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Monday, 27 April 2009 13:53:53 GMT