0. Introduction to BMP format
According to Baidu Encyclopedia BMP We know that BMP is the abbreviation of Bitmap and the standard image file format in the Windows operating system. It is characterized by rich image information because it is hardly compressed, but it also occupies a large disk space.
1 file format
The bitmap file consists of four parts:
- Bitmap file header
- Bitmap information header
- Color table: use the index to represent the image. At this time, the color table is the mapping table between the index and its corresponding color (that is, find the corresponding pixel information by combining the index value with the color table)
- Bitmap data (data bits)
The above different parts have different data structures. The data structures of the first three parts are introduced below.
Data segment name | Corresponding Windows structure definition | Size (Byte) |
bmp file header | BITMAPFILEHEADER | 14 |
bmp header | BITMAPINFOHEADER | 40 |
color table | Determined by color index number | |
bmp data | Determined by image size |
2 bitmap header file
In this paper, the file format of BMP image is analyzed according to the above figure. Before analyzing the image data, it should be emphasized that in the BMP file, the data storage mode is small endian, that is, assuming that a data needs multiple bytes to represent, the order of data storage bytes is "low address stores status data, high address stores high-level data". In hexadecimal, a number occupies 4 bits, so each byte can store 2 hexadecimal digits.
Therefore, the storage order of data 0x1756 in memory is:
The structure of bitmap header file is defined as follows:
typedef struct tagBITMAPFILEHEADER { UINT16 bfType; // 19778 must be a BM string, the corresponding hexadecimal is 0x4d42 and the decimal is 19778, otherwise it is not a bmp format file DWORD bfSize; // File size in bytes (2-5 bytes) UINT16 bfReserved1; // Reserved, must be set to 0 (6-7 bytes) UINT16 bfReserved2; // Reserved, must be set to 0 (8-9 bytes) DWORD bfOffBits; // Offset from file header to pixel data (10-13 bytes) } BITMAPFILEHEADER;
In VScode, BMP image data can be viewed in binary form by installing the hexdump plug-in.
You can see by comparing the structure and file data:
0-1: 0x4d42='BM ', indicating that this is a bitmap format supported by Windows
2-5: 0x000088EA indicates the file size
6-9: reserved segment, 0
A-D: 0x00000436 = 1078, indicating that 1078 bytes need to be offset from the file header to the bitmap data
[note] when opening a file with fopen to get the file handle and read the corresponding data, there is a problem that the structure memory is aligned, which will cause errors in subsequent data reading.
What is memory alignment? For details, please refer to the article: Alignment of structure members in memory
The specific performance of the above problems can be realized through the following code:
#include <stdio.h> typedef struct tagBITMAPFILEHEADER { unsigned short bfType; // 19778 must be a BM string, the corresponding hexadecimal is 0x4d42, and the decimal is 19778. Otherwise, it is not a bmp format file (0-4) int bfSize; // File size in bytes (2-5 bytes) (4-8) unsigned short bfReserved1; // Reserved, must be set to 0 (6-7 bytes) (8-10) unsigned short bfReserved2; // Reserved, must be set to 0 (8-9 bytes) (10-12) int bfOffBits; // Offset from file header to pixel data (10-13 bytes) (12-16) } BITMAPFILEHEADER; int main(int argc, char* argv[]) { printf("sizeof(BITMAPFILEHEADER) = %lu\n", sizeof(BITMAPFILEHEADER)); return 0; } // sizeof(BITMAPFILEHEADER) = 16
There are two ways to turn off memory alignment of structures: add preprocessing instruction #pragma pack(1) or__ attribute__ ((packed)). The difference between the two methods is:
- #pragma pack(1) preprocessing instruction is to close the memory alignment mode of the whole file
- __ attribute__ ((packed)) instruction is for the specified structure
#include <stdio.h> // #pragma pack(1) typedef struct tagBITMAPFILEHEADER { unsigned short bfType; // 19778 must be a BM string, the corresponding hexadecimal is 0x4d42, and the decimal is 19778. Otherwise, it is not a bmp format file (0-4) int bfSize; // File size in bytes (2-5 bytes) (4-8) unsigned short bfReserved1; // Reserved, must be set to 0 (6-7 bytes) (8-10) unsigned short bfReserved2; // Reserved, must be set to 0 (8-9 bytes) (10-12) int bfOffBits; // Offset from file header to pixel data (10-13 bytes) (12-16) }__attribute__ ((packed)) BITMAPFILEHEADER; int main(int argc, char* argv[]) { printf("sizeof(BITMAPFILEHEADER) = %lu\n", sizeof(BITMAPFILEHEADER)); return 0; } // sizeof(BITMAPFILEHEADER) = 14
3 bitmap header
The structure of bitmap header is defined as follows:
typedef struct tagBITMAPINFOHEADER { unsigned int biSize; // Size of this structure (14-17 bytes) long biWidth; // Width of image (18-21 bytes) long biHeight; // Image height (22-25 bytes) unsigned short biPlanes; // It indicates the plane of bmp image. Obviously, the display has only one plane, so it is equal to 1 (26-27 bytes) unsigned short biBitCount; // The number of bits occupied by a pixel, usually 24 (28-29 bytes) unsigned int biCompression; // Describes the type of image data compression. 0 is not compressed. (30-33 bytes) unsigned int biSizeImage; // The size of pixel data, which should be equal to bfsize bfoffbits (34-37 bytes) in the file header structure above long biXPelsPerMeter; // Indicates the horizontal resolution in pixels per meter. Generally 0 (38-41 bytes) long biYPelsPerMeter; // Indicates the vertical resolution in pixels per meter. Generally 0 (42-45 bytes) unsigned int biClrUsed; // Indicates the number of color indexes in the color table actually used by the bitmap (if set to 0, all palette items are used). (46-49 bytes) unsigned int biClrImportant; // Indicates the number of color indexes that have an important impact on image display. If it is 0, it means that they are important. (50-53 bytes) } BITMAPINFOHEADER;
4 color table
The color table is essentially a query table, which queries the corresponding color through the color serial number. The layout in the file is similar to a two-dimensional array palette[N][4] The four elements represent the corresponding values of B, G, R and Alpha, and each component accounts for one byte. N is generally equal to 256.
There are 256 colors in total. Each color occupies 4 bytes, that is, 1024 bytes in total. Plus the 54 bytes of the previous file information header and bitmap information header, the total is 1078 bytes.
5. Bitmap data
In bitmap data, each pixel occupies one byte. Take the number of bytes as the color index, go to the color table to query the corresponding color and display it.
6. Reference links
c realize BMP to JPG with source code_ Etc. jzy's blog - CSDN blog_ c language BMP to jpg
Reading BMP files with C language - Zhihu (zhihu.com)