glenda.party
term% ls -F
term% cat index.txt
COLOR(6)                         Games Manual                         COLOR(6)

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  dis‐
       plays.  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  advan‐
       tages—mapping  from  a  (red,  green, blue) triple to the color map and
       back again is easy—but ignores an important property of the  human  vi‐
       sual 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), pick‐
       ing 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  uni‐
       formly  through  the  map—the i'th grey shade, 0<=i<=15 has index iÃ17,
       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,  photo‐
       graphic film and television are both normally under-corrected, the for‐
       mer 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.   Prop‐
       erly  gamma-corrected  displays  with adequate low-intensity resolution
       pack the high-intensity parts of the color cube with colors whose  dif‐
       ferences  are almost imperceptible.  Either reason suggests concentrat‐
       ing 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  de‐
       scribed in the paper by Porter and Duff cited in draw(2).  The function
       setalpha  (see  allocimage(2))  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 exam‐
       ple, 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(2).

SEE ALSO
       color(2), graphics(2), draw(2)

                                                                      COLOR(6)