6/19/2009

Translation bitmap image



Bitmap image contains BitmapHeader, pixels data and palette. The palette only need less than 16 bit color bitmap image, so This article will not include. Microsoft Visual studio has BitmapHeader structure in some header files. It also provides some functions which often give developer difficult to understand. Anyone who may has basic knowledge of c++ and the structure of bitmap file will has no problem with this article. The aritcle will touch only Device Independent Bitmap and pixels data are not compressed.

Code begining here // ->>
#include <stdio.h>
#include <stdlib.h>

#pragma pack(1) // get the structure size 54 not 56

typedef struct {
unsigned char bfType1; // fixed 'B'
unsigned char bfType2; // fixed 'M'
unsigned int bfSize; // Size of File. Zero is acceptable
unsigned short bfReserved1; // Zero
unsigned short bfReserved2; // Zero
unsigned int bfOffBits; // Offset to beginning of bitmap
unsigned int biSize; // Number of Bytes in Structure
unsigned int biWidth; // width of bitmap in pixels
unsigned int biHeight; // height of bitmap in pixels
unsigned short biPlanes; // Planes in target device = 1
unsigned short biBitCount; // Bits per Pixel 1, 4, 8, 16, 24, 32
unsigned int biCompression; // BI_RGB = 0, BI_RLE8, BI_RLE4
unsigned int biSizeImage; // Size of Image Part (often ignored)
unsigned int biXPelsPerMeter; // Always Zero
unsigned int biYPelsPerMeter; // Always Zero
unsigned int biClrUsed; // Number of Colors used in Palette
unsigned int biClrImportant; // Number of Colors that are Important
} TBmpHeader;
<<- // Code end here

The pixels data fills the end of bitmap file after bitmap header. The 1 point pixel data consists of red, green and blue color value each. The each color value has the size of 8 bit.

This is a structure for 24 bit color.

Code begining here // ->>
typedef struct {
unsigned char rgbBlue; //intensity of blue in the color
unsigned char rgbGreen; //intensity of green in the color
unsigned char rgbRed; //intensity of red in the color
} TRGB;
<<- // Code end here

32 bit color adds alpha color value which sometimes use calcuration for mixing two images.

Code begining here // ->>
typedef struct {
unsigned char rgbBlue; //intensity of blue in the color
unsigned char rgbGreen; //intensity of green in the color
unsigned char rgbRed; //intensity of red in the color
unsigned char rgbAlpha; //intensity of Alpha in the color
} TRGBA;
<<- // Code end here

This routine fills bitmapheader structure by using width, height and color bit. The third argument is color type. It can use with 16, 24 and 32 value.

Code begin here // ->>
TBmpHeader FillBitmapHeader(unsigned int width, unsigned int height,
unsigned short bitmapType)
{
TBmpHeader MyBitmapHeader;

MyBitmapHeader.bfType1 = 0x42;
MyBitmapHeader.bfType2 = 0x4D;
MyBitmapHeader.bfSize = 0x00000000;
MyBitmapHeader.bfReserved1 = 0x0000;
MyBitmapHeader.bfReserved2 = 0x0000;
MyBitmapHeader.bfOffBits = 0x36; // the location of bitmap data
MyBitmapHeader.biSize = 0x28; // Size of the BItmapHeader

MyBitmapHeader.biWidth = width;
MyBitmapHeader.biHeight = height;
MyBitmapHeader.biPlanes = 0x0001; // Plane target device 1

MyBitmapHeader.biBitCount = bitmapType; // Bits per Pixel 1, 4, 8, 16, 24, 32
MyBitmapHeader.biCompression = 0x00000000; // BI_RGB = 0, BI_RLE8, BI_RLE4

MyBitmapHeader.biSizeImage = 0x00000000;
MyBitmapHeader.biXPelsPerMeter = 0x00000000;
MyBitmapHeader.biYPelsPerMeter = 0x00000000;
MyBitmapHeader.biClrUsed = 0x00000000;
MyBitmapHeader.biClrImportant = 0x00000000;

return MyBitmapHeader;
}
<<- // Code end here

16 bit color can consist 32 bit color but each RGBA color has to decrease there own size half. Therefore, the result image can not avoid color loss.

Code begin here // ->>
void ConvertBmp32to16(const char *srcfname, const char *dstfname)
{
TBmpHeader MyBitmapHeader;
FILE *finput = fopen(srcfname, “rb”);
if(finput == NULL) return;
fread(&MyBitmapHeader, sizeof(TBmpHeader), 1, finput);
TRGBA * rgbdata;
unsigned short *rgbdata16;

int SSize = MyBitmapHeader.biWidth * MyBitmapHeader.biHeight;
int Size = SSize * 4;

rgbdata = (TRGBA *)malloc(Size);

fread(rgbdata, Size, 1, finput);
fclose(finput);

rgbdata16 = (unsigned short *)malloc(SSize*2);

unsigned short r, g, b, a;
for(int i=0; i < SSize; i++) {
b = rgbdata[i].rgbBlue >> 4;
g = rgbdata[i].rgbGreen >> 4;
r = rgbdata[i].rgbRed >> 4;
a = rgbdata[i].rgbAlpha >> 4;
rgbdata16[i] = (r << 12) + (g << 8) + (b << 4) + a;
}

MyBitmapHeader = FillBitmapHeader(MyBitmapHeader.biWidth, MyBitmapHeader.biHeight, 16);

FILE *fpout = fopen(dstfname, “wb”);
if(fpout == NULL) return;
fwrite(&MyBitmapHeader, sizeof(TBmpHeader), 1, fpout);
fwrite(rgbdata16, SSize*2, 1, fpout);
fclose(fpout);
free(rgbdata);
free(rgbdata16);
}
<<- // Code End here

After execute the ConvertBmp32to16() routine, a bitmap image will be generated. The aim of this routine is for keeping alpha value after translation. So, you don't have to confirm the generated image.

Code begin here // ->>
void ConvertBmp16to32(const char *srcfname, const char *dstfname)
{
TBmpHeader MyBitmapHeader;
FILE *finput = fopen(srcfname, “rb”);
if(finput == NULL) return;
fread(&MyBitmapHeader, sizeof(TBmpHeader), 1, finput);
TRGBA * rgbdata;
unsigned short *rgbdata16;

int SSize = MyBitmapHeader.biWidth * MyBitmapHeader.biHeight;
int Size = SSize * 2;

rgbdata16 = (unsigned short *)malloc(Size);

fread(rgbdata16, Size, 1, finput);
fclose(finput);

rgbdata = (TRGBA *)malloc(SSize*4);

unsigned short r, g, b, a;
for(int i=0; i < SSize; i++) {
b = (rgbdata16[i] >> 4) & 0x0f;
g = (rgbdata16[i] >> 8) & 0x0f;
r = (rgbdata16[i] >> 12) & 0x0f;
a = rgbdata16[i] & 0x0f;
rgbdata[i].rgbBlue = b << 4;
rgbdata[i].rgbGreen = g << 4;
rgbdata[i].rgbRed = r << 4;
rgbdata[i].rgbAlpha = a << 4;
}

MyBitmapHeader = FillBitmapHeader(MyBitmapHeader.biWidth, MyBitmapHeader.biHeight, 32);

FILE *fpout = fopen(dstfname, “wb”);
if(fpout == NULL) return;
fwrite(&MyBitmapHeader, sizeof(TBmpHeader), 1, fpout);
fwrite(rgbdata, SSize*4, 1, fpout);
fclose(fpout);
free(rgbdata);
free(rgbdata16);
}
<<- // Code end here

After execute the ConvertBmp16to32() routine, a bitmap image will also be generated. The image color shows
some color loss.

The shown below routine is translation routine which converts 24 bit color into 16 bit color bitmap.

Code begin here // ->>
void ConvertBmp24to16_555(const char *srcfname, const char *dstfname)
{
TBmpHeader MyBitmapHeader;
FILE *finput = fopen(srcfname, “rb”);
if(finput == NULL) return;
fread(&MyBitmapHeader, sizeof(TBmpHeader), 1, finput);
TRGB * rgbdata;
unsigned short *rgbdata16;

int SSize = MyBitmapHeader.biWidth * MyBitmapHeader.biHeight;
int Size = SSize * 3;

rgbdata = (TRGB *)malloc(Size);

fread(rgbdata, Size, 1, finput);
fclose(finput);

rgbdata16 = (unsigned short *)malloc(SSize*2);

unsigned short r, g, b, a;
for(int i=0; i < SSize; i++) {
b = rgbdata[i].rgbBlue >> 3;
g = rgbdata[i].rgbGreen >> 3;
r = rgbdata[i].rgbRed >> 3;
rgbdata16[i] = (r << 10) + (g << 5) + b;
}

MyBitmapHeader = FillBitmapHeader(MyBitmapHeader.biWidth, MyBitmapHeader.biHeight, 16);

FILE *fpout = fopen(dstfname, “wb&rdquo);
if(fpout == NULL) return;
fwrite(&MyBitmapHeader, sizeof(TBmpHeader), 1, fpout);
fwrite(rgbdata16, SSize*2, 1, fpout);
fclose(fpout);
free(rgbdata);
free(rgbdata16);
}
<<- // Code end here

Code begin here // ->>
int main(int argc, char **argv)
{
ConvertBmp32to16(“bitmap32.bmp”, “bitmap16r1.bmp”);
ConvertBmp16to32(“bitmap16r1.bmp”, “bitmap32r1.bmp”);
ConvertBmp24to16_555(“bitmap24.bmp”, “bitmap16r2.bmp”);
return 0;
}
<<- // Code end here

No comments:

Post a Comment