A bitmap ( .bmp ) is a binary file. Therefore you should
have knowledge of accessing binary formats file. The appropriate file function in C is
- fopen & fclose
- fread
- fgetc
Each bitmap file has header which explained what type of
bitmap that contained in the file either it's a monochrome bitmaps, 16 colour bitmap, 256
colour bitmap or 16 million colour bitmap. In this tutorial we only concerned about 16
colour and 256 colour bitmaps.
- The BYTE refers to ONE single Byte.
- The UINT stands for Unsigned Integer which consist of 2
bytes. It's also known as Word.
- The DWORD stands for Double Word, consisting of 4 bytes.
- The LONG also refers to Double Word, consisting of 4 bytes
but it is signed.
To read a bitmap, firstly we have to read the file header.
The file header will determine whether the file IS A BITMAP FILE, width & height of
the image, number of colours contained and so on. To determine whether the file is a
bitmap, the bfType must have a value of 19778. This value is taken from 2 byte unsigned
integer. If the integer are separated to a single byte. The equivalent value is 'B' for
the first byte & 'M' for the second byte, which stand for BitMap.
We must first read the BITMAPFILEHEADER, then we read the BITMAPINFOHEADER.
typedef struct tagBITMAPFILEHEADER { /* bmfh */
UINT bfType;
DWORD bfSize;
UINT bfReserved1;
UINT bfReserved2;
DWORD bfOffBits;
} BITMAPFILEHEADER;
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;
Properties of File Header
|
Size in bytes |
data type |
Name |
Comment |
Bitmap File Header |
2 |
UINT |
bfType |
'B' 'M' |
|
4 |
DWORD |
bfSize |
size of file |
|
2 |
UINT |
bfReserved1 |
reserved |
|
2 |
UINT |
bfReserved2 |
reserved |
|
4 |
DWORD |
bfOffBits |
byte location in the file which is first byte of IMAGE |
Bitmap Info Header |
4 |
DWORD |
biSize |
Size of BITMAPINFOHEADER |
|
4 |
LONG |
biWidth |
width of bitmap |
|
4 |
LONG |
biHeight |
height of bitmap |
|
2 |
WORD |
biPlanes |
1 |
|
2 |
WORD |
biBitCount |
1 (mono) or 4 (16 clr ) or 8 (256 clr) or 24 (16 Mil) |
|
4 |
DWORD |
biCompression |
RLE COMPRESSION |
|
4 |
DWORD |
biSizeImage |
width x height |
|
4 |
LONG |
biXPelsPerMeter |
|
|
4 |
LONG |
biYPelsPerMeter |
|
|
4 |
DWORD |
biClrUsed |
Number of palettes used (if less than standard) |
|
4 |
DWORD |
biClrImportant |
Number of important colour |
TOTAL LENGTH OF
BITMAP HEADER IS 54 BYTES (NOT NECESSARILY)
depend on size of bitmapinfo header (becareful)
Immediately after the file header is the PALETTES of the
bitmaps. It depends on the bitmaps it self. If you are reading 16 colour bitmaps, then the
palettes consist of 16 x 4 bytes. If you're reading 256 Colour bitmaps, then the palettes
consist of 256 x 4 bytes. For each 4 bytes, the first byte is for RED entries, second is
for GREEN entries and the third one is for BLUE entries and the last one is ignored. The
reason for this 'ignored byte' is to have a even number of bitmap file size (i.e. multiply
of 4). So that the file is more efficient in disk storage terms. The ignored bytes are
left unread.
There are some conditions where we have to consider the
anomalies of the bitmaps. Some bitmaps does not have completely 16 colour palettes, i.e.
less or 4 colour only. Some of the does not have completely 256 colour palettes, may be
less. This is because of the program that was used to create the bitmap store only the
colour needed to display the image.
BYTE cRed; /* red component of color */
BYTE cGreen; /* green component of color */
BYTE cBlue; /* blue component of color */
BYTE cIgnore; /* ignore this byte */
For 16 colour & 256 colour we only use the first 6 bits
of the bytes to determine the colour of the palettes. for example, consider a byte
01101100. The colour used for this byte is 011011. To access the first 6 bits on a bytes
you can use bit shifting " >>" (shift 2 position) or using bitwise routine
in the download section.
Note: Some of the programs that were used to create bitmaps
does not show the right amount of colour used in a bitmap. Therefore, we can determine the
colour used by determine the number of colour by using bitCount property. 4 bit is a 16
colour bitmap while 8 bit is a 256 colour bitmap.
After reading the palettes colour, 16x4 bytes or 256x4
bytes. The rest of file is the IMAGE it self. The bitmap IMAGE has certain properties. The
left bottom of the image is the first byte of the IMAGE.
first pixel>> |
|
<<last pixel |
16 & 256 COLOUR IMAGE
PROPERTIES
16 colour image will have half the size used
for 256 colour, it is because only 4 BITS (also called a nibble) are used to represent ONE
PIXEL. For example a byte 11001011. The first pixel is 1100 and the second pixel is 1011.
If we have the remainder of the bitmap width equals to 1. Therefore, the bitmap has the
last nibble + three byte in each line unused. User should ignore this nibble. The reason
is to have a multiply of 4 image size. Do check for the bitmap biImageSize property. This
property tells the user the actual bytes reserved for the IMAGE. The biWidth &
biHeight tells the user the size of the IMAGE.
For 256 colour bitmap, the image has different
properties. ONE BYTE is used to represent ONE PIXEL. If the width of the bitmap is not
devisable by 4. Then the rest of the width is padded with 0. For example, Consider a
bitmap, which have width that when been divided by 4, the remainder is 1. Therefore, the
width is actually sized width+3, with 3 bytes 0 padded at each end of line.
|
assume width % 4 == 1
----------------------------
1112323213123123123123123123
1231231231231231232323232322
1231231231231242143123123123
1231231241232131231231231231
1231241231231231231231232131
1231241231231231231231232131
1231241231231231231231232131
1231241231231231231231232131
1231241231231231231231232131
1231241231231231231231232131
1231241231231231231231232131
1231241231231231231231232131
1231241231231231231231232131
1231241231231231231231232131
|
---
000
000
000
000
000
000
000
000
000
000
000
000
000
000
|
<<last byte
|
The condition also applies if
the remainder of the bitmaps width is 3. In this case only 1 '0' byte padded at every
line. The reason of such characteristic is to make the size of the file multiply of 4. For
disk storage efficiency.
For learning purpose, suggest you
tried to understand 256 colours bitmap file first. Since it is easier to understand. After
that, tried 16 colours bitmap. As a challenge why don't you try reading monochrome
bitmaps.
BELOW IS AN EXAMPLE OF 16 COLOUR BITMAP
FILE.
BitmapFileHeader
Type 19778
Size 3118
Reserved1 0
Reserved2 0
OffsetBits 118
Size 40
Width 80
Height 75
Planes 1
BitCount 4
Compression 0
SizeImage 3000
XPelsPerMeter 0
YPelsPerMeter 0
ColorsUsed 16
ColorsImportant 16
B G R Unused
[00000000] 84 252 84 0
[00000001] 252 252 84 0
[00000002] 84 84 252 0
[00000003] 252 84 252 0
[00000004] 84 252 252 0
[00000005] 252 252 252 0
[00000006] 0 0 0 0
[00000007] 168 0 0 0
[00000008] 0 168 0 0
[00000009] 168 168 0 0
[0000000A] 0 0 168 0
[0000000B] 168 0 168 0
[0000000C] 0 168 168 0
[0000000D] 168 168 168 0
[0000000E] 84 84 84 0
[0000000F] 252 84 84 0
Then.. after knowing all the values needed to
display the image. We can simply use our graphics system to display the image. |