|
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); }
|