Formato XPM

Generalidades

Imagen XPM

X PixMap es un formato de fichero para almacenar imágenes, generalmente de pequeño tamaño, como iconos o gráficos usados en menús y barras de herramientas.

Se almacenan en ficheros de texto con la extensión "xpm".

Hay varias versiones, pero en este artículos hablaremos de la versión 3, que es la más reciente.

El formato es básicamente una definición de un array de cadenas constantes en C, con ciertos comentarios obligatorios y otros opcionales.

Este formato tiene varias ventajas:

  • Se puede editar manualmente usando un sencillo editor de textos.
  • Se puede incluir como código C en programas, en lugar de usar ficheros gráficos externos.
  • Permite añadir comentarios.

Formato

El formato es muy simple:

/* XPM */
static const char <identificador>[] = {
<valores>
<colores>
<pixels>
<extensiones>
};

Como separadores se usan espacios o tabuladores.

La primera línea es obligatoria cuando se trata de ficheros e indica que se trata de un formato XPM versión 3.x.

La segunda línea declara un array de cadenas constantes con un identificador.

La tercera línea indica los valores enteros en base diez que definen las propiedades el gráfico. Estos valores son:

<width> <height> <ncolors> <cpp> [<x_hotspot> <y_hotspot>] [<SPMEXT>] 

Donde:

  • width: Anchura, en pixels.
  • height: Altura, en pixels.
  • ncolors: Número de colores.
  • cpp: caracteres por pixel.
  • Opcionalmente:
    • x_hotspot: coordenada x del punto activo, para gráficos que se usarán como cursores.
    • y_hotspot: coordenada y del punto activo, para gráficos que se usarán como cursores.
    • XPMEXT: etiquetas de las extensiones opcionales.

A continuación se añade una línea por cada color, un total de ncolors líneas.

Cada línea de color tiene el siguiente formato:

<chars> {<key> <color>}+

Donde:

  • chars: es una cadena de cpp caracteres, sin delimitadores.
  • key: es una palabra clave que indica contexto de color se debe usar. Puede ser uno de los siguientes valores:
    • m: visualización monocromo.
    • s: nombre simbólico.
    • g4: escala de cuatro niveles de gris.
    • g: escala de más de cuatro niveles de gris.
    • c: un color.
  • color: especifica el color. Puede ser un nombre simbólico, como Red, Green, Yellow, Blue, Magenta, etc que el programa debe traducir adecuadamente después de cargar. También puede ser una codificación RGB, que empieza con el carácter # y usa dos caracteres hexadecimales para cada componente, por ejemplo, #808080, o #FF0030. O none, para indicar transparencia.

Siguen a continuación height cadenas de width*cpp caracteres que indican el color de cada pixel. Para cada pixel se usará una de las cadenas chars definidas en el apartado de colores.

Finalmente se añaden las extensiones, si existen.

Ejemplo

Veamos un ejemplo:

/* XPM */
static const char *const slider_xpm[] = {
/* columns rows colors chars-per-pixel */
"32 32 16 1",
"  c Gray0",
". c #808000",
"X c #000080",
"o c #808080",
"O c #000000",
"+ c #808000",
"@ c #000080",
"# c none",
"$ c #808080",
"% c Red",
"& c Green",
"* c Yellow",
"= c Blue",
"- c Magenta",
"; c Cyan",
": c Gray100",
/* pixels */
"################################",
"################################",
"################################",
"################################",
"################################",
"################################",
"################################",
"################################",
"#######      ###################",
"###### :::::$ ##################",
"###### :####$ ##################",
"###### :####$ ##################",
"###### :####$ ##################",
"###### :####$ ##################",
"###### :####$ ##################",
"##     :####$                 ##",
"## $$$ :####$ $$$$$$$$$$$$$$$ ##",
"## ### :####$ ############### ##",
"## ### :####$ ############### ##",
"## ### :####$ ############### ##",
"###### :####$ ##################",
"###### :####$ ##################",
"###### :$$$$$ ##################",
"#######      ###################",
"################################",
"################################",
"################################",
"################################",
"################################",
"################################",
"################################",
"################################"
};

Este ejemplo define un gráfico con el identificador "slider_xpm", de 32x32 pixels y 16 colores. Los colores se codifican con cadenas de un carácter.

Así, por ejemplo, el espacio identifica los pixels de color 'Gray0', el carácter '#' indica los pixels transparentes, el '$' los pixels de color #808080 o los ':' los pixels de color Gray100.

Evidentemente, no es necesario utilizar todos los colores.

Uso

Existen librerías para leer y convertir estos ficheros en imágenes, pero en nuestro caso nos interesa usarlos para cargar imágenes en proyectos basados en wxWidgets.

wxWidgets dispone de una clase manipuladora para convertir imágenes en este formato. Se trata de wxXPMHandler.

Para usar estos ficheros en nuestras aplicaciones wxWidgets deberemos añadir el manipulador XPM a nuestro código e incluir el fichero con el gráfico xpm. Después podremos usar el identificador del array como una imagen para cargar mapas de bits o iconos.

Por ejemplo, para usar una imagen xpm para el icono de la aplicación podríamos usar el siguiente código:

#include "logo_24.xpm"

IMPLEMENT_APP(miApp);

bool miApp::OnInit()
{
    miFrame* frame = new sudokuFrame(0L, _T("Mi aplicación wxWidgets"));
    wxImage::AddHandler(new wxXPMHandler);
    wxIcon ic(icono_xpm);
    frame->SetIcon(ic); // To Set App Icon
...

Convertidor a xpm

Podemos generar ficheros de imágenes xpm manualmente, usando un editor de textos, pero es relativamente fácil cometer errores, sobre todo con imágenes que no sean muy sencillas. Es mejor usar algún programa convertidos, como por ejemplo el de la página para conversión de ficheros de imagen entre diferentes formatos: https://convertio.co/es/.

Los ficheros convertidos usan un identificador para el array que probablemente tendremos que cambiar, ya que usa cadenas generadas mediante alguna fórmula y que no aportan información sobre la imagen.

Además, si ese fichero convertido se va a usar en un programa C++, será necesario hacer otra modificación, añadiendo el modificador const a la definición del array de cadenas, ya que el convertidor no lo hace.

Bibliografía

https://www.x.org/docs/XPM/xpm.pdf.

https://en.wikipedia.org/wiki/X_PixMap.