bmp文件,总的说来,可以分为以下4个部分
1. 文件头-----FILE_HEADER (总共14个字节)
2. 信息头-----INFO_HEADER (总共40个字节)
3. 调色板----PALLET (单通道灰度图像才有,真彩色3通道图像没有)
4. 图像数据---IMAGE_DATA (实际图象像素数据)
bmp位图文件读写和显示到指定控件api简单封装,下面给出了封装源码的链接地址,欢迎大家一起交流,共同进步。
下载链接:http://download.csdn.net/detail/cimage/6610213
分别基本结构定义如下:
1. 文件头
struct tagBmpFileHeader //文件头
{
unsigned short bfType; //标识该文件为bmp文件,判断文件是否为bmp文件,即用该值与"0x4d42"比较是否相等即可,0x4d42 = 19778
unsigned long bfSize; //文件大小
unsigned short bfReserved1; //预保留位
unsigned short bfReserved2; //预保留位
unsigned long bfOffBits; //图像数据区的起始位置
}BmpFileHeader;//14字节
2. 信息头
struct tagBmpInfoHeader //信息头
{
unsigned long biSize; //图像数据大小
long biWidth; //宽度
long biHeight; //高度
unsigned short biPlanes;//为1
unsigned short biBitCount; //像素位数,8-灰度图;24-真彩色
unsigned longbiCompression;//压缩方式
unsigned longbiSizeImage; //图像区数据大小
long biXPelsPerMeter; //水平分辨率,像素每米
long biYPelsPerMeter;
unsigned long biClrUsed; //位图实际用到的颜色数
unsigned short biClrImportant;//位图显示过程,重要的颜色数;0--所有都重要
}BmpInfoHeader;//40字节
3. 调色板
struct tagRGBPallete //调色板
{
unsigned char b;
unsigned char g;
unsigned char r;
unsigned char alpha; //预保留位
}RGBPallete;
4. 定义一个图像结构
typedef struct tagVImage
{
int width;
int height;
int channels;
unsigned char* data;
}VImage;
5. bmp图像读取
VImage* LoadBMP(const char* filename)
{
VImage* tempImage = (VImage*)malloc(sizeof(VImage));
ULONGLONG position = 0;//文件中内容地址
int szBmpFileHeader = 0, szBmpInfoHeader = 0, szRGBPallete = 0, szTemp = 0;
int width = 0, height = 0, nChannels = 0, widthStep = 0, index = 0;
unsigned char* dataBuff = NULL;
CFile bmpFile;
if (!bmpFile.Open(filename, CFile::modeRead | CFile::shareDenyWrite))
return NULL;
szBmpFileHeader = sizeof(BmpFileHeader);
szBmpInfoHeader = sizeof(BmpInfoHeader);
szRGBPallete = sizeof(RGBPallete);
BmpFileHeader* pFileHeader = (BmpFileHeader*)malloc(szBmpFileHeader);
szTemp = bmpFile.Read(pFileHeader, szBmpFileHeader); //文件头读取完毕
position = bmpFile.Seek(szBmpFileHeader, CFile::begin); //跳转到文件头后地址处
if (szTemp != szBmpFileHeader)
return NULL;
if (pFileHeader->bfType != 0x4d42)// 0x4d42 = 19778
return NULL;
BmpInfoHeader* pInfoHeader = (BmpInfoHeader*) malloc(szBmpInfoHeader);
bmpFile.Read(pInfoHeader, szBmpInfoHeader); //信息头读取完毕
position = bmpFile.Seek(szBmpInfoHeader + position, CFile::begin);//跳转到信息头后
width = pInfoHeader->biWidth;
height = pInfoHeader->biHeight;
width = ((width + 3) >> 2) << 2;
if (8 == pInfoHeader->biBitCount)//灰度图
{
RGBPallete* pRGBPallete = (RGBPallete*) malloc(256 * szRGBPallete);
bmpFile.Read(pRGBPallete, 256 * szRGBPallete);//灰度图,读取调色板完毕
position = bmpFile.Seek(256 * szRGBPallete + position, CFile::begin);
nChannels = 1;
widthStep = width;
tempImage->width = width;
tempImage->height = height;
tempImage->channels = nChannels;
tempImage->data = (unsigned char*) malloc(width * height);
dataBuff = (unsigned char*) malloc(width * height);
memset(dataBuff, 0, width * height);
//bmpFile.Read(tempImage->data, width * height);//图像实际数据读取完毕
bmpFile.Read(dataBuff, width * height);//图像实际数据读取完毕
for (index = 0; index < height; index++)//bmp数据分布格式
{
memcpy(tempImage->data + index * width, dataBuff + (height - 1 - index) * width, width);
}
free(pFileHeader);
free(pInfoHeader);
free(pRGBPallete);
free(dataBuff);
pFileHeader = NULL;
pInfoHeader = NULL;
pRGBPallete = NULL;
dataBuff = NULL;
bmpFile.Close();//关闭文件
return tempImage;
}
else if (24 == pInfoHeader->biBitCount) // 真彩色
{
nChannels = 3;
widthStep = width * 3;
tempImage->width = width;
tempImage->height = height;
tempImage->channels = nChannels;
tempImage->data = (unsigned char*) malloc(widthStep * height);
dataBuff = (unsigned char*) malloc(widthStep * height);
//bmpFile.Read(tempImage->data, widthStep * height);
bmpFile.Read(dataBuff, widthStep * height);
for (index = 0; index < height; index++)//bmp数据分布格式为左下角到右上角,因此转换一下。
{
memcpy(tempImage->data + index * widthStep, dataBuff + (height - 1 - index) * widthStep, widthStep);
}
free(pFileHeader);
free(pInfoHeader);
free(dataBuff);
dataBuff = NULL;
pFileHeader = NULL;
pInfoHeader = NULL;
bmpFile.Close();
return tempImage;
}
return NULL;
}