Mostrar/Ocultar TOC

Tabla de Contenidos del Libro
Prefacio
Capítulo 1: Introducción
Capítulo 2: Fundamentos
Capítulo 3: Mapas de Bits
Capítulo 4: Archivos Vectoriales
Capítulo 5: Metaarchivos
Capítulo 6: Dependencias de Plataforma
Capítulo 7: Conversión de Formatos
Capítulo 8: Trabajando con Archivos Gráficos  
Capítulo 9: Compresión
Capítulo 10: Multimedia
Formato: Adobe Illustrator
Formato: Adobe Photoshop
Formato: Atari ST
Formato: AutoCAD DXF
Formato: Autodesk 3D Studio
Formato: BDF
Formato: BRL-CAD
Formato: BUFR
Formato: CALS Raster
Formato: CGM
Formato: CMU
Formato: DKB
Formato: Dore Raster
Formato: DPX
Formato: Dr. Halo
Formato: DVM Movie
Formato: PostScript Encapsulado
Formato: FaceSaver
Formato: FAX
Formato: FITS
Formato: FLI
Formato: GEM Raster
Formato: GEM VDI
Formato: GIF
Texto en Inglés del Capítulo 3
Imagen del CD-ROM de la 2° Edición
Imagen del CD-ROM de la 1° Edición (Torrent y HTTPS)
Versión Hipertexto del CD-ROM de la 2° Edición (En Inglés)
Versión Hipertexto del CD-ROM de la 2° Edición (En Ruso)

Capítulo 3 — Archivos de Mapa de Bits

Capítulo 3 — Archivos de Mapa de Bits

Los archivos de mapa de bits varían grandemente en sus detalles, pero todos ellos comparten la misma estructura general. Este capítulo estudia los componentes de un archivo de mapa de bits típico. Más tarde en este capítulo, entraremos en las explicaciones de los detalles, pero por ahora simplemente familiaricémonos con la estructura general. Explicaremos a medida que sea necesario mientras avanzamos.



Cómo Están Organizados los Archivos de Mapa de Bits

Los componentes principales de un archivo de mapa de bits simple son los siguientes:

Cabecera
Datos de Mapa de Bits

Si un archivo no contiene datos de imagen, solamente habrá una cabecera presente. Si se requiere información adicional que no cabe en la cabecera, un pie (footer) usualmente también estará presente:

Cabecera
Datos de Mapa de Bits
Pie

Un archivo de imagen puede almacenar una paleta en la cabecera, pero es más probable que esta aparezca inmediatamente después de la cabecera:

Cabecera
Paleta
Datos de Mapa de Bits
Pie

Una paleta también puede aparecer inmediatamente después de los datos de imagen, como un pie, o estar almacenada en el pie mismo:

Cabecera
Datos de Mapa de Bits
Paleta

Las tablas de scan lines y las tablas de corrección de color también pueden aparecer después de la cabecera y antes o después de los datos de imagen:

Cabecera
Paleta
Tabla de Scan Line
Tabla de Corrección de Color (aquí)
Datos de Mapa de Bits
Tabla de Corrección de Color (o aquí)
Pie

Si un formato de archivo de imagen es capaz de mantener múltiples imágenes, entonces un índice de archivo de imagen puede aparecer después de la cabecera, el cual mantiene los valores de offsets de las posiciones iniciales de las imágenes en el archivo:

Cabecera
Paleta
Índice de Mapa de Bits
Datos de Mapa de Bits 1
Datos de Mapa de Bits 2
...
Datos de Mapa de Bits n
Pie

Si la definición del formato permite que cada imagen tenga su propia paleta, lo más probable es que dicha paleta aparezca antes de los datos de imagen con los cuales está asociada:

Cabecera
Paleta
Índice de Mapa de Bits
Paleta 1
Datos de Mapa de Bits
Paleta 2
Datos de Mapa de Bits 2
...
Paleta n
Datos de Mapa de Bits n
Pie

Ahora estudiaremos las partes de un archivo de mapa de bits pieza por pieza.



Cabecera

La cabecera es una sección es una sección de datos en formato binario o ASCII que normalmente se encuentra al inicio del archivo, la cual contiene información sobre los datos de mapa de bits ubicados en otro lugar del archivo. Todos los archivos de mapa de bits tienen algún tipo de cabecera, aunque el formato de la cabecera y la información almacenada en ella varían considerablemente entre un formato y otro. Típicamente, una cabecera de mapa de bits está compuesta de campos fijos. Ninguno de estos campos es absolutamente necesario, ni se encuentra en todos los formatos, pero esta lista es típica de aquellos formatos en amplio uso hoy en día. La siguiente información es comúnmente encontrada en una cabecera de mapa de bits:

Cabecera
Paleta
Índice de Mapa de Bits
Paleta 1
Identificador de Archivo
Versión de Archivo
Número de Líneas por Imagen
Número de Pixeles por Línea
Número de Bits por Pixel
Número de Planos de Color
Tipo de Compresión
Origen X de la Imagen
Origen Y de la Imagen
Descripción de Texto
Espacio No Utilizado

Más adelante en este capítulo, presentaremos ejemplos de cabeceras de varios formatos reales, que contienen campos similares a los presentados antes.

Identificador de Archivo

Una cabecera usualmente comienza con algún tipo de valor de identificación único llamado identificador de archivo, ID de archivo, o valor de ID. Su propósito es permitirle a una aplicación de software determinar el formato del archivo gráfico particular que se está accediendo.

Los valores de ID a menudo son valores mágicos en el sentido de que son asignados arbitrariamente por el creador del formato de archivo. pueden ser una serie de caracteres ASCII, tales como BM o GIF, o un valor de palabra de 2 o 4 bytes, tal como 4242h o 596aa695h, o cualquier otro patrón que tuviera sentido para el creador del formato. Se asume que el patrón es único, incluso entre plataformas, pero no siempre es el caso, como describimos en los siguientes pocos párrafos. Usualmente, si un valor en el lugar correcto en un archivo concuerda con el valor de identificación esperado, la aplicación que lee la cabecera del archivo puede asumir que el formato del archivo de imagen es conocido.

Tres circunstancias surgen, sin embargo, que hacen que esto sea menos que una regla segura y rápida. Algunos formatos omiten el identificador del archivo, comenzando con datos que pueden cambiar entre un archivo y otro. En este caso, hay una pequeña probabilidad de que los datos dupliquen accidentalmente uno de los valores mágicos de otro formato de archivo conocido por la aplicación. Afortunadamente, la probabilidad de que esto ocurra es remota.

La segunda circunstancia puede surgir cuando se crea un nuevo formato y el creador del formato accidentalmente duplica, en todo o en parte, los valores mágicos de otro formato. En caso de que esto parezca aun más improbable que la duplicación accidental, puedes estar seguro de que ya ha pasado varias veces. Probablemente la causa principal es que, históricamente, los programadores han tomado ideas de otras plataformas, seguros en la creencia de que sus esfuerzos quedarían aislados detrás de la "Muralla China" de la incompatibilidad binaria. En el pasado, la confusión de formatos con campos de ID similares raramente ocurría, y a menudo se resolvía por el contexto de cuando sucedió. Obviamente, este enfoque ingenuo por parte de los creadores de formatos ya no es una habilidad de supervivencia. En el futuro, podemos esperar más problemas de este tipo como usuarios, a través de redes de área local y a través de avances en la interconectividad regional y global, ganemos acceso a datos creados en otras plataformas.

La tercera circunstancia se da cuando un vendedor — ya sea el creador del formato o el curador del formato o un tercero— cambia, intencional o no intencionalmente, la especificación del formato, al tiempo que mantiene el valor de ID especificado en la documentación del formato. En este caso, una aplicación puede reconocer el formato, pero ser incapaz de leer algunos o todos los datos. Si la idea de un vendedor que crea cambios intencionales no documentados parece improbable, puedes estar seguro de que esto, también, ya ha pasado muchas veces. Ejemplos de esto son los formatos de archivo GIF, TIFF y TGA. En el caso de los formatos GIF y TGA, los vendedores (no necesariamente los creadores del formato) han extendido o alterado los formatos para incluir nuevos tipos de datos. En el caso de TIFF, los vendedores han creado y promulgado lo que puede describirse solamente como revisiones de conveniencia, aparentemente diseñadas para acomodar errores de programación o peculiaridades del programa de aplicación.

Versión de Archivo

Lo que le sigue al valor de identificación en la cabecera es usualmente un campo que contiene la versión del archivo. Naturalmente, versiones sucesivas de los formatos de mapa de bits pueden diferir en características tales como tamaño de la cabecera, datos de mapa de bits soportados, y capacidad de color. Una vez que se ha verificado el formato del archivo a través de su valor de ID, una aplicación típicamente examinará el valor de la versión para determinar si puede manejar los datos de imagen contenidos en el archivo.

Información de Descripción de la Imagen

A continuación vienen una serie de campos que describen a la imagen en cuestión. Como veremos, los mapas de bits están usualmente organizados ya sea física o lógicamente, en líneas de pixeles. El campo designado número de líneas por imagen, también llamado la longitud de imagen, altura de imagen, o número de scan lines, contiene un valor que corresponde al número de líneas que conforman los datos de mapa de bits en cuestión. El número de pixeles por línea, también llamados la anchura de imagen o anchura de scanline, indica el número de pixeles almacenados en cada línea.

El número de bits por pixel indica el tamaño de los datos necesario para describir cada pixel por plano de color. Este también puede almacenarse como el número de bytes por pixel, y es más apropiadamente llamado la profundidad de pixel. Olvidar la interpretación exacta de este campo cuando se programa un lector de formato es una fuente común de error. Si los datos de mapa de bits están almacenados en una serie de planos, el número de planos de color indica el número de planos usados. A menudo este valor es 1 por defecto. Hay una tendencia en aumento de almacenar mapas de bits en formato de un único plano, pero los formatos de múltiples planos siguen siendo soportados para soportar hardware especial y modelos de color alternos.

El número de bits en una línea de la imagen puede calcularse al multiplicar los valores del número de bits por pixel, número de pixeles por línea, y número de planos de color. Podemos determinar el número de bytes por scanline al dividir entonces el producto resultante entre 8. Nota que no hay nada que obligue a que el número de bits por pixel sea un número integral de bytes de 8 bits.

Tipo de Compresión

Si el formato soporta algún tipo de codificación diseñado para reducir el tamaño de los datos de mapa de bits, entonces se encontrará un campo de tipo de compresión en la cabecera. Algunos formatos soportan múltiples tipos de compresión, incluyendo datos crudos o descomprimidos. Algunas revisiones de formato consisten principalmente de adiciones o cambios al esquema de compresión usado. La compresión de datos es un campo activo, y nuevos tipos de compresión que se acomodan a los avances en la tecnología aparecen con cierta regularidad. Los TIFF son uno de los formatos comunes que ha exhibido este patrón en el pasado.

Para más información sobre la compresión, mira el Capítulo 9, Compresión de Datos.

Orígenes x y y

El origen x de la imagen y el origen y de la imagen especifican un par de coordenadas que indican en dónde comienza la imagen en el dispositivo de salida. El par de origen más común es 0,0, el cual pone una esquina de la imagen en el punto de origen del dispositivo. Cambiar estos valores normalmente provoca que la imagen sea desplegada en una ubicación diferente cuando es renderizada.

La mayoría de formatos de mapa de bits fueron diseñados con ciertas suposiciones en mente sobre el dispositivo de salida, y así, puede decirse que modelan ya sea un dispositivo real o virtual que tiene una característica llamada superficie de dibujado. La superficie de dibujado tiene un origen implícito, el cual define el punto inicial de la imagen, y una orientación implícita, la cual define la dirección en la que se dibujan líneas sucesivas a medida que se renderiza la imagen de salida. Varios formatos y dispositivos de salida varían en el posicionamiento del punto de origen y la dirección de orientación. Muchos ubican el origen en la esquina superior izquierda de la superficie de salida, aunque también puede aparecer en el centro, o en la esquina inferior izquierda. Otros, aunque esto es mucho menos común, lo ubican en la esquina inferior o superior derecha.

A menudo se dice que los modelos de orientación con el origen en la esquina superior izquierda han sido creados para soportar el hardware, y puede haber alguna justificación histórica y del mundo real para esto. La gente con bases de conocimiento de matemática y de las ciencias naturales, sin embargo, están acostumbrados a tener el origen en la esquina inferior izquerda o en el centro de la superficie de dibujado. Puede que te encuentres adivinando la base de conocimento del creador del formato basado en el origen y orientación implícitos encontrados en el formato. Algunos formatos incluyen provisiones para la especificación del origen y la orientación.

Una imagen desplegada por una aplicación que incorpora una suposición incorrecta sobre el punto de origen o la orientación, puede aparecer cabeza abajo o al revés, o puede estar horizontalmente desplazada en una fracción de la anchura de la superficie de dibujado en el dispositivo de salida.

A veces la cabecera contendrá un campo de descripción de texto, el cual es una sección de comentarios que consisten de datos ASCII que describen el nombre de la imagen, el nombre del archivo de imagen, el nombre de la persona que creó la imagen, o la aplicación de software usada para crearla. Este campo puede contener datos ASCII de 7 bits, para portabilidad de la información de la cabecera entre plataformas.

Espacio Sin Utilizar

Al final de la cabecera puede haber un campo sin utilizar, al que se refiere a menudo por el nombre de relleno (padding), filler, espacio reservado o campos reservados. Los campos reservados no contienen datos, no están documentados y carecen de estructura, y esencialmente actúan como marcadores de posición (placeholders). Todo lo que sabemos de ellos son su tamaño y posición en la cabecera. De esta forma, si el formato se altera en alguna fecha posterior para incorporar nuevos datos, el espacio reservado puede usarse para describir el formato o ubicación de estos datos al tiempo que se mantiene la compatibilidad anterior con programas que soportan versiones más antiguas del formato. Este es un método común usado para minimizar problemas de versión — crear una versión inicial basada en una cabecera fija sustancialmente más grande de lo necesario. Nuevos campos pueden entonces agregarse a áreas reservadas de la cabecera en revisiones subsecuentes del formato sin alterar el tamaño de la cabecera.

A menudo las cabeceras de formato se rellenan intencionalmente alineadas a 128, 256 o 512 bytes. Esto tiene algunas implicaciones de desempeño, particularmente en sistemas más antiguos, y está diseñado para acomodarse a tamaños comunes de búferes de lectura y escritura. El relleno puede aparecer después de los campos documentados al final de la cabecera, y a veces esto es una indicación de que el creador del formato tenía en mente asuntos de desempeño y cacheo cuando el formato fue creado.

Los campos reservados a veces son solo características que han sido dejadas como resultado de versiones funcionales más antiguas del formato, congeladas de forma no intencional en su lugar cuando el formato se publicó. Un fabricante normalmente cambiará o extenderá el formato del archivo solo bajo coacción, o como una respuesta natural a la presión del mercado típicamente provocada por un avance no anticipado en la tecnología. De cualquier manera, la actualización casi nunca es planeada. Esto usualmente significa que existe una cantidad mínima de esfuerzo para acoplar nuevos datos en formatos antiguos. A menudo el primer elemento sacrificado en el proceso es la compatibilidad completa con las versiones anteriores del formato.



Ejemplos de Cabeceras de Mapa de Bits

Para darte una idea de qué esperar cuando examines las cabeceras de los mapas de bits, estudiaremos tres típicas de estas. Comenzaremos con una de las menos complejas (Mapa de Bits de Microsoft Windows), y procederemos a examinar otras dos que son más complejas (Sun Raster y rastro Kofax).

Para hacer esto, proveemos una estructura de datos de C, la cual ofrece una idea del tamaño y la posición relativa de cada campo en las cabeceras.

Ejemplo 1: Cabecera de Versión 1.0 de Mapa de Bits de Microsoft Windows

//
// Estructura de cabecera para el Formato MS Windows 1.x Bitmap
//    un BYTE es un unsigned char
//    un WORD es un unsigned short int (16 bits)
//
typedef struct _WinHeader1x
{
//
//  Tipo    Nombre      Offset   Comentario
//
	WORD    Type;       /* 00h   Identificador de Tipo de Archivo (siempre 0)  */
	WORD    Width;      /* 02h   Anchura el Mapa de Bits en Pixeles            */
	WORD    Height;     /* 04h   Altura del Mapa de Bits en Scan-lines         */
	WORD    Width;      /* 06h   Anchura del Mapa de Bits en Bytes             */
	BYTE    Planes;     /* 08h   Número de Planos de Color                     */
	BYTE    BitsPixel;  /* 09h   Número de Bits Por Pixel                      */
} OLDWINHEAD;

Como puedes ver por los comentarios, esta cabecera particular contiene un valor de identificación de archivo, la anchura y longitud de la imagen, la anchura de una única línea de la imagen (en bytes), el número de planos de color, y el número de bits por pixel. Esta información está cerca del mínimo absoluto requerido para describir una imagen de mapa de bits para que pueda leerse y renderizarse en un entorno arbitrario.

Nota que la cabecera del Mapa de Bits de Microsoft Windows 1.x no contiene información sobre color o compresión de datos de imagen. Un formato de imagen más avanzado tendrá provisiones tanto para información de color y al menos un esquema de compresión simple. Un ejemplo de una cabecera más elaborada es la encontrada en el formato de archivo de imagen Sun Raster mostrado en el siguiente ejemplo:

Ejemplo 2: Cabecera de Formato de Sun Raster

//
// Estructura de cabecera para el Formato de Imagen Sun Raster
//  un WORD aquí es un unsigned long int (32 bits)
//
typedef struct _SunRasterHead
{
//
//  Tipo   Nombre      Offset   Comentario
//
	WORD   Magic;      /* 00h   Número Mágico (59a66a95h)                    */
	WORD   Width;      /* 04h   Anchura de Imagen en Pixeles                 */
	WORD   Height;     /* 08h   Altura de la Imagen en Pixeles               */
	WORD   Depth;      /* 0Ch   Número de Bits Por Pixel                     */
	WORD   Length;     /* 10h   Longitud de la Imagen en Bytes               */
	WORD   Type;       /* 14h   Tipo de Codificación del Formato de Archivo  */
	WORD   MapType;    /* 18h   Tipo de Mapa de Color                        */
	WORD   MapLength;  /* 1Ch   Longitud del Mapa de Color en Bytes          */
} SUNRASHEAD;

La cabecera Sun Raster contiene información similar a la del mapa de bits de Windows 1.x ilustrada anteriormente. Pero nota que también contiene campos para el método de codificación de datos y el tipo y tamaño del mapa de color o paleta asociado con los datos de mapa de bits.

Ninguna de las dos cabeceras mencionadas anteriormente contiene un campo de descripción de texto. Una cabecera que sí lo contiene es la asociada con el Formato de Imagen Kofax mostrado en el Ejemplo 3.

Ejemplo 3: Cabecera de Formato Kofax Raster

//
//  Estructura de cabecera para el Formato de Archivo Kofax Raster
//    un LONG es un signed long int (32 bits)
//    un SHORT es un signed short int (16 bits)
//
typedef struct _KofaxHeader
{
//
//  Tipo    Nombre           Offset   Comentario
//
	LONG    Magic;           /* 00h   Número Mágico (68464B2Eh)                 */
	SHORT   HeaderSize;      /* 04h   Tamaño de Cabecera                        */
	SHORT   HeaderVersion;   /* 06h   Número de Versión de Cabecera             */
	LONG    ImageId;         /* 0Ah   Número de Identificación de Imagen        */
	SHORT   Width;           /* 0Ch   Anchura de Imagen en Bytes                */
	SHORT   Length;          /* 0Eh   Longitud de Imagen en Scan-lines          */
	SHORT   Format;          /* 10h   Codificación de Datos de Imagen           */
	CHAR    Bitsex;          /* 11h   No Cero si Bitsex Está Revertido          */
	CHAR    Color;           /* 12h   No Cero si el Color Está Invertido        */
	SHORT   Xres;            /* 14h   Puntos Horizontales Por Pulgada           */
	SHORT   Yres;            /* 16h   Puntos Verticales Por Pulgada             */
	CHAR    Planes;          /* 18h   Número de Planos                          */
	CHAR    BitsPerPixel;    /* 19h   Número de Bits Por Pixel                  */
	SHORT   PaperSize;       /* 1Ah   Tamaño Original de Papel                  */
	CHAR    Reserved1[20];   /* 1Ch   Campo Reservado de 20 Bytes               */
	LONG    Dcreated;        /* 30h   Fecha de Creación                         */
	LONG    Dmodified;       /* 34h   Fecha de Modificación                     */
	LONG    Daccessed;       /* 38h   Fecha de Último Acceso                    */
	CHAR    Reserved2[4];    /* 3Ch   Campo Reservado de 4 Bytes                */
	LONG    Ioffset;         /* 40h   Offset de Info-Texto Índice               */
	LONG    Ilength;         /* 44h   Longitud de Info-Texto Índice             */
	LONG    Coffset;         /* 48h   Offset de Comentario de Texto             */
	LONG    Clength;         /* 4Ch   Longitud de Comentario de Texto en Bytes  */
	LONG    Uoffset;         /* 50h   Offset de Datos de Usuario                */
	LONG    Ulength;         /* 54h   Longitud de Datos de Usuario en Bytes     */
	LONG    Doffset;         /* 58h   Offset de Datos de Imagen                 */
	LONG    Dlength;         /* 5Ch   Longitud de Datos de Imagen en Bytes      */
	CHAR    Reserved3[32];   /* 60h   Campo Reservado de 32 Bytes               */
} KFXHEAD;

Nota que la cabecera Kofax es considerablemente más grande que las cabeceras de Mapa de Bits de Windows o del rastro Sun. Se incluyen campos que describen la resolución horizontal y vertical, tamaño de papel del sujeto de imagen, valores de desplazamiento (offset) de diferentes tipos de datos almacenados en el archivo, y la hora y fecha en que la imagen fue creada, modificada, y accedida por última vez.

Nota también la aparición de varios campos marcados como reservados. La cabecera del formato Kofax está rellenada intencionalmente alineada a 128 bytes para acomodarse a tamaños comunes de búferes de lectura y escritura. Usa solo 72 bytes de la cabecera en la revisión presentada aquí, pero está rellenada a 128 bytes. La especificación del formato Kofax promete que los primeros 128 bytes de cada archivo de imagen Kofax serán cabecera de archivo, sin importar revisiones futuras. De esta manera las aplicaciones son libres de ignorar los datos reservados, y el formato presumiblemente está diseñado para permitir esto sin sanciones graves. Mira la discusión general de campos reservados en la sección llamada "Espacio Sin Utilizar" más atrás en este capítulo.

Optimizando la Lectura de Cabecera

La velocidad de lectura de cabecera puede optimizarse al observar las maneras en que tu aplicación usa los datos, porque leer los datos de cabecera usualmente puede efectuarse en varias maneras. Si solamente se necesitan valores selectos de la cabecera, la aplicación puede calcular el offset de los datos desde una marca clave tal como el inicio del archivo. La aplicación puede entonces desplazarse directamente al valor de datos requerido y leerlo. Los valores de offset que aparecen en los comentarios en los ejemplos de cabecera anteriores pueden usarse como argumentos de offset para la función de desplazamiento utilizada.

Si la mayoría de los datos contenidos en la cabecera se necesitan por la aplicación, entonces puede que sea más conveniente leer la cabecera entera en un búfer o estructura de datos previamente reservada. Esto puede llevarse a cabo rápidamente, aprovechando la ventaja de cualquier eficiencia provista por lecturas integrales potencia de dos, como se mencionó antes. Todos los datos de la cabecera estarán disponibles en memoria y pueden cachearse para ser usados cuando se necesiten. Un problema, sin embargo, ocurre cuando el orden de los bytes del archivo es diferente al orden de los bytes nativo del sistema en el que el archivo está siendo leído. La mayoría de funciones de lectura de bloques, por ejemplo, no están diseñadas para ofrecer conversión automática de datos. Otro problema puede surgir cuando las estructuras de datos se rellenan por el compilador o el entorno de ejecución para propósitos de alineación de los miembros de datos. Estos problemas y otros se discuten en mayor detalle en el Capítulo 6, Dependencias de la Plataforma.



Datos de Mapa de Bits

Los datos de mapa de bits en cuestión usualmente conforman el grueso de un archivo de formato de mapa de bits. En la siguiente discusión, asumiremos que has leído el Capítulo 2, Fundamentos de Gráficos de Computadora, y que tienes una comprensión sobre los datos de pixel y temas relacionados tales como el color.

En muchos formatos de archivo de mapa de bits, los datos de mapa de bits en cuestión se encuentran inmediatamente después del final de la cabecera de archivo. Puede que se encuentren en otro lugar del archivo, no obstante, para acomodar una paleta u otra estructura de datos que también pueda estar presente. Si este es el caso, aparecerá un valor de offset en la cabecera o en la documentación, que indica dónde encontrar el inicio de los datos de mapa de bits en el archivo.

Algo que puede que notes mientras inspeccionas las especificaciones de formato de archivo es la ausencia relativa de información que explica la disposición de los datos de mapa de bits en cuestión en el archivo. Para determinar cómo están dispuestos los datos, usualmente tienes que descubrirlo a partir de información relacionada a la estructura del archivo.

Afortunadamente, la estructuración de los datos de mapa de bits dentro de la mayoría de archivos es sencilla y fácilmente deducible. Como se mencionó antes, los datos de mapa de bits están compuestos de valores de pixeles. Los pixeles en un dispositivo de salida usualmente son dibujados en scan lines que corresponden a filas que ocupan la anchura de la superficie de salida. Este hecho usualmente se refleja en el arreglo de los datos en el archivo. Este ejercicio, de deducir el arreglo exacto de los datos en el archivo, a veces es ayudado al tener alguna idea de los dispositivos de salida que el creador tenía en mente.

Una o más scan lines combinadas forman una malla 2D de datos de pixel; por lo que podemos pensar en cada pixel en el mapa de bits como estando ubicado en una coordenada lógica específica. También se puede pensar en un mapa de bits como una secuencia de valores que mapean lógicamente datos de mapa de bits en un archivo, a una imagen en la superficie de display en un dispositivo de salida. Los datos en cuestión de un mapa de bits usualmente la parte individual más grande de cualquier archivo de formato de mapa de bits.

Cómo Se Escriben a Archivos los Datos de Mapa de Bits

Antes de que una aplicación escriba una imagen a un archivo, los datos de imagen son primero ensamblados en uno o más bloques de memoria. Estos bloques pueden estar localizados en la memoria principal de la computadora o en parte de un dispositivo de recolección de datos auxiliares. Exactamente cómo están dispuestos los datos entonces, depende de un número de factores, incluyendo la cantidad de memoria instalada, la cantidad disponible a la aplicación, y los detalles específicos de la adquisición de datos o la operación de escritura de archivo en uso. Cuando los datos de mapa de bits son finalmente escritos a un archivo, sin embargo, normalmente solo se usa uno de dos métodos de organización: datos de scan line o datos planares.

Datos de Scan-Line

El primer y más simple método, es la organización de valores de pixeles en filas o scan lines, brevemente mencionadas antes. Si consideramos que cada imagen está formada de una o más scan lines, los datos de pixel en el archivo que describen esa imagen serán una serie de conjuntos de valores, cada conjunto correspondiente a una fila de la imagen. Múltiples filas se representan por múltiples conjuntos escritos de principio a fin en el archivo. Este es el método más común para almacenar datos de imagen organizados en filas.

Si conocemos el tamaño de cada pixel en la imagen, y el número de pixeles por fila, podemos calcular el offset del inicio de cada fila en el archivo. Por ejemplo, en una imagen de 8 bits, cada valor de pixel tiene 1 byte de longitud. Si la imagen tiene una anchura de 21 pixeles, las filas en el archivo están representadas por conjuntos de valores de pixeles con 21 bytes de anchura. En este caso, las filas en el archivo comienzan en los offsets de 0, 21, 42, 63, etc. bytes desde el inicio de los datos de mapa de bits.

En algunas máquinas y en algunos formatos, sin embargo, las filas de datos de imagen deben ser ciertos múltiplos pares de bytes en longitud. Un ejemplo es la regla común que requiere que los datos de fila de mapa de bits terminen en límites de palabra larga, en donde una palabra larga tiene 4 bytes. En el ejemplo mencionado en el párrafo anterior, una imagen de 21 pixeles entonces se almacenaría en el archivo como conjuntos de valores de pixel de 24 bytes en longitud, y las filas comenzarían en el offset del archivo 0, 24, 48, 64. Los tres bytes extra por fila son relleno. En este caso particular, tres archivos de almacenamiento en el archivo son desperdiciados para cada fila, y de hecho, las imágenes que tienen 21 pixeles de anchura ocuparán el mismo espacio que imágenes de 24 pixeles de anchura. En la práctica, esta ineficiencia de almacenamiento usualmente (pero no siempre) se compensa por un aumento de velocidad ganado al abastecer las peculiaridades de la máquina cliente en cuanto a su habilidad de manipular rápidamente dos o cuatro bytes al mismo tiempo. La anchura real de la imagen siempre está disponible a la aplicación de renderización, usualmente desde la información en la cabecera del archivo.

En una imagen de 24 bits, cada pixel de la imagen corresponde a un valor de pixel de 3 bytes en el archivo. En el ejemplo que hemos estado discutiendo, una imagen de 21 pixeles requeriría un mínimo de 21 * 3 = 63 bytes de almacenamiento. Si el formato requiere que los inicios de fila estén alineados a una palabra larga (4 bytes), se requerirían 64 bytes para mantener los valores de pixeles para cada fila. Ocasionalmente, como se mencionó antes, los datos de imagen de 24 bits se almacenan como una serie de valores de pixeles de 4 bytes, y cada fila de la imagen entonces requeriría 21 * 4 = 84 bytes. Almacenar datos de 24 bits como valores de 4 bytes tiene la ventaja de estar siempre alineado a una palabra larga (4 bytes), y como dijimos esto puede tener sentido en ciertas máquinas.

En una imagen de 4 bits, cada pixel corresponde a la mitad de un byte, y los datos usualmente se almacenan dos pixeles por byte, aunque almacenar los datos como valores de pixel de 1 byte haría que los datos sean más fácil de leer y, de hecho, no es algo desconocido.

La Figura 3-1 ilustra la organización de los datos de pixel en scan lines.

Figura 3-1: Organización de datos de pixel en scan lines (imagen de 24 bits)
FIGURA 3-1: Organización de datos de pixel en scan lines (imagen de 24 bits)

Datos Planares

El segundo método de organización de datos de pixeles involucra la separación de datos de imagen en dos o más planos. Los archivos en los que los datos se organizan de esta manera son llamados archivos planares. Usaremos el término imagen compuesta para referirnos a una imagen con muchos colores (por ejemplo, no monocromática, no de escala de grises, y no de un único color). Bajo esta definición, la mayoría de imágenes coloreadas normalmente con las que estás familiarizado, son imágenes compuestas (composite images).

Una imagen compuesta, entonces, puede representarse por tres bloques de datos de mapa de bits, cada bloque conteniendo solo uno de los colores componentes que conforman la imagen. Construir cada bloque es semejante al proceso fotográfico de hacer una separación — usar filtros para descomponer una imagen a color en un conjunto de componentes de color, usualmente tres. La fotografía original puede reconstruirse al combinar las tres separaciones. Cada bloque se compone de filas dispuestas de extremo a extremo, como en el método más simple explicado antes; en este caso, ahora se necesita más de un bloque para reconstruir la imagen. Los bloques pueden estar almacenados consecutivamente o pueden estar físicamente separados entre sí en el archivo.

Los datos en formato planar usualmente son un signo de que el diseñador del formato tenía algún dispositivo de display particular en mente, uno que construye pixeles de color compuesto enrutados a través de hardware diseñado para manejar un color a la vez. Por razones de eficiencia, los datos en formato planar usualmente se leen un plano a la vez en bloques, aunque una aplicación puede elegir ensamblar laboriosamente pixeles compuestos al leer datos del lugar apropiado en cada plano secuencialmente.

Como un ejemplo, una imagen de 24 bits de dos filas por tres columnas, puede representarse en formato RGB como seis valores de pixeles:

(00, 01, 02) (03, 04, 05) (06, 07, 08)
(09, 10, 11) (12, 13, 14) (15, 16, 17)


pero luego escribirse al archivo en formato planar como:

(00) (03) (06)
(09) (12) (15)
plano rojo
(01) (04) (07)
(10) (13) (16)
plano verde
(02) (05) (08)
(11) (14) (17)
plano azul


Nota que se están escribiendo exactamente los mismos datos; solo que arreglados de forma diferente. En el primer caso, una imagen que consiste de seis pixeles de 24 bits está almacenada como seis valores de de pixel de 3 bytes arreglados en un único plano. Con el segundo método, que es planar, la misma imagen se almacena como 18 valores de pixel de 1 byte arreglados en tres planos, cada plano correspondiente a información de rojo, verde y azul, respectivamente. Cada método ocupa exactamente la misma cantidad de espacio, 18 bytes, al menos en este ejemplo.

Es bastante seguro afirmar que la mayoría de archivos de mapa de bits están almacenados en formato no planar. Soportar hardware planar, entonces, usualmente significa desensamblar los datos de pixel y crear múltiples planos de color en memoria, los cuales son luego presentados a la subrutina de renderización planar, o al hardware planar.

Puede que los archivos planares necesiten ensamblarse en un tercer búfer o, como se mencionó antes, crearse laboriosamente (por la rutina que da servicio al dispositivo de salida) un pixel a la vez.

La Figura 3-2 ilustra la organización de datos de pixel en planos de color.

Figura 3-2: Organización de datos de pixel en planos de color
FIGURA 3-2: Organización de datos de pixel en planos de color

Diferentes Enfoques a la Organización de Datos de Mapa de Bits

Normalmente, consideramos que una imágen está conformada de un número de filas, cada una de un cierto número de pixeles de longitud. Los datos de pixeles que representan la imagen pueden almacenarse en el archivo en tres formas: como datos contiguos, como tiras (strips) o como azulejos (tiles). La Figura 3-3 ilustra estas tres representaciones.

Figura 3-3: Ejemplos de organización de datos de mapa de bits (scan lines contiguas, tiras, y azulejos)
FIGURA 3-3: Ejemplos de organización de datos de mapa de bits (scan lines contiguas, tiras, y azulejos)

Datos Contiguos

El método más simple de organización de filas es donde todos los datos de imagen están almacenados de manera contigua en el archivo, una fila siguiendo a la anterior. Para recuperar los datos, lees las filas en el orden del archivo, lo cual entrega las filas en el orden en que están escritas. Los datos en este esquema organizacional se almacenan en el archivo, de forma equivalente a un arreglo 2D. Puedes indexar los datos en el archivo al conocer la anchura de la fila en pixeles y el formato de almacenamiento y el tamaño de los valores de pixeles. Los datos almacenados de manera contigua de esta manera pueden leerse rápidamente, en porciones grandes, y ensamblados en memoria muy fácilmente.

Tiras

En el segundo método de organización de archivos, las imágenes están almacenadas en tiras, las cuales también consisten de filas almacenadas contiguamente. La imagen total, sin embargo, está representada por más de una tira, y las tiras individuales pueden estar ampliamente separadas en el archivo. Las tiras dividen la imagen en un número de segmentos, los cuales son siempre tan anchos como la imagen original.

Las tiras hacen que sea más fácil manejar los datos de imagen con memoria limtada. Una imagen con un tamaño de 1024 filas, por ejemplo, puede almacenarse en el archivo como ocho tiras, cada tira conteniendo 128 filas. Arreglar un archivo en tiras facilita el buffering. Si esto no es obvio, considera una imagen descomprimida de 8 bits con un tamaño de 1024 filas y 10,000 pixeles de ancho, que contiene 10 megabytes de datos de pixel. Incluso dividiendo los datos en ocho tiras de 128 tiras, deja a la aplicación con el trabajo de manejar 1.25 megabytes de datos por tira, una tarea pesada incluso para una máquina con mucha memoria y un disco rápido. Dividir los datos en 313 tiras, sin embargo, deja cada tira con un tamaño que puede leerse y ponerse en un búfer rápidamente, por máquinas capaces de leer solo 32K de datos por cada lectura de archivo.

Las tiras también entran en juego cuando los datos de pixel están almacenados en un formato comprimido o codificado en el archivo. En este caso, una aplicación primero debe leer los datos comprimidos en un búfer, y luego descomprimir o decodificar los datos en otro búfer del mismo tamaño que, o más grande que, el primero. Arreglar la compresión en base a tiras facilita grandemente la tarea del lector del archivo, el cual solo necesita manejar una tira a la vez.

Encontrarás que las tiras son a menudo evidencia de que el creador del formato de archivo ha pensado en las posibles limitaciones de las posibles plataformas de destino que son soportadas y ha querido que no se limite el tamaño de las imágenes que pueden manejarse por el formato. Los formatos de archivo de imagen que permiten o exigen que los datos sean almacenados en tiras, usualmente proveen el almacenamiento de información en la cabecera del archivo tal como el número de tiras de datos, el tamaño de cada tira, y la posición de offset de cada tira dentro del archivo.

Azulejos

Un tercer método de organización de datos de mapa de bits son los azulejos. Estos son similares a las tiras en que cada uno es una delineación de un área rectangular de una imagen. Sin embargo, a diferencia de las tiras, las cuales tienen siempre la anchura de la imagen, los azulejos pueden tener absolutamente cualquier anchura, desde un pixel individual hasta la imagen entera. Así, en un sentido, una imagen contigua es un gran azulejo. En la práctica, sin embargo, los azulejos están arreglados de tal forma que los datos de pixel que corresponden a cada uno tienen entre 4Kb y 64Kb de tamaño, y usualmente con una altura y anchura divisible entre 16. Estos límites ayudan a incrementar la eficiencia con la que los datos pueden ponerse en un búfer y ser decodificados.

Cuando una imagen se divide en azulejos, el caso es que generalmente todos son del mismo tamaño, que la imagen entera está dividida, que los azulejos no se traslapan, y que los azulejos están todos codificados con el mismo esquema de codificación. Una excepción es el formato CALS Raster Tipo II, el cual permite que los datos de imagen estén compuestos tanto de azulejos codificados y decodificados. Los azulejos se dejan sin codificar cuando dicha codificación provocaría que los datos aumenten de tamaño (compresión negativa) o cuando se requeriría una cantidad no razonable de tiempo para codificar el archivo.

Dividir una imagen en azulejos también permite aplicar diferentes esquemas de compresión a diferentes partes de una imagen para lograr una tasa de compresión óptima. Por ejemplo, una porción de una imagen (una porción muy variada) podría dividirse en azulejos que estén comprimidos usando JPEG, mientras que otra porción de la misma imagen (una porción que contiene solo uno o dos colores) podría almacenarse como azulejos que están codificados con run-length. En este caso, los azulejos en la imagen no tendrían todos un tamaño uniforme; los más pequeños tendrían solo unos pocos pixeles, y los más grandes tendrían cientos o miles de pixeles en uno de sus lados.

Dividir en azulejos a veces permite decodificación y descompresión más rápidas de imágenes grandes de lo que sería posible si los datos de pixeles estuvieran organizados como líneas o tiras. Ya que los azulejos pueden codificarse individualmente, los formatos de archivo que permiten el uso de estos contendrán la cantidad de azulejos, el tamaño, y la información de offset en las especificaciones de la cabecera. Usando esta información, un lector que necesite desplegar solamente la esquina inferior derecha de una imagen muy grande, solo tendría que leer los azulejos para esa área de la imagen; no tendría que leer todos los datos de imagen que estaban almacenados antes de dicha área.

Ciertos esquemas de compresión más recientes orientados a azulejos, tales como JPEG, naturalmente funcionan mejor con los formatos de archivo capaces de soportar la división por azulejos. Un buen ejemplo de esto es la incorporación de JPEG en versiones más recientes del formato de imagen TIFF. Para más información sobre el uso de azulejos, mira el artículo sobre el formato de archivo TIFF.

Paleta

Muchos formatos de archivo de mapa de bits contienen una paleta de colores. Para una discusión sobre paletas de diferentes tipos, mira el Capítulo 2.



Pie (Footer)

El pie, a veces llamado el trailer, es una estructura de datos similar a una cabecera y es a menudo una adición a la cabecera original, pero adjuntada al final de un archivo. Un pie usualmente se agrega cuando el formato de archivo se actualiza para acomodar nuevos tipos de datos y ya no es conveniente agregar o cambiar información en la cabecera. Es principalmente resultado de un deseo de mantener la compatibilidad con versiones anteriores del formato. Un ejemplo de esto es el formato TGA, versiones posteriores del cual contienen una cabecera que permite a las aplicaciones identificar las diferentes versiones de su formato y acceder características especiales disponibles solo en la versión más reciente del formato.

Ya que por definición aparece después de los datos de imagen, los cuales son de longitud variable, un pie nunca se encuentra en una posición de offset fija desde el inicio de una imagen, a menos que los datos de imagen sean siempre del mismo tamaño. Está, sin embargo, usualmente ubicada en una posición especificada desde el final de un archivo de imagen. Como las cabeceras, los pies usualmente tienen un tamaño fijo. El valor de offset de la cabecera puede estar presente también en la información de la cabecera, siempre que hubiera espacio reservado o relleno disponible en la cabecera. También como una cabecera, una cabecera puede contener un campo de identificación o número mágico el cual puede usarse por una aplicación de renderización para diferenciarlo de otras estructuras de datos en el archivo.



Otras Estructuras de Datos de Archivos de Mapa de Bits

Además de las cabeceras, los pies y las paletas, los archivos de mapa de bits pueden contener estructuras de datos adicionales, las cuales se agregan usualmente para ayudar a la manipulación de los datos de imagen por parte de la aplicación de renderización.

Un formato de archivo que permite más de una imagen en el archivo, necesita ofrecer algún método de identificación para el inicio de cada imagen. Así, una tabla de offset de imagen, a veces llamada índice de archivo de imagen o tabla de páginas, puede usarse para almacenar los valores de offset del inicio de cada imagen desde el inicio del archivo.

Una tabla de scan-lines puede proveerse para localizar el inicio de cada scan line de la imagen en los datos de pixeles. Esto puede ser útil si los datos de imagen están comprimidos y los datos de pixeles que corresponden a scan lines individuales deben accederse aleatoriamente; los pixeles en los datos de imagen no pueden contarse hasta que los datos de imagen sean decodificados. Las tablas de scan lines contienen una entrada por scan line de la imagen. Variantes de esta idea incluyen tablas de localización de tiras (una entrada por grupo de scan lines) y localización de tablas de tiras (una entrada por cada sub-área rectangular de la imagen).



Otras Características de Archivos de Mapa de Bits

Varios formatos incorporan estructuras de datos únicas o inusuales en su diseño. Esto es usualmente con el fin de llevar a cabo el propósito específico del formato o para crear tanta generalidad como sea posible.

Un formato de archivo común que viene a la mente bajo la definicion de "inusual" es TIFF. TIFF contiene una cabecera rudimentaria, pero almacena muchos de sus datos en una serie de etiquetas llamadas Directorios de Imagen de Archivo, los cuales no son fijos ni en tamaño ni en posición. En su lugar, son como una estructura de datos de lista en memoria en que están enlazadas por una serie de valores de offsets de archivo. Los datos pueden encontrarse al desplazarse al siguiente offset desde la posición actual. Si bien este arreglo puede llevar a confusiones (y de hecho TIFF muchas veces ha sido llamado un formato de "solo lectura"), le permite al programador construir una estructura similar a una cabecera que contiene absolutamente cualquier información, agregando así a su versatilidad.

Características inusuales o únicas de otros formatos incluyen el almacenamiento de datos de imagen e información de paleta en archivos separados (los archivos Dr. Halo CUT y PAL, por ejemplo) y el almacenamiento de mapas de bits monocromáticos como bloques de unos y ceros en formato ASCII (como en el formato PBM), diseñados tal vez con la portabilidad interplataforma en mente.



Pros y Contras de los Formatos de Archivo de Mapa de Bits

Los archivos de mapa de bits son especialmente adecuados para almacenar imágenes del mundo real; imágenes complejas pueden rasterizarse en conjunto con video, escaneo y equipo fotográfico, y almacenarse en formato de mapa de bits.

Las ventajas de los archivos de mapa de bits incluyen lo siguiente:

Los archivos de mapa de bits, sin embargo, tienen inconvenientes:

 n0HCo(-JT' &N5i5詗7c'wOưQ|c!@|%A"@[0d1̖Y'zb,5͔Ow( 2+FcI`Fqlzv(7LX rfYvNzzYOA#.E-94Zn!S 52@K9my;.}U݀r&jn2WWHJ`Q}u_tro {rWL;=_ؼ