LECTURA DE ARCHIVOS BMP EN LENGUAJE C

RESUMEN:

Este documento explica de manera sencilla como se guarda la información dentro de un archivo BMP. Se explican el formato del encabezado, la paleta de colores y como se guarda la imagen. Al final se muestra un pequeño en lenguaje C de como puede leer la información de un archivo BMP.

ESTRUCTURA DE UN ARCHIVO BMP

La descripción que se hará a continuación será con respecto a la forma como Windows almacena los mapas de bits.

FORMATO DE LOS MAPAS DE BITS:

Los mapas de bits son almacenados en un formato independiente al tipo de dispositivo en donde se presentarán. Esto se debe a estos archivos especifican el color de cada pixel independiente al método usado para representarlos y La extensión utilizada por defecto es .BMP.

ESTRUCTURA DE UN MAPA DE BITS:

Un archivo de bitmap está dividido en secciones cuyos nombres son los siguientes:

BITMAPFILEHEADER bmfh;
BITMAPINFOHEADER bmih;
RGBQUAD aColors[];
BYTE aBitmapBits[];

BITMAPFILEHEADER: Contiene información sobre el tipo y tamaño del archivo.

BITMAPINFOHEADER: Especifica dimensiones,tipo de compresión y formato de color para el mapa de bits.

RGBQUAD: Contiene un arreglo de colores ( R,G,B,QUAD ) utilizado para representar cada color que puede contener la imagen. Las imágenes de 24 bits no poseen esta estructura debido a que cada pixel se representan con 24 bits directamente en la imagen.

Con respecto al número de bits por pixel este valor se guarda en una variable llamada biBitCount dentro del BITMAPINFOHEADER y sus valores pueden ser los siguientes:

1 Significa que tenemos una imagen monocromo, es decir que la paleta de colores tiene 2 entradas aunque estas no necesariamente son blanco y negro, además cada pixel se representa con 1 bit.
4 Cada bitmap tiene una paleta de colores con un máximo de 16 entradas y cada pixel se reprsenta con 4 bits .
8 Cada bitmap tiene una paleta de colores con un máximo de 256 colores y cada pixel se representa con un byte.
24 En estas imagenes tienen un máximo de 2^24 colores y cada pixel es representado por 3 bytes que corresponden a las distintas tonalidades de rojo,verde,azul.

ESTRUCTURA DE BITMAPFILEHEADER

typedef struct tagBITMAPFILEHEADER { /* bmfh */
UINT bfType;
DWORD bfSize;
UINT bfReserved1;
UINT bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER;

Este encabezado contiene la siguiente información:

bfType: Especifica el tipo de archivo su valor debe ser BM.
bfSize: Especifica el tamaño del archivo en bytes.
BfReserved1: Su valor debe ser 0.
bfReserved2: Su valor debe ser 0.
bfOffbits: Especifica en bytes el desplazamiento desde la estructura
BITMAPFILEHEADER hasta los datos del archivo.

ESTRUCTURA BITMAPINFOHEADER

typedef struct tagBITMAPINFOHEADER { /* bmih */
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER;

Esta parte de el encabezado contiene la siguiente información:

biSize: Especifica el número bytes requeridos por la estructura BITMAPINFOHEADER.
biWidth: Especifica elancho de la imagen en Pixeles.
biHeight: Especifica lo largo de la imagen en Pixeles.
biPlanes: Especifica el número de planos para el dispositivo destino. Su valor debe ser 1.
biBitCount: Especifica el número de bits por pixel. Susvalores deben ser 2,4,8,24.
biCompression: Especifica el tipo de compresión para el mapa de bits.
biSizeImage: Especifica el tamaño en bytes de la imagen.
biXPelsPerMeter: Especifica la resolución horizontal en pixeles por metro.
biYPelsPerMeter: Especifica la resolución vertical en pixeles por metro.
biClrUsed: Especifica el número de colores indexados en la tabla de colores y actualmente usados por el mapa de bits. En caso de que este valor sea cero se debe entender que los colores indexados serán los especificados por la variable biBitCount.
BiClrImportant: Especifica el número de colores indexados que son considerados
importantes. Si este valor es cero todos los colores son importantes.

LA ESTRUCTURA RGBQUAD

typedef struct tagRGBQUAD { /* rgbq */
BYTE rgbBlue;
BYTE rgbGreen;
BYTE rgbRed;
BYTE rgbReserved;
} RGBQUAD;

Esta estructura determina los valores de intensidad en los siguientes colores rojo,azul y verde:

rgbBlue: Especifica la intensidad del color azul (0 - 255)
rgbGreen: Especicica la intensidad del color verde (0 - 255 )
rgbRed: Especifica la intensidad del color rojo (0 - 255)
rgbReserved: Su valor debe ser 0.

A continuación se muestra un programa desarrollado por Samuel Garrido Daniel para la lectura del encabezado de un archivo BMP

1 /*Samuel Garrido Daniel
2 * 98-271
3 * Sistemas Operativos II
4 * Horario: 10-11 a.m. */
5
6 #include <stdio.h>
7 #include <fcntl.h>
8
9 struct /*BITMAPFILEHEADER*/
10 {
11 char bftype[2];
12 int bfsize;
13 short bfreserved1;
14 short bfreserved2;
15 unsigned long bfoffbits;
16 } bmfh;
17
18 struct /*BITMAPINFOHEADER*/
19 {
20 unsigned long bisize;
21 unsigned long biwidht;
22 unsigned long biheight;
23 short biplanes;
24 short bibitcount;
25 unsigned long bicompression;
26 unsigned long bisizeimage;
27 unsigned long bixpelsmeter;
28 unsigned long biypelsmeter;
29 unsigned long biclrused;
30 unsigned long biclrimportant;
31 } bmih;
32
33 void leer(char *argv2)
34 {
35 int colores,i,archivo,bx;
36 unsigned long entu;
37 archivo=open(argv2,O_RDONLY);
38 system("clear");
39 printf("---INFORMACION DE LA CABECERA DEL BMP
----------------------------------------\n");
40 printf("___________Descripcion del dato______________ VALORES EN : %s ",argv2);
41 printf("\n");
42 read(archivo,&bmfh.bftype,sizeof(bmfh.bftype));
43 printf("Tipo del archivo debe almacenar \"BM\" | Tipo : %c%c
\n",bmfh.bftype[0],bmfh.bftype[1]);
44 read(archivo,&bmfh.bfsize,sizeof(bmfh.bfsize));
45 printf("Tamaño del archivo en bytes | Tamaño : %d bytes\n",bmfh.bfsize);
46 read(archivo,&bmfh.bfreserved1,sizeof(bmfh.bfreserved1));
47 printf("Reservado, debe almacenar un 0 | Reserved1 : %i \n",bmfh.bfreserved1);
48 read(archivo,&bmfh.bfreserved2,sizeof(bmfh.bfreserved2));
49 printf("Reservado, debe almacenar un 0 | Reserved2 : %i \n",bmfh.bfreserved2);
50 read(archivo,&bmfh.bfoffbits,sizeof(bmfh.bfoffbits));
51 printf("Offset desde la estructura de cabecera a\n");
52 printf("los datos del bitmap en el archivo | Offbits : %li \n",bmfh.bfoffbits);
53 getchar();
54 printf("---INFORMACION DEL BITMAP
--------------------------------------------------\n");
55 read(archivo,&bmih.bisize,sizeof(entu));
56 printf("Tamaño de la BITMAPINFOHEADER en bytes. | Tamaño : %i
bytes\n",bmih.bisize);
57 read(archivo,&bmih.biwidht,sizeof(entu));
58 printf("Anchura del bitmap en pixeles | Ancho : %i pixeles\n",bmih.biwidht);
59 read(archivo,&bmih.biheight,sizeof(entu));
60 printf("Altura del bitmap en pixeles | Altura : %i pixeles\n",bmih.biheight);
61 read(archivo,&bmih.biplanes,sizeof(bmih.biplanes));
62 printf("Numero de Planos en el dispositivo de salida | Planos : %i \n",bmih.biplanes);
63 read(archivo,&bmih.bibitcount,sizeof(bmih.bibitcount));
64 printf("Numero de Bits por pixel (1,4,8 o 24) | Bits : %i \n",bmih.bibitcount);
65 read(archivo,&bmih.bicompression,sizeof(bmih.bicompression));
66 printf("Tipo de compresion (0,1 o 2) | Compresion : %ld \n",bmih.bicompression);
67 read(archivo,&bmih.bisizeimage,sizeof(bmih.bisizeimage));
68 printf("Tamaño de imagen en bytes, si es una imagen \n");
69 printf("sin compresion el campo puede quedar en 0: | Tamaño : %ld
bytes\n",bmih.bisizeimage);
70 read(archivo,&bmih.bixpelsmeter,sizeof(entu));
71 printf("Pixels en X por metro | Pixeles : %ld \n",bmih.bixpelsmeter);
72 read(archivo,&bmih.biypelsmeter,sizeof(entu));
73 printf("Pixels en Y por metro | Pixeles : %lu \n",bmih.biypelsmeter);
74 read(archivo,&bmih.biclrused,sizeof(entu));
75 printf("Nº de colores de la tabla de colores que son \n");
76 printf("usados en la imagen, un 0 indica que todos \n");
77 printf("los colores son usados | Nº colores : %lu \n",bmih.biclrused);
78 read(archivo,&bmih.biclrimportant,sizeof(entu));
79 printf("Nº de colores importantes para ver el bitmap | Nº colores : %i \n",bmih.biclrimportant);
80 bx=1;
81 if ( bmih.bibitcount == 24 )
82 printf ("Archivo de 24 bits no contiene PALETA ");
83 else
84 {
85 for(i=0;i<bmih.bibitcount;i++)
86 bx=bx*2;
87 colores=(bmfh.bfoffbits - 54) /4;
88 printf("Colores en Paleta = %i ",colores);
89 }
90 printf(" :) fin del programa...");
91 getchar();
92 close(archivo);
93 }
94
95 main(int arg,char *argv[])
96 {
97 system("clear");
98 if (arg!=2)
99 {
100 printf("\n\n\nPara ejecutar el programa siga la sintaxis: nombre_programa archivo.bmp\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
101 exit(0);
102 }
103 printf("\n\n Informacion del archivo .BMP : %s \n\n",argv[1]);
104 printf("\n\n\n\n\n\n\n\n\n");
105 printf(" Presione Enter para continuar...");
106 getchar();
107 system("clear");
108 leer(argv[1]);
109 }

Este código es en realidad bastante sencillo. Al principio se declaran las estructuras BITMAPFILEHEADER y BITMAPINFOHEADER del encabezado para después invocar en el programa principal una función que lee uno por uno los registros del encabezado para finalmente enviarlos a pantalla, este sencillo procedimiento le devolvera algo como esto:

---INFORMACION DE LA CABECERA DEL BMP ---------------------------------
___________Descripcion del dato______________ VALORES EN : dr_del~1.bmp
Tipo del archivo debe almacenar "BM" | Tipo : BM
Tamaño del archivo en bytes | Tamaño : 175774 bytes
Reservado, debe almacenar un 0 | Reserved1 : 0
Reservado, debe almacenar un 0 | Reserved2 : 0
Offset desde la estructura de cabecera a
los datos del bitmap en el archivo | Offbits : 54

---INFORMACION DEL BITMAP ----------------------------------------------
Tamaño de la BITMAPINFOHEADER en bytes. | Tamaño : 40 bytes
Anchura del bitmap en pixeles | Ancho : 254 pixeles
Altura del bitmap en pixeles | Altura : 230 pixeles
Numero de Planos en el dispositivo de salida | Planos : 1
Numero de Bits por pixel (1,4,8 o 24) | Bits : 24
Tipo de compresion (0,1 o 2) | Compresion : 0
Tamaño de imagen en bytes, si es una imagen
sin compresion el campo puede quedar en 0: | Tamaño : 175720 bytes
Pixels en X por metro | Pixeles : 3780
Pixels en Y por metro | Pixeles : 3780
Nº de colores de la tabla de colores que son
usados en la imagen, un 0 indica que todos
los colores son usados | Nº colores : 0
Nº de colores importantes para ver el bitmap | Nº colores : 0
Archivo de 24 bits no contiene PALETA :) fin del programa...