Department of Engineering

IT Services

Using Colour

Windows in X on a color display always have an associated colormap, a collection of color cells (i.e. triples of R, G and B values).

On some high end displays it may be possible to interpret the contents of the colormap in more than one way. These `ways' are called Visuals. The possible classes of visual are:-

  • Direct Color:- A pixel value is separated into 3 fields, each used for indexing separate R,G,B arrays.
  • True color:- Like DirectColor, except that colormap has predefined read-only, server-dependent, values.
  • PseudoColor:- The pixel value indexes the colormap (an array of triples) to produce RGB values.
  • Static Color:- read-only PseudoColor.
  • GrayScale:- A degenerate case of PseudoColor, when within a triple, R=G=B.
  • StaticGray:- read-only GrayScale.

If you just use

Visual XDefaultVisual(display,screen)

to find the default Visual and use that, you can't go far wrong. Use

Colormap XDefaultColorMap(display,screen)

to get the default colormap. Colormaps are local to a particular screen and if read-only, may be shared among multiple applications.

Much hardware built today have a single color map, so the primitives are written to encourage sharing of color map entries between applications. If there is not sufficient colormap resources in the display, then some windows may not be displayed in their true colors. If you ask for colors that are named then you're more likely to be able to share an already used colorcell.

Colors can be specified by RGB values or by name. Color information is held in the following structure.

typedef struct         /* the colour structure is used to set  */
{                      /* colour cell mappings for the screen  */
    unsigned long pixel;           /* pixel value    */
    unsigned long red,green,blue;  /* intensity (0 to 65535) */
    char flags;                    /* DoRed, DoGreen, DoBlue */
    char pad;
} XColor;

Allocating Color cells

To see how to use Read/Write cells, see a later section. Use Read Only cells if at all possible.

Status XAllocColor(display,cmap,screen_def)
    XColor *screen_def;        /* supplies RGB values.
           RETURNS pixel value closest to the RGB specified
           and the RGB values actually used */

Status XAllocNamedColor(display,cmap,colorname,screen_def,exact_def);
   char *colorname;    /* supplies name of color                           */
   XColor *screen_def; /* RETURNS the values actually used in the colormap */
   XColor *exact_def;  /* RETURNS the closest color provided by the hardware*/

Read Only Colorcells: An easy Example

 

#include <stdio.h> 
#include <X11/X.h>
#include <X11/Xlib.h> 
#define NAME "red"  
 main (argc, argv) 
 char   *argv[]; 
 int     argc; 
 { 
     XColor   color_cell, truecolor;
     XSetWindowAttributes attributes; 
     Visual *visual; 
     int depth; 
     int which_color,which_cell,which_plane; 
     Display *display; 
     Window  win; 
     GC gc; 
     Colormap cmap; 
     XEvent event; 
     int screen;
     setbuf (stdout, NULL); 
     setbuf (stderr, NULL); 

     display = XOpenDisplay(NULL); 
     screen = DefaultScreen(display);
     visual = DefaultVisual(display,screen); 
     depth  = DefaultDepth(display,screen); 
     cmap= XDefaultColormap(display,screen); 

     attributes.background_pixel      = XWhitePixel(display,screen); 
     attributes.border_pixel          = XBlackPixel(display,screen); 
     attributes.override_redirect     = 1; 
  
     win = XCreateWindow(display,XRootWindow(display,screen),0,0,507,426,5,
           depth, InputOutput,visual,
           CWBackPixel | CWBorderPixel | CWOverrideRedirect,&attributes);
  
     XSelectInput(display,win,ButtonPressMask+ KeyPressMask) ; 
  
  
     gc=XCreateGC(display,win,NULL,NULL); 
  
     XMapWindow(display,win); 
  
       /* first by RGB values */
       color_cell.flags= DoRed | DoGreen | DoBlue; 
       color_cell.red = 10000; 
       color_cell.green = 40000; 
       color_cell.blue = 60000;        
       if (XAllocColor(display,cmap,&color_cell)==0)
           fprintf("XAllocColor failed\n");
       XSetForeground(display,gc,color_cell.pixel);
  
       XDrawImageString(display,win,gc,250,50,"RGB color",9); 
       XFlush(display);
  
       /* now by name */
  
       if (XAllocNamedColor(display,cmap,
                             NAME, &color_cell, &truecolor) == 0) {
            fprintf(stderr, "Color '%s' unknown\n", NAME);
       }
       if (truecolor.red != color_cell.red ||
                truecolor.green != color_cell.green ||
                truecolor.blue != color_cell.blue) {
            fprintf(stderr, "Warning: %s color may be wrong\n", NAME);
       }
       XSetForeground(display,gc,color_cell.pixel);
       XDrawImageString(display,win,gc,250,80, "named color",11); 
       XFlush(display); 
  
       printf("now press button: \n"); 
       do{ 
         XNextEvent(display,&event); 
       }while(event.type != ButtonPress); 
  
       printf("closing display\n"); 
       XCloseDisplay(display); 
       exit(0); 
 }

The following routine consults the database /usr/lib/X11/rgb.txt which contains RGB info on the named colors

Status XLookupColor(display,cmap,spec,screen_def,exact_def);
   char *spec;         /* case ignored */
   XColor *screen_def; /* RETURNS the values actually used in the colormap */
   XColor *exact_def;  /* RETURNS the closest color provided by the hardware*/

useful little routines are

Status XParseColor(display,colormap,spec, screen_def)
    char *spec;        /* name of colour or spec string        */
         /* a spec string must begin with a hash sign and then */
         /* contain 3,6,9 or 12 hex digits with no spaces      */
         /* these are taken in groups of 1,2,3 or 4 respectively*/
         /* to give the desired RGB value for the colour       */
    Color *screen_def;    /* RETURN nearest RGB supported by hardware */

XQueryColor(display,cmap,def);
   XColor *def; /*supplies pixel value, RETURNS RGB */
XQueryColors(display,cmap,defs, ncolors);
   XColor defs[ncolors]; /*supplies pixel values, RETURNS RGB */

X11R5 introduced a more sophisticated color system called Xcms which is beyond the scope of this handout.