|
NAME
| |
color – representation of pixels and colors
|
DESCRIPTION
| |
To address problems of consistency and portability among applications,
Plan 9 uses a fixed color map, called rgbv, on 8-bit-per-pixel
displays. Although this avoids problems caused by multiplexing
color maps between applications, it requires that the color map
chosen be suitable for most purposes and usable for
all. Other systems that use fixed color maps tend to sample the
color cube uniformly, which has advantages--mapping from a (red,
green, blue) triple to the color map and back again is easy--but
ignores an important property of the human visual system: eyes
are much more sensitive to small changes in intensity than
to changes in hue. Sampling the color cube uniformly gives a color
map with many different hues, but only a few shades of each. Continuous
tone images converted into such maps demonstrate conspicuous artifacts.
Rather than dice the color cube into subregions of size 6×6×6 (as
in Netscape Navigator) or 8×8×4 (as in previous releases of Plan
9), picking 1 color in each, the rgbv color map uses a 4×4×4 subdivision,
with 4 shades in each subcube. The idea is to reduce the color
resolution by dicing the color cube into fewer
cells, and to use the extra space to increase the intensity resolution.
This results in 16 grey shades (4 grey subcubes with 4 samples
in each), 13 shades of each primary and secondary color (3 subcubes
with 4 samples plus black) and a reasonable selection of colors
covering the rest of the color cube. The advantage is
better representation of continuous tones.
The following function computes the 256 3-byte entries in the
color map:
| |
void
setmaprgbv(uchar cmap[256][3])
{
| |
uchar *c;
int r, g, b, v;
int num, den;
int i, j;
for(r=0,i=0; r!=4; r++)
for(v=0; v!=4; v++,i+=16)
for(g=0,j=v−r; g!=4; g++)
for(b=0; b!=4; b++,j++){
c = cmap[i+(j&15)];
den = r;
if(g > den)
den = g;
if(b > den)
den = b;
if(den == 0) /* would divide check; pick grey shades */
c[0] = c[1] = c[2] = 17*v;
else{
num = 17*(4*den+v);
c[0] = r*num/den;
c[1] = g*num/den;
c[2] = b*num/den;
}
}
|
}
|
There are 4 nested loops to pick the (red,green,blue) coordinates
of the subcube, and the value (intensity) within the subcube,
indexed by r, g, b, and v, whence the name rgbv. The peculiar
order in which the color map is indexed is designed to distribute
the grey shades uniformly through the map--the i’th grey
shade, 0<=i<=15 has index ix17, with black going to 0 and white to
255. Therefore, when a call to draw converts a 1, 2 or 4 bit-per-pixel
picture to 8 bits per pixel (which it does by replicating the
pixels’ bits), the converted pixel values are the appropriate
grey shades.
The rgbv map is not gamma-corrected, for two reasons. First, photographic
film and television are both normally under-corrected, the former
by an accident of physics and the latter by NTSC’s design. Second,
we require extra color resolution at low intensities because of
the non-linear response and adaptation of
the human visual system. Properly gamma-corrected displays with
adequate low-intensity resolution pack the high-intensity parts
of the color cube with colors whose differences are almost imperceptible.
Either reason suggests concentrating the available intensities
at the low end of the range.
On ‘true-color’ displays with separate values for the red, green,
and blue components of a pixel, the values are chosen so 0 represents
no intensity (black) and the maximum value (255 for an 8-bit-per-color
display) represents full intensity (e.g., full red). Common display
depths are 24 bits per pixel, with 8 bits per
color in order red, green, blue, and 16 bits per pixel, with 5
bits of red, 6 bits of green, and 5 bits of blue.
Colors may also be created with an opacity factor called alpha,
which is scaled so 0 represents fully transparent and 255 represents
opaque color. The alpha is premultiplied into the other channels,
as described in the paper by Porter and Duff cited in draw(3).
The function setalpha (see allocimage(3)) aids the
initialization of color values with non-trivial alpha.
The packing of pixels into bytes and words is odd. For compatibility
with VGA frame buffers, the bits within a pixel byte are in big-endian
order (leftmost pixel is most significant bits in byte), while
bytes within a pixel are packed in little-endian order. Pixels
are stored in contiguous bytes. This results in unintuitive
pixel formats. For example, for the RGB24 format, the byte ordering
is blue, green, red.
To maintain a constant external representation, the draw(3) interface
as well as the various graphics libraries represent colors by
32-bit numbers, as described in color(3).
|
SEE ALSO
|
|