C++:BMP图像文件的读取与存储

在进行本文章的阅读前, 应确保已有BMP文件结构的基础知识。
BMP图像结构基本知识链接:C++:关于BMP图像文件的基础知识

BMP类的建立

在对BMP图像文件进行操作前,应对**BMP文件**的属性及接口进行**封装**
class BMP
{
private:
	int lineByte;
	unsigned char* bmpBuffer;
	RGBQUAD* colorTable;
	BITMAPFILEHEADER fhead;
	BITMAPINFOHEADER ihead;
public:
	//初始化
	BMP()
	{
		lineByte = 0;
		bmpBuffer = new unsigned char;
		colorTable = new RGBQUAD[256];
	}
	//记得要写析构函数
	~BMP(){ delete[]bmpBuffer, colorTable; }
	
	//两个接口:读写操作
	void readBmp(string filename);
	void saveBmp(string filename);
};

一、BMP的读操作

  1. 创建ifstream对象, 并以二进制模式打开;
	ifstream ifile(filename, ios::binary);
  1. 读取并存取 BITMAPFILEHEADER 和 BITMAPINFOHEADER
    此处用到了std::istream &std::istream::read(char *_Str, std::streamsize _Count)
    1)第一个参数是一个char类型的指针,是用于存储所读的信息;
    2)第二个参数是一个streamsize类型,可理解为有符号的整型,是用于判断一次读操作所读取的大小;
	//此处用到了强制类型转换
	ifile.read((char*)&fhead, sizeof(BITMAPFILEHEADER));
	ifile.read((char*)&ihead, sizeof(BITMAPINFOHEADER));
  1. 由于真彩色图像(24位或更高位图像)无调色板,而在有调色板的图像中,8位图像又更为常见,因此在有调色板的情况中,我们仅考虑8位图像的情况,1位和4位图像的情况只要以此类推。
    注:8位图像可以表示256色位图
	if (ihead.biBitCount == 8)
		for (int i = 0; i < 256; i++) //256色位图
			ifile.read((char*)&colorTable[i], sizeof(RGBQUAD));
  1. 计算每行像素所占的字节数,并存储位图数据。
	//lineByte必须是4的倍数,且只能进位
	lineByte = (ihead.biWidth * ihead.biBitCount / 8 + 3) / 4 * 4;
	bmpBuffer = new unsigned char[lineByte * ihead.biHeight];
	for (int i = 0; i < lineByte * ihead.biHeight; i++)
		ifile.read((char*)&bmpBuffer[i], 1);

二、BMP图像的写操作

BMP图像的写操作较为简单,只需将BITMAPFILEHEADER、BITMAPINFOHEADER 、RGBQUAD 、和位图数据
依次写进文件中即可。
void BMP::saveBmp(string filename)
{
	if (!bmpBuffer)	return;
	ofstream ofile(filename, ios::binary);
	ofile.write((char*)&fhead, sizeof(BITMAPFILEHEADER));
	ofile.write((char*)&ihead, sizeof(BITMAPINFOHEADER));
	if (ihead.biBitCount == 8)for (int i = 0; i < 256; i++)
		ofile.write((char*)&colorTable[i], sizeof(RGBQUAD));
	ofile.write((char*)bmpBuffer, lineByte * ihead.biHeight);
	ofile.close();
}

三、完整代码如下

#include<Windows.h>
#include<stdio.h>
#include<fstream>
using namespace std;
class BMP
{
private:
	int lineByte;
	unsigned char* bmpBuffer;
	RGBQUAD* colorTable;
	BITMAPFILEHEADER fhead;
	BITMAPINFOHEADER ihead;
public:
	//初始化
	BMP()
	{
		lineByte = 0;
		bmpBuffer = new unsigned char;
		colorTable = new RGBQUAD[256];
	}
	//记得要写析构函数
	~BMP(){ delete[]bmpBuffer, colorTable; }
	
	//两个接口:读写操作
	void readBmp(string filename);
	void saveBmp(string filename);
};
void BMP::readBmp(string filename)
{
	ifstream ifile(filename, ios::binary);
	ifile.read((char*)&fhead, sizeof(BITMAPFILEHEADER));
	ifile.read((char*)&ihead, sizeof(BITMAPINFOHEADER));
	if (ihead.biBitCount == 8)
		for (int i = 0; i < 256; i++) 
			ifile.read((char*)&colorTable[i], sizeof(RGBQUAD));
	lineByte = (ihead.biWidth * ihead.biBitCount / 8 + 3) / 4 * 4;
	bmpBuffer = new unsigned char[lineByte * ihead.biHeight];
	for (int i = 0; i < lineByte * ihead.biHeight; i++)
		ifile.read((char*)&bmpBuffer[i], 1);
	ifile.close();
}
void BMP::saveBmp(string filename)
{
	if (!bmpBuffer)	return;
	ofstream ofile(filename, ios::binary);
	ofile.write((char*)&fhead, sizeof(BITMAPFILEHEADER));
	ofile.write((char*)&ihead, sizeof(BITMAPINFOHEADER));
	if (ihead.biBitCount == 8)for (int i = 0; i < 256; i++)
		ofile.write((char*)&colorTable[i], sizeof(RGBQUAD));
	ofile.write((char*)bmpBuffer, lineByte * ihead.biHeight);
	ofile.close();
}
int main()
{
	BMP bmp;
	bmp.readBmp("1.bmp");
	bmp.saveBmp("2.bmp");
	bmp.showBmp();
	return 0;
}
  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值