// bmptest.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "stdio.h"
#include "stdlib.h"
#pragma pack(push)
#pragma pack(1)
typedef struct tagBITMAPFILEHEADER {
unsigned short bfType;// 位图文件的类型,必须为BM
unsigned long bfSize; // 位图文件的大小,以字节为单位
unsigned short bfReserved1; // 位图文件保留字,必须为0
unsigned short bfReserved2; // 位图文件保留字,必须为0
unsigned long bfOffBits;// 位图数据的起始位置,以相对于位图
// 文件头的偏移量表示,以字节为单位
} BITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER{
unsigned long biSize; // 本结构所占用字节数
unsigned long biWidth; // 位图的宽度,以像素为单位
unsigned long biHeight; // 位图的高度,以像素为单位
unsigned short biPlanes; // 目标设备的级别,必须为1
unsigned short biBitCount;// 每个像素所需的位数,必须是1(双色),
// 4(16色),8(256色)或24(真彩色)之一
unsigned long biCompression; // 位图压缩类型,必须是 0(不压缩),
// 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一
unsigned long biSizeImage; // 位图的大小,以字节为单位
unsigned long biXPelsPerMeter; // 位图水平分辨率,每米像素数
unsigned long biYPelsPerMeter; // 位图垂直分辨率,每米像素数
unsigned long biClrUsed;// 位图实际使用的颜色表中的颜色数
unsigned long biClrImportant;// 位图显示过程中重要的颜色数
} BITMAPINFOHEADER;
#pragma pack(pop)
typedef struct tagRGB24PIX{
unsigned char R;
unsigned char G;
unsigned char B;
} RGB24PIX;
int readBMP(char * fileName, BITMAPFILEHEADER * bmpFileHeader, BITMAPINFOHEADER * bmpInfoHeader, unsigned char ** bmpData)
{
FILE *fp;
if (!(fp = fopen(fileName, "rb")))
{
return -1;
}
fread((void *)bmpFileHeader, sizeof(unsigned char), sizeof(BITMAPFILEHEADER), fp);
fread((void *)bmpInfoHeader, sizeof(unsigned char), sizeof(BITMAPINFOHEADER), fp);
if(NULL != *bmpData)
{
free(*bmpData);
}
*bmpData = (unsigned char *)malloc(bmpFileHeader->bfSize - bmpFileHeader->bfOffBits);
fread((void *)*bmpData, sizeof(unsigned char), bmpFileHeader->bfSize - bmpFileHeader->bfOffBits, fp);
fclose(fp);
return 0;
}
int writeBMP(char * fileName, BITMAPFILEHEADER bmpFileHeader, BITMAPINFOHEADER bmpInfoHeader, unsigned char * bmpData)
{
FILE *fp;
if (!(fp = fopen(fileName, "wb")))
{
return -1;
}
fwrite((void *)&bmpFileHeader, sizeof(unsigned char), sizeof(BITMAPFILEHEADER), fp);
fwrite((void *)&bmpInfoHeader, sizeof(unsigned char), sizeof(BITMAPINFOHEADER), fp);
fwrite((void *)bmpData, sizeof(unsigned char), bmpFileHeader.bfSize - bmpFileHeader.bfOffBits, fp);
fclose(fp);
return 0;
}
unsigned long conv24to16(unsigned char * src, unsigned char ** dst, unsigned long width, unsigned long height)
{
unsigned short * convedData = NULL;
unsigned long y = 0;
unsigned long x = 0;
RGB24PIX tempPix = {0};
if(NULL != *dst)
{
free(*dst);
}
*dst = (unsigned char *)malloc(width * height * 2);
convedData = (unsigned short *) *dst;
for(y=0; y<height ; y++)
{
for(x=0; x<width ; x++)
{
tempPix.R = *(src + 3 * (width * y + x));
tempPix.G = *(src + 3 * (width * y + x) + 1);
tempPix.B = *(src + 3 * (width * y + x) + 2);
*convedData = ((((unsigned long)tempPix.R)>>3)&0x001F)|((((unsigned long)tempPix.G)<<2)&0x03E0)|((((unsigned long)tempPix.B)<<7)&0xFC00);
convedData++;
}
}
return width * height * 2;
}
int main(int argc, char* argv[])
{
BITMAPFILEHEADER srcBH = {0};
BITMAPINFOHEADER srcBI = {0};
unsigned char * srcBmpData = NULL;
unsigned char * dstBmpData = NULL;
readBMP("c://src.bmp", &srcBH, &srcBI, &srcBmpData);
srcBH.bfSize = conv24to16(srcBmpData, &dstBmpData, srcBI.biWidth, srcBI.biHeight);
srcBH.bfSize += srcBH.bfOffBits;
srcBI.biBitCount = 16;
writeBMP("c://dst.bmp", srcBH, srcBI, dstBmpData);
if(NULL != srcBmpData)
{
free(srcBmpData);
}
if(NULL != dstBmpData)
{
free(dstBmpData);
}
return 0;
}