Conversion between rgb555 and rgb888 in BMP file format, 24-bit and 16-bit bitmaps

Source: Internet
Author: User
Tags bmp image



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

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.