C++ bmp文件读写操作

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值