// 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;
}