Today, some colleagues asked me, rgb555 mode bitmap file format problem, so spent an afternoon of time through guessing and testing, analyzed the following BMP file in the rgb555 mode file storage law:
The biBitCount data in the file information header of the 1:bmp file should be 16
In rgb555 mode, one pixel occupies 2 bytes, RGB occupies 5 bits, and another is a fill bit.
2: The 16-bit data is composed of the following
First byte: g5g4g3b7b6b5b4b3
Second byte: 0r7r6r5r4r3g7g6
The first bit to the left of the second byte is the fill bit, and I fill it with 0 in the experiment.
3: The 16-bit BMP image has no palette data
4: When the 16-bit BMP image is displayed, the picture-browsing software (such as Windows Paint) automatically converts the rgb555 to the rgb888 display. The specific method is as follows
B7b6b5b4b3->b7b6b5b4b3b7b6b5
R7r6r5r4r3->r7r6r5r4r7r6r5
G7g6g5g4g3->r7r6r5r4g7g6g5
The test picture is as follows
The image above is a 24-bit BMP image, and the pixel values of the color bands from left to right are BGR
0,0,128
0,128,0
128,0,0
0,0,64
0,64,0
64,0,0
32,0,0
If the image is converted to the BMP file format of rgb55 mode, the converted file is a 16-bit BMP file. The pixel values in the color bands from left to right are
Second byte of first byte
00000000 01000000
00000000 00000010
00010000 00000000
00000000 00100000
00000000 00000001
00001000 00000000
00000100 00000000
The conversion code is as follows:
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <time.h>
BYTE * Read24BitBmpFile2Img (const char * filename, int * width, int * height)
{
FILE * BinFile;
BITMAPFILEHEADER FileHeader;
BITMAPINFOHEADER BmpHeader;
BYTE * img;
unsigned int size;
int Suc = 1, w, h;
// Open File
* width = * height = 0;
if ((BinFile = fopen (filename, "rb")) == NULL) return NULL;
// Read Struct Info
if (fread ((void *) & FileHeader, 1, sizeof (FileHeader), BinFile)! = sizeof (FileHeader)) Suc = -1;
if (fread ((void *) & BmpHeader, 1, sizeof (BmpHeader), BinFile)! = sizeof (BmpHeader)) Suc = -1;
if ((Suc ==-1) || (FileHeader.bfOffBits <sizeof (FileHeader) + sizeof (BmpHeader)))
{
fclose (BinFile);
return NULL;
}
// Read Image Data
* width = w = BmpHeader.biWidth;
* height = h = BmpHeader.biHeight;
size = (* width) * (* height) * 3;
fseek (BinFile, FileHeader.bfOffBits, SEEK_SET);
if ((img = new BYTE [size])! = NULL)
{
for (int i = 0; i <h; i ++)
{
if (fread (img + (h-1-i) * w * 3, sizeof (BYTE), w * 3, BinFile)! = w * 3)
{
fclose (BinFile);
delete img;
img = NULL;
return NULL;
}
fseek (BinFile, (3 * w + 3) / 4 * 4-3 * w, SEEK_CUR);
}
}
fclose (BinFile);
return img;
}
void BGR8882BGR555 (unsigned char * img888, unsigned char * img555, int width, int height)
{
unsigned char * p = img888;
unsigned char * q = img555;
unsigned char r, g, b;
unsigned char r1, g1, b1;
int i, j;
for (i = 0; i <height; i ++)
{
for (j = 0; j <width; j ++)
{
b = * p;
g = * (p + 1);
r = * (p + 2);
g1 = g >> 6;
r = (r >> 3) << 2;
* (q + 1) = r | g1;
g1 = ((g << 2) >> 5) << 5;
b1 = (b >> 3);
* (q) = g1 | b1;
p + = 3;
q + = 2;
}
}
}
bool Write555BitImg2BmpFile (BYTE * pImg, int width, int height, const char * filename)
// When width is not a multiple of 4, it is automatically added to a multiple of 4
{
FILE * BinFile;
BITMAPFILEHEADER FileHeader;
BITMAPINFOHEADER BmpHeader;
bool Suc = true;
int i, extend;
BYTE p [4], * pCur;
// Open File
if ((BinFile = fopen (filename, "w + b")) == NULL) {return false;}
// Fill the FileHeader
FileHeader.bfType = ((WORD) ('M' << 8) | 'B');
FileHeader.bfOffBits = sizeof (BITMAPFILEHEADER) + sizeof (BITMAPINFOHEADER);
FileHeader.bfSize = FileHeader.bfOffBits + width * height * 3L;
FileHeader.bfReserved1 = 0;
FileHeader.bfReserved2 = 0;
if (fwrite ((void *) & FileHeader, 1, sizeof (BITMAPFILEHEADER), BinFile)! = sizeof (BITMAPFILEHEADER))
Suc = false;
// Fill the ImgHeader
BmpHeader.biSize = 40;
BmpHeader.biWidth = width;
BmpHeader.biHeight = height;
BmpHeader.biPlanes = 1;
BmpHeader.biBitCount = 16;
BmpHeader.biCompression = 0;
BmpHeader.biSizeImage = 0;
BmpHeader.biXPelsPerMeter = 0;
BmpHeader.biYPelsPerMeter = 0;
BmpHeader.biClrUsed = 0;
BmpHeader.biClrImportant = 0;
if (fwrite ((void *) & BmpHeader, 1, sizeof (BITMAPINFOHEADER), BinFile)! = sizeof (BITMAPINFOHEADER))
Suc = false;
// write image data
extend = (2 * width + 2) / 4 * 4-2 * width;
if (extend == 0)
{
for (pCur = pImg + (height-1) * 2 * width; pCur> = pImg; pCur- = 2 * width)
{
if (fwrite ((void *) pCur, 1, width * 2, BinFile)! = (unsigned int) (2 * width)) Suc = false; // real data
}
}
else
{
for (pCur = pImg + (height-1) * 2 * width; pCur> = pImg; pCur- = 2 * width)
{
if (fwrite ((void *) pCur, 1, width * 2, BinFile)! = (unsigned int) (2 * width)) Suc = false; // real data
if (fwrite ((void *) (pCur + 2 * (width-1) +0), 1, extend, BinFile)! = 1) Suc = false; // extended data
}
}
// return;
fclose (BinFile);
return Suc;
}
void main ()
{
int width, height;
BYTE * pGryImg = Read24BitBmpFile2Img ("test.bmp", & width, & height);
printf ("% d,% d", width, height);
unsigned char * pImg555 = new unsigned char [width * height * 2];
BGR8882BGR555 (pGryImg, pImg555, width, height);
Write555BitImg2BmpFile (pImg555, width, height, "result.bmp");
delete pGryImg;
delete pImg555;
return;
}
After running the file result.bmp and its file attributes are as follows
Use the pixel extraction tool to view the rgb value of each color bar in result.bmp opened by windows drawing:
Take the rightmost ribbon as an example to explain why rgb is displayed as 0,0,33
The pixel value of the rightmost ribbon in rgb555 is the first byte 00000100 and the second byte 00000000
According to the first byte: g5g4g3b7b6b5b4b3 the second byte: 0r7r6r5r4r3g7g6 knows
b7b6b5b4b3 is 00100
r7r6r5r4r3 is 00000
g7g6g5g4g3 is 00000
According to the conversion rules of rgb555 to rgb888:
b7b6b5b4b3-> b7b6b5b4b3b7b6b5
r7r6r5r4r3-> r7r6r5r4r7r6r5
g7g6g5g4g3-> r7r6r5r4g7g6g5
It can be calculated that 8-bit data of r in rgb888 is 00000000, 8-bit data of g is 000000, and b data is 00100001
Convert to decimal to RGB (0,0,33)
Test the natural image:
Original image: 24-bit color image bmp file format
The converted 16-bit image (RGB555 format) bmp file and its file attributes are as follows:
You can see that there is basically no color difference between the 16-bit image and the 24-bit image.
Copyright statement: This article is an original article by the blogger and may not be reproduced without the permission of the blogger.
Bmp file format conversion between rgb555 and rgb888, 24-bit and 16-bit bitmap conversion