I. File Format BMP files are very common bitmap files, which are widely used in games and other fields. There are also a bunch of ready-made APIs for processing BMP files. However, how can we resolve such files on our own? In order to eliminate boredom, I spent a few days studying it and recording it as study notes. First, the content of the entire BMP file can be divided into three to four parts. The reason why there are 3 to 4 blocks instead of fixed values is that there may be a color palette or some masks for BMP. The details will be discussed later. The first part is the BMP file header used to describe the entire BMP file. The structure is as follows: typedef struct tagBITMAPFILEHEADER { WORD bfType; DWORD bfSize; WORD bfReserved1; WORD bfReserved2; DWORD bfOffBits; } Bitmapfileheader, * pbitmapfileheader; this information is quite useful if you want to parse the BMP file directly. The first bftype indicates the file type. If it is a BMP file, the value of this position must be "BM", that is, 0x4d42. The second bfsize indicates the number of bytes of the entire file. The third and fourth items are retained, which is meaningless at present. The last one is very important, indicating the offset of the bitmap data information from the file header, in bytes. The second part is the bitmap information header, which is used to describe the entire bitmap file. The following lists important data to explain: typedef struct tagbitmapinfoheader {DWORD bisize; // indicates the size of the structure long biwidth; // The width of the bitmap long biheight; // The height of the bitmap word biplanes; // It will always be 1. Because it has never been used, no research has been conducted. attached the msdn explanation // specifies the number of planes for the target device. this value must be set to 1. word bibitcount; // The number of Bitmap digits is divided into 1 4 8 16 24 32 this article did not study 1 4 DWORD bicompression; // This is the compression type, but it has another function, DWORD bisizeimage; // indicates the size of the bitmap data area in bytes. Long bixpelsperme Ter; long biypelspermeter; DWORD biclrused; DWORD biclrimportant;} bitmapinfoheader, * pbitmapinfoheader; the third part is the color palette information or mask. If it is an 8-Bit Bitmap, the color palette is stored; the 16-bit and 32-bit bitmaps store the RGB color masks, which are stored in DWORD size. The last part is the data entity of the bitmap. The above file information can be found in any article on the BMP file structure, so this article is just a little bit. 2. 4 bytes for Data Reading. BMP files have an important feature, that is, for the data area, each row of data must be fully 4 bytes. If not, redundant data is used for completion. This feature directly affects the method for reading bitmap data, because in our opinion (x, y) the data must be at the position y * width + X, but because of the redundant information, the width must be processed with the redundant amount of width + row, because bitmap files have different digits, such calculations are also different. The following lists the general formulas used to calculate the offset. First, read the bitmap information into the buffer of A uchar: 8 bits: int pitch; If (width % 4 = 0) {pitch = width ;} else {pitch = width + 4-width % 4;} Index = buffer [y * Pitch + X]; because the eight-Bit Bitmap data area stores the palette index value, so you only need to read this index 16-bit int pitch = width + width % 2; buffer [(y * Pitch + x) * 2] buffer [(I * Pitch + J) * 2 + 1] The color information of (x, y) in two uchar files is 24-bit int pitch = width % 4; buffer [(y * width + x) * 3 + y * pitch]; buffer [(y * width + x) * 3 + y * Pitch + 1]; buffer [(y * width + x) * 3 + y * Pitch + 2]; 32 bits are not included because one pixel is 4 bytes. Although computation is cumbersome, these computation operations are required. Otherwise, when the number of the elephant prime in each row of your bitmap is not a multiple of 4, then, y * width + X brings you a distorted image. Of course, if you want to perform such a rotation, it would be nice, at least because I didn't consider it at the beginning (I don't know this feature), a 16-bit image with one byte less per line of pixels turned into a distorted diamond. 3. Data separation RGB components. Since my test code uses GDI, it is not easy to separate the values of a certain vertex into RGB values in 24-Bit mode. One of the most troublesome aspects of bitmap is that there are too many formats, so we should discuss them again. We get an index through the operation mentioned in the second part. The value range is 0 ~ 255 a total of 256 colors are exactly the number of colors in the palette. In an 8-bit BMP image, the size of the first 256 rgbquad is the information of the color palette. However, to organize it into a color palette, it must be converted because the rgbquad information r B is reversed with the order in the color palette. Because I do not need to set the color palette, I read the bytes to the rgbquad array and obtain the RGB value through the following expression: uchar r = quad [Index]. rgbred; uchar G = quad [Index]. rgbgreen; uchar B = quad [Index]. rgbblue; 16 bits are the most troublesome. Because there is a difference between 555 and 565 formats, and there is also a difference between the so-called compression types. The previous bitmapinfoheader mentioned a bicompression. Now we can discuss it in two ways: bi_rgb and bi_bitfields. When they are equal to bi_rgb, they only use the 555 format. Therefore, you can perform the following data separation with confidence: uchar B = buffer [(I * Pitch + J) * 2] & 0x1f; uchar G = (buffer [(I * Pitch + J) * 2 + 1] <6) & 0xff)> 3) + (buffer [(I * Pitch + J) * 2]> 5 ); uchar r = (buffer [(I * Pitch + J) * 2 + 1] <1)> 3; don't be dazzled by this expression, I think that since you are reading this article, you have the ability to read such code. Otherwise, you can only say that you have not yet read this code and you need to learn the basic syntax. One thing worth noting is that there are many bit operations, so a pair of parentheses are added to the previous operation during processing. I used to cause errors because I did not add them, in addition, although one element in the buffer represents a uchar, the right-shift operation will automatically increase to two bytes, so we need to intercept the low-level 1-byte data at one operation. Now we will discuss bi_bitfields. In this mode, there can be 555 or 565. 555 format xrrrrrgggggbbbbb565 format rrrrrggggggbbbbb is obviously different in different formats, so we must first determine which format it belongs. When the bicompression of bitmapinfoheader is bi_bitfields, there is an RGB mask in front of the bitmap data area that describes three DWORD values. We only need to read the R or G mask, to determine the format. Take the red mask as an example. When the mask is 0111110000000000, the 555 format is 1111100000000000. Data separation in 565 format: uchar B = buffer [(I * Pitch + J) * 2] & 0x1f; uchar G = (buffer [(I * Pitch + J) * 2 + 1] <5) & 0xff)> 2) + (buffer [(I * Pitch + J) * 2]> 5); uchar r = buffer [(I * Pitch + J) * 2 + 1]> 3; now we get the respective components of RGB, but there is a new problem, that is, because the two bytes indicate the maximum green weight of each color in 3 colors 555 to 0x1f 565 format, that is, 0x3f. Therefore, we need a conversion color = color * 255/Maximum number of colors, for example, RGB (R * 0xff/0x1f, G * 0xff/0x3f, B * 0xff/0x1f) under 565) 24-bit uchar B = buffer [(I * width + J) * 3 + realpitch]; uchar G = buffer [(I * width + J) * 3 + 1 + realpitch]; uchar r = buffer [(I * width + J) * 3 + 2 + realpitch]; 32-bit uchar B = buffer [(I * width + J) * 4]; uchar G = buffer [(I * width + J) * 4 + 1]; uchar r = buffer [(I * width + J) * 4 + 2]; 4. Remaining problems when the data is obtained, the color is also separated, but the bitmap you plot may be reversed, because some bitmaps are indeed flipped. The biheight of bitmapinfoheader can be used to determine whether it is normal or flipped. When biheight is greater than 0, it is normal when it is smaller than 0, but the files written in the test are all reversed. |