 |
Bitmap Image Format
The BMP file format has been created by Microsoft
and IBM. The BMP files are the way, Windows stores bit mapped images. The BMP
image data is bit packed but every line must end on a dword boundary - if that’s
not the case, it must be padded with zeroes. BMP files are stored bottom-up,
that means that the first scan line is the bottom line.
BMP Format Contents
The following table
contains a description of the contents of the BMP file. For every field, the
file offset, the length and the contents will be given. For a more detailed
discussion, see the following chapters.
|
Offset |
Field Name |
Size |
Description |
|
0000h |
Identifier |
2 chars |
The
characters identifying the bitmap. The following entries are
possible:
‘BM’ - Windows 3.1x, 95, NT, …
‘BA’ - OS/2 Bitmap Array
‘CI’ - OS/2 Color Icon
‘CP’ - OS/2 Color Pointer
‘IC’ - OS/2 Icon
‘PT’ - OS/2 Pointer |
|
0002h |
File Size |
1 dword |
Complete
file size in bytes. |
|
0006h |
Reserved |
1 dword |
Reserved
for later use. |
|
000Ah |
Bitmap
Data Offset |
1 dword |
Offset
from beginning of file to the beginning of the bitmap data. |
|
000Eh |
Bitmap
Header Size |
1 dword |
Length of
the Bitmap Info Header used to describe the bitmap colors,
compression, … The following sizes are possible:
28h - Windows 3.1x, 95, NT, …
0Ch - OS/2 1.x
F0h - OS/2 2.x |
|
0012h |
Width |
1 dword |
Horizontal width of bitmap in pixels. |
|
0016h |
Height |
1 dword |
Vertical
height of bitmap in pixels. |
|
001Ah |
Planes |
1 word |
Number of
planes in this bitmap. |
|
001Ch |
Bits Per
Pixel |
1 word |
Bits per
pixel used to store palette entry information. This also identifies
in an indirect way the number of possible colors. Possible values
are:
1 - Monochrome bitmap
4 - 16 color bitmap
8 - 256 color bitmap
16 - 16bit (high color) bitmap
24 - 24bit (true color) bitmap
32 - 32bit (true color) bitmap |
|
001Eh |
Compression |
1 dword |
Compression specifications. The following values are possible:
0 - none (Also identified by
BI_RGB)
1 - RLE 8-bit / pixel (Also
identified by BI_RLE4)
2 - RLE 4-bit / pixel (Also
identified by BI_RLE8)
3 - Bitfields (Also
identified by BI_BITFIELDS) |
|
0022h |
Bitmap
Data Size |
1 dword |
Size of
the bitmap data in bytes. This number must be rounded to the next 4
byte boundary. |
|
0026h |
HResolution |
1 dword |
Horizontal resolution expressed in pixel per meter. |
|
002Ah |
VResolution |
1 dword |
Vertical
resolution expressed in pixels per meter. |
|
002Eh |
Colors |
1 dword |
Number of
colors used by this bitmap. For a 8-bit / pixel bitmap this will be
100h or 256. |
|
0032h |
Important
Colors |
1 dword |
Number of
important colors. This number will be equal to the number of colors
when every color is important. |
|
0036h |
Palette |
N * 4
byte |
The
palette specification. For every entry in the palette four bytes are
used to describe the RGB values of the color in the following way:
1 byte for blue component
1 byte for green component
1 byte for red component
1 byte filler which is set to
0 (zero) |
|
0436h |
Bitmap
Data |
x bytes |
Depending
on the compression specifications, this field contains all the
bitmap data bytes which represent indices in the color palette. |
The
following sizes were used in the specification above:
|
Size |
# bytes |
Sign |
|
char |
1 |
signed |
|
word |
2 |
unsigned |
|
dword |
4 |
unsigned |
Palette content is used for lower than 24-bit
images. In 24-bit image this content does not make any sense. Just ignore it.
That means in 24-bit BMP image data starts from offset 0036h.
Sample C Source Code
Nowadays smaller than 24-bit BMP formats are used
rarely. So here I wrote only 24-bit uncompressed BMP code. Enjoy it. Functions
use dynamically allocated matrices.
/*
* Give a
reference to this site if you like to use this code.
*
* Written by Chasan Chouse, 2004
*/
// Bitmap Structure
typedef struct {
long FileSz;
long Reserved;
long BmpOffset;
long BmpSzHead;
long X;
long Y;
unsigned int Planes;
unsigned int BitsPPixel;
long Comp; // compression
long BmpSzData;
long HRes;
long VRes;
long Colors;
long ImpColors;
} BMPHEADER;
#define UCHAR unsigned char
#define USHORT unsigned short
#define ULONG unsigned long
/*
* 24-bit full color bitmap files
* Read
Header and fill the structure.
*/
bool BMP_24_Get_Header(char FlName[], BMPHEADER *BmpHdr)
{
char ch1, ch2;
unsigned short s1, s2;
FILE *f;
f =fopen(FlName,"rb");
ch1 = fgetc(f);
ch2 = fgetc(f);
if( (ch1 != 'B') && (ch2 != 'M') ) // Supports only Windows 3.1x, 95, NT BMP format
return (false);
fread(&BmpHdr->FileSz, 4, 1, f);
fread(&BmpHdr->Reserved, 4, 1, f);
fread(&BmpHdr->BmpOffset, 4, 1, f);
fread(&BmpHdr->BmpSzHead, 4, 1, f);
fread(&BmpHdr->X, 4, 1, f);
printf("\nWidth : %ld", BmpHdr->X);
fread(&BmpHdr->Y, 4, 1, f);
printf("\nHeigth : %ld", BmpHdr->Y);
s1 = fgetc(f);
s2 = fgetc(f);
s2 <<=8;
BmpHdr->Planes = 0;
BmpHdr->Planes |= s1;
BmpHdr->Planes |= s2;
s1 = fgetc(f);
s2 = fgetc(f);
s2 <<=8;
BmpHdr->BitsPPixel = 0;
BmpHdr->BitsPPixel |= s1;
BmpHdr->BitsPPixel |= s2;
fread(&BmpHdr->Comp, 4, 1, f);
fread(&BmpHdr->BmpSzData, 4, 1, f);
fread(&BmpHdr->HRes, 4, 1, f);
fread(&BmpHdr->VRes, 4, 1, f);
fread(&BmpHdr->Colors, 4, 1, f);
fread(&BmpHdr->ImpColors, 4, 1, f);
fclose(f);
return (true);
}
/*
* -
Read actual
bitmap data. Note that bitmap lines are organized
*
reversely. List line is placed in the first scan line.
* - Look at
Dynamic Memory Allocation for double pointer(**RRed) Matrices.
*/
bool BMP_24_Get_Data(char FlName[],
BMPHEADER *BmpHdr,
UCHAR **RRed,
UCHAR **GGreen,
UCHAR **BBlue)
{
long i, j;
unsigned long BmpPix, k;
FILE *f;
f=fopen(FlName,"rb");
fseek(f,BmpHdr->BmpOffset, SEEK_SET);
for(i=(long)BmpHdr->Y-1;i>=0;i--)
{
for (j=0;j<(long)BmpHdr->X;j++)
{
fread(&BmpPix, 3, 1, f);
BmpPix &= 0x00FFFFFF;
k = BmpPix & 0xFF0000;
RRed[i][j] = k >> 16;
k = BmpPix & 0x00FF00;
GGreen[i][j] = k >> 8;
k = BmpPix & 0x0000FF;
BBlue[i][j] = k;
}
}
fclose(f);
return(true);
}
/*
* - Write
bitmap data. Note that bitmap lines are organized
*
reversely. List line is placed in the first scan line.
* - Look at
Dynamic Memory Allocation for double pointer(**RRed) Matrices.
*/
bool BMP_24_Put_Data(char FlNameFOut[],
BMPHEADER *BmpHdr,
UCHAR **RRed,
UCHAR **GGreen,
UCHAR **BBlue)
{
long i, j, BD, nx, ny, BmpPix;
char ch1, ch2;
FILE *f2;
nx = BmpHdr->X;
ny = BmpHdr->Y;
f2 = fopen(FlNameFOut,"wb");
fseek(f2, 0, SEEK_SET);
ch1 = 'B';
ch2 = 'M';
fputc(ch1, f2);
fputc(ch2, f2);
fseek(f2, 6, SEEK_SET);
fwrite(&BmpHdr->Reserved, 4, 1, f2);
fseek(f2, 14, SEEK_SET);
fwrite(&BmpHdr->BmpSzHead, 4, 1, f2);
fseek(f2, 18, SEEK_SET);
fwrite(&BmpHdr->X, 4, 1, f2);
fseek(f2, 22, SEEK_SET);
fwrite(&BmpHdr->Y, 4, 1, f2);
fseek(f2, 26, SEEK_SET);
fwrite(&BmpHdr->Planes, 2, 1, f2);
fseek(f2, 28, SEEK_SET);
fwrite(&BmpHdr->BitsPPixel, 2, 1, f2);
fseek(f2, 30, SEEK_SET);
fwrite(&BmpHdr->Comp, 4, 1, f2);
fseek(f2, 34, SEEK_SET);
fwrite(&BmpHdr->BmpSzData, 4, 1, f2);
fseek(f2, 38, SEEK_SET);
fwrite(&BmpHdr->HRes, 4, 1, f2);
fseek(f2, 42, SEEK_SET);
fwrite(&BmpHdr->VRes, 4, 1, f2);
fseek(f2, 46, SEEK_SET);
fwrite(&BmpHdr->Colors, 4, 1, f2);
fseek(f2, 2, SEEK_SET);
fwrite(&BmpHdr->FileSz, 4, 1, f2);
// Number Of important colors
fseek(f2, 50, SEEK_SET);
fwrite(&BmpHdr->ImpColors, 4, 1, f2);
// Offset from beginning of file to the beginning of the bitmap data.
fseek(f2, 10, SEEK_SET);
fwrite(&BmpHdr->BmpOffset, 4, 1, f2);
fseek(f2, BmpHdr->BmpOffset, SEEK_SET);
for(i=ny-1;i>=0;i--)
{
for (j=0;j<nx;j++)
{
BD = RRed[i][j] & 0xFF;
BmpPix = BD << 16;
BD = GGreen[i][j] & 0xFF;
BD <<= 8;
BmpPix |= BD;
BD = BBlue[i][j] & 0xFF;
BmpPix |= BD;
fwrite(&BmpPix, 3, 1, f2);
}
}
fclose(f2);
return (true);
}
|
 |