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