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...