See the wiki to briefly understand a BMP file format:
https://en.wikipedia.org/wiki/BMP_file_format#Example_1
The following shows how a very simple bitmap file’s content (2x2, 4 pixels) looks like.
Following is an example of a 2×2 pixel, 24-bit bitmap (Windows DIB header BITMAPINFOHEADER) with pixel format RGB24.
Offset | Size | Hex value | Value | Description |
---|---|---|---|---|
BMP Header | ||||
0h | 2 | 42 4D | "BM" | ID field (42h, 4Dh) |
2h | 4 | 46 00 00 00 | 70 bytes (54+16) | Size of the BMP file (54 bytes header + 16 bytes data) |
6h | 2 | 00 00 | Unused | Application specific |
8h | 2 | 00 00 | Unused | Application specific |
Ah | 4 | 36 00 00 00 | 54 bytes (14+40) | Offset where the pixel array (bitmap data) can be found |
DIB Header | ||||
Eh | 4 | 28 00 00 00 | 40 bytes | Number of bytes in the DIB header (from this point) |
12h | 4 | 02 00 00 00 | 2 pixels (left to right order) | Width of the bitmap in pixels |
16h | 4 | 02 00 00 00 | 2 pixels (bottom to top order) | Height of the bitmap in pixels. Positive for bottom to top pixel order. |
1Ah | 2 | 01 00 | 1 plane | Number of color planes being used |
1Ch | 2 | 18 00 | 24 bits | Number of bits per pixel |
1Eh | 4 | 00 00 00 00 | 0 | BI_RGB, no pixel array compression used |
22h | 4 | 10 00 00 00 | 16 bytes | Size of the raw bitmap data (including padding) |
26h | 4 | 13 0B 00 00 | 2835 pixels/metre horizontal | Print resolution of the image,72 DPI × 39.3701 inches per metre yields 2834.6472 |
2Ah | 4 | 13 0B 00 00 | 2835 pixels/metre vertical | |
2Eh | 4 | 00 00 00 00 | 0 colors | Number of colors in the palette |
32h | 4 | 00 00 00 00 | 0 important colors | 0 means all colors are important |
Start of pixel array (bitmap data) | ||||
36h | 3 | 00 00 FF | 0 0 255 | Red, Pixel (x=0, y=1) |
39h | 3 | FF FF FF | 255 255 255 | White, Pixel (x=1, y=1) |
3Ch | 2 | 00 00 | 0 0 | Padding for 4 byte alignment (could be a value other than zero) |
3Eh | 3 | FF 00 00 | 255 0 0 | Blue, Pixel (x=0, y=0) |
41h | 3 | 00 FF 00 | 0 255 0 | Green, Pixel (x=1, y=0) |
44h | 2 | 00 00 | 0 0 | Padding for 4 byte alignment (could be a value other than zero) |
With the above information, you can define structures as follows:
(If your descriptions include similar level of information of the following structures and pseudo code, it should be sufficient. If you are in doubt, ask or try the same style pseudo code).
struct BMP_HEADER {
char magic[2]; // “BM”
int size; // size of the entire file
int unused;
**int bitmapDataOffset; // bitmap data offset**
};
struct DIB_HEADER {
int size_DIBHeader; // size of DIB_HEADER (including the unused part).
**int width; // width and height of the image define the size of BITMAPDATA
int height; // width and height of the image define the size of BITMAPDATA**
short colorPlane;
short bitsPerPixel;
int unused;
**int sizeRawBitmapData; // raw size of the bitmap data (= width * height * 4)**
int resolutionHorizontal;
int resolutionVertical;
int numOfColorsPallete;
int numOfImportantColors;
char unused[...]; // DIB_HEADER's size is defeined by size_DIBHeader
};
typedef unsigned char byte;
struct BITMAPDATA {
byte R;
byte G;
byte B;
};
Then, with the above structures, you can explain as follows:
// A pseudo program can parse as follows
// fread(BUFFER, bytes_to_read, FILE);
// fseek(FILE, offset);
procedure parse(FILE* fp) {
// BMP HEADER
fread(&bmp_header, sizeof(BMP_HEADER), fp);
// DIB HEADER
fread(&dib_header, sizeof(int), fp); // just read 4 bytes (for the size)
fseek(fp, sizeof(BMP_HEADER)); // set the file pointer 4 bytes back
fread(&dib_header, dib_header.**size_DIBHeader**, fp); // read the entire header
// BITMAP DATA
fseek(fp, bmp_header.**bitmapDataOffset**);
fread(bmpData, dib_header.**sizeRawBitmapData**, fp);
// It is important to show how each of the elements can be accessed.
// Use access() function to demonstrate those.
for( i = 0; i < dib_header.height; i++ ) {
BITMAPDATA* pixels = bmpData;
pixels = bmpData;
for( j = 0; j < dib_header.width; j++ ) {
// pixel's RGB can be accessed
// with pixels[j].R/G/B
access(pixels[j].R);
access(pixels[j].G);
access(pixels[j].B);
}
// next line
bmpData += (sizeof(BITMAPDATA) + 1/*1 byte is for padding*/) *
dib_header.width;
}
}
With the structure defined as follows,
struct BMP_HEADER {
char magic[2]; // “BM”
int size; // size of the entire file
int unused;
**int bitmapDataOffset; // bitmap data offset**
};
struct DIB_HEADER {
int size_DIBHeader; // size of DIB_HEADER (including the unused part).
**int width; // width and height of the image define the size of BITMAPDATA
int height; // width and height of the image define the size of BITMAPDATA**
short colorPlane;
short bitsPerPixel;
int unused;
**int sizeRawBitmapData; // raw size of the bitmap data (= width * height * 4)**
int resolutionHorizontal;
int resolutionVertical;
int numOfColorsPallete;
int numOfImportantColors;
char unused[...]; // DIB_HEADER's size is defeined by size_DIBHeader
};
typedef unsigned char byte;
struct BITMAPDATA {
byte R;
byte G;
byte B;
};