COLOR(6)                                                 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 displays.  Although this avoids problems
          caused by multiplexing color maps between applications, it
          requires that the color map chosen be suitable for most pur-
          poses 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 impor-
          tant 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
          6x6x6 (as in Netscape Navigator) or 8x8x4 (as in previous
          releases of Plan 9), picking 1 color in each, the rgbv color
          map uses a 4x4x4 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 sam-
          ples plus black) and a reasonable selection of colors cover-
          ing 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;

     Page 1                       Plan 9             (printed 3/28/24)

     COLOR(6)                                                 COLOR(6)

                           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) coor-
          dinates 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 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, 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.  Prop-
          erly 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 intensi-
          ties 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 inten-
          sity (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(2). The function setalpha (see

     Page 2                       Plan 9             (printed 3/28/24)

     COLOR(6)                                                 COLOR(6)

          allocimage(2)) aids the initialization of color values with
          non-trivial alpha.

          The packing of pixels into bytes and words is odd.  For com-
          patibility with VGA frame buffers, the bits within a pixel
          byte are in big-endian order (leftmost pixel is most signif-
          icant 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 repre-
          sent colors by 32-bit numbers, as described in color(2).

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

     Page 3                       Plan 9             (printed 3/28/24)