Previous Next Table of Contents

5. Cómo especificar colores

5.1 Valores de píxels y mapas de colores

La pantalla de un display de mapa de bits se puede considerar como una colección de posiciones de píxels. Cada posición de píxel almacena un valor de píxel que representa un color específico. Dichos valores de píxels se almacenan en una memoria de vídeo (frame memory) compuesta de planos. Cada plano contiene un bit por cada posición de píxel de pantalla, y todos los bits de los planos dan el valor del píxel correspondiente.

Si la memoria de vídeo tiene cuatro planos y los valores 1010 para los planos 0, 1, 2 y 3 respectivamente, entonces el valor de píxel es 5. Si tuviera ocho planos y los valores 01101000 para los planos 0, 1, 2, 3, 4, 5, 6 y 7, entonces el valor del píxel sería 22.

Un mapa de colores es una tabla en la que se almacenan las relaciones entre los valores de píxels y los colores reales. Cada celda de la tabla almacena los valores de intensidad de los tres colore primarios rojo, verde y azul (RGB). Estos valores se envían a un convertidor D/A y posteriormente a la pantalla CRT.

5.2 Mapa de colores por defecto

El mapa de colores por defecto se crea en el servidor cuando se inicializa. Se puede obtener el ID de este mapa de colores usando la macro DefaultColormap o la función equivalente XDefaultColormap. A menos que se necesite crear un mapa de colores específico para un propósito especial, el mapa de colores por defecto es el que se suele usar la mayoría de las veces.

La sintaxis de la macro y de la función es la siguiente:

Colormap Default( display, pantalla )
Colormap XDefaultColormap( Display *display, int pantalla )

5.3 Localización de celdas de colores

Para obtener el valor de píxel, es decir, el índice de la celda, para un color determinado se pueden usar dos funciones. Si se quiere obtener el valor de píxel más cernano o unos valores RGB dados se usa XAllocColor, mientras que si se quiere usar un nombre simbólico de color se usa XAllocNameColor.

5.4 La estructura XColor

Para localizar una celda de color (o simplemente, un color) se necesita la estructura XColor para almacenar la información. Su definición es la siguiente:

typedef struct {
    unsigned long pixel;
    unsigned short red, green, blue;
    char flags;   /* do_red, do_green, do_blue */
    char pad;
} XColor;

En el campo pixel es donde devuelve el valor de píxel (la posición del color en el mapa de colores). En red, green y blue se especifican los valores RGB, que deben estar entre 0 y 255, independientemente del número actual de bits que se usen en la pantalla.

El campo flags se usa sólo cuando se usa el tipo descompuesto de mapa de colores. Por último, el campo pad se usa internamente por el sistema.

5.5 Llamadas Xlib: localización de colores

Status XAllocColor( Display *display, Colormap mapa, XColor *color )

El argumento mapa indica el ID del mapa de colores, normalmente el mapa de colores por defecto. El argumento color es un puntero a una estructura XColor en la que se deben especificar los valores RGB del color que se desea encontrar. Como resultado, la función devuelve el color más parecido en el campo pixel y reemplaza los valores RGB enviados por los valores del color devuelto como más cercano.

Status XAllocNameColor( Display *display, Colormap mapa,
                        const char *nombre,
                        XColor *color, XColor *exacto )

En XAllocNamedColor, no hay que especificar los valores RGB, sino el nombre del color que se desea encontrar. Los nombres que el servidor X considera colores válidos se pueden encontrar en el fichero /usr/lib/X11/rgb.txt. Como resultado, se devuelve en el campo pixel el color más cercano, y los valores exactos correspondientes al color en los campos red, green y blue de la estructura exacto.

5.6 Ejemplo: problema

Escribir un programa que ponga el color de fondo de una ventana amarillo y el de fondo azul usando nombres de colores.

5.7 Ejemplo: solución


#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdio.h>
 
main()
    {
    Display *d;
    Window w;
    Colormap mapa;
    XColor c1, c2, aux;
    XSetWindowAttributes atributos;
 
    d    = XOpenDisplay( NULL );
    mapa = DefaultColormap( d, DefaultScreen( d ) );
 
    XAllocNamedColor( d, mapa, "blue",   &c1, &aux );
    XAllocNamedColor( d, mapa, "yellow", &c2, &aux );
 
    w = XCreateSimpleWindow( d, DefaultRootWindow( d ),
                             200, 100, 400, 300, 10, c1.pixel, c2.pixel );
 
    atributos.override_redirect = True; /* para puentear el WM */
    XChangeWindowAttributes( d, w, CWOverrideRedirect, &atributos );
 
    XMapWindow( d, w );
    XFlush( d );
    getchar();
    }

5.8 Llamadas Xlib: cambio de los colores de ventana

Las siguientes llamadas a la Xlib cambian el color de fondo y el color de borde de una ventana:

XSetWindowBackground( Display *display, Window *ventana,
                      unsigned long pixel )
XSetWindowBorder( Display *display, Window *ventana,
                  unsigned long pixel )

5.9 Ejemplo: problema

Crear una ventana de 400 por 300 píxels con un borde de 10 píxels de ancho. La ventana debe tener un color de fondo inicial con los siguientes valores RGB: ( 29184, 40704, 65280 ), y un color de borde con los siguientes valores RGB: ( 55108, 43520, 0 ), que corresponden respectivamente a sky blue y a gold.

Una vez creada se deben intercambiar los colores de fondo y borde usando XAllocColor.

5.10 Ejemplo: solución


#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdio.h>
 
main()
    {
    Display *d;
    Window w;
    Colormap mapa;
    XColor colorBorde, colorFondo;
    XSetWindowAttributes atributos;
 
    d    = XOpenDisplay( NULL );
    mapa = DefaultColormap( d, DefaultScreen( d ) );
 
    colorBorde.red = 29184; colorBorde.green = 40704; colorBorde.blue = 65280;
    colorFondo.red = 55108; colorFondo.green = 43520; colorFondo.blue =     0;
 
    XAllocColor( d, mapa, &colorBorde );
    XAllocColor( d, mapa, &colorFondo );
 
    w = XCreateSimpleWindow( d, DefaultRootWindow( d ), 200, 100,
                             400, 300, 10, colorBorde.pixel, colorFondo.pixel );
 
    atributos.override_redirect = True; /* para puentear el WM */
    XChangeWindowAttributes( d, w, CWOverrideRedirect, &atributos );
 
    XMapWindow( d, w );
    XFlush( d );
    getchar();
 
    XUnmapWindow( d, w );
 
    XSetWindowBackground( d, w, colorBorde.pixel );
    XSetWindowBorder( d, w, colorFondo.pixel );
 
    XMapWindow( d, w );
    XFlush( d );
    getchar();
    }

5.11 LAB: mostrar el mapa de colores

Escribir un programa que haga lo siguiente:

  1. Crear una ventana con las siguientes especificaciones borde castaño fondo azul ancho suficiente para las ventanas hijas altura suficiente para las ventanas hijas
  2. Crear una subventana para cada color del mapa de colores, de forma que el color de fondo de cada ventana sea el correspondiente del mapa de colores.

5.12 Ejemplo: problema

Crear una función que dado el display y una cadena de caracteres devuelva el valor del píxel correspondiente del mapa de colores. El prototipo debe ser el siguiente:

unsigned long Color( Display *display, char *nombreColor )

5.13 Ejemplo: solución


#include <X11/Xlib.h>
#include <X11/Xutil.h>
 
unsigned long Color( Display *d, const char *nombreColor )
    {
    XColor color, aux;
 
    XAllocNamedColor( d, DefaultColormap( d, DefaultScreen( d ) ),
                      nombreColor, &color, &aux );
 
    return color.pixel;
    }

El siguiente programa es un ejemplo que usa la función anterior:


#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdio.h>
 
main()
    {
    Display *d;
    Window w;
    unsigned long azul, amarillo;
    XSetWindowAttributes atributos;
 
    d = XOpenDisplay( NULL );
 
    azul     = Color( d, "blue"   );
    amarillo = Color( d, "yellow" );
 
    w = XCreateSimpleWindow( d, DefaultRootWindow( d ), 200, 100,
                             400, 300, 10, azul, amarillo );
 
    atributos.override_redirect = True; /* para puentear el WM */ 
    XChangeWindowAttributes( d, w, CWOverrideRedirect, &atributos );
 
    XMapWindow( d, w );
    XFlush( d );
    getchar();
    }

5.14 LAB: solución


#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdio.h>
 
#define ANCHO 10
#define ALTO  25
 
main()
    {
    Display *d;
    Window madre, hija;
    Colormap mapa;
    XColor borde, fondo, aux;
    int numeroColores, i;
    XSetWindowAttributes atributos;
 
    d             = XOpenDisplay( NULL );
    mapa          = DefaultColormap( d, DefaultScreen( d ) );
    numeroColores = XDisplayCells( d, DefaultScreen( d ) );
    printf( "\nHay %d celdas en el mapa de colores por defecto", numeroColores );
 
    XAllocNamedColor( d, mapa, "maroon", &borde, &aux );
    XAllocNamedColor( d, mapa, "blue",   &fondo, &aux );
 
    madre = XCreateSimpleWindow( d, DefaultRootWindow( d ), 0, 0,
                            ( ANCHO * numeroColores ) + 10, ALTO + 10, 10,
                            borde.pixel, fondo.pixel );
 
    atributos.override_redirect = True; /* para puentear el WM */
    XChangeWindowAttributes( d, madre, CWOverrideRedirect, &atributos );
 
    XMapWindow( d, madre );
    XFlush( d );
 
    for ( i = 0; i < numeroColores; i++ )
        {
        hija = XCreateSimpleWindow( d, madre, ( ANCHO * i ) + 5, 5,
                                    ANCHO, ALTO, 0, i, i );
        XMapWindow( d, hija );
        }
    XFlush( d );
    getchar();
    }


Previous Next Table of Contents