图像处理学习笔记(二):三维图像数组正确生成真彩色bmp格式图像文件(C++描述)

参考知识:https://www.runoob.com/cplusplus/cpp-files-streams.html(文件操作)

https://www.cnblogs.com/wainiwann/p/7086844.html(BMP文件详解)

数据集上网找bmp真彩色的有很多。

这篇博客紧接着我上一篇,上一篇写的是怎么打开真彩色bmp格式图像文件。其实我觉得(一)(二)两篇博客可以和在一起了。假设你和我一样想搞清楚更多的底层知识,暂时不想用opencv。

闲话少说,我们从文件拉出了图像的数据进内存,然后处理完,自然要存回文件。问题来了,我们一般处理的都是像素数组。像素数组一般是三维的数组。我用的是动态的数组。图像是二维的,但每个像素可能不止用一个字节来表示,RGB三通道的话就是三个。所以底层图像其实也就是一个三维的数组。你处理完之后也是一个三维的像素数组。那如何把三维像素数组变成真彩色bmp图像文件呢?答案就是反推,你需要提供像素数组的三维位宽,即图像的宽度,高度,还有每个像素用的字节数。你就看着BMP文件格式就行了。直接上代码

void bmp::produce_bmp_file(byte ***pixel,int image_width,int image_heigth,int byte_count,string file_name)
{
	int image_size;
	fstream fp;
	fp.open(file_name, ios::out|ios::binary);
	if (!fp.is_open())
	{
		cout << "文件打开失败"<<endl;
		return;
	}
	fp.put('B');
	fp.put('M');
	image_size=14+40+image_width*image_heigth*byte_count;//头文件长度+位图信息图长度+位图数据长度
	int_to_byte(image_size,int_temp);
	for(int i=0;i<4;++i)
		fp.put(int_temp[i]);
	for(int i=0;i<4;++i)
		fp.put(0);//保留字
	int_to_byte(offset,int_temp);
	for(int i=0;i<4;++i)
		fp.put(int_temp[i]);//放入偏移量
	int_to_byte(40,int_temp);//放入信息头开始,40是我目前用的BMP信息头格式大小
	for(int i=0;i<4;++i)
		fp.put(int_temp[i]);
	int_to_byte(image_width,int_temp);
	for(int i=0;i<4;++i)
		fp.put(int_temp[i]);
	int_to_byte(image_heigth,int_temp);
	for(int i=0;i<4;++i)
		fp.put(int_temp[i]);
	fp.put(1);
	fp.put(0);//放入颜色数
	short_to_byte(byte_count*8,short_temp);
	for(int i=0;i<2;++i)
		fp.put(short_temp[i]);//放入位宽大小
	for (int i = 0; i < 4; ++i)
		fp.put(0);//说明压缩格式为不压缩
	for(int i=0;i<4;++i)
		fp.put(0);//BI_RGB格式设置为0
	for (int i = 0; i < 4; ++i)
		fp.put(0);//水平分辨率缺省为0
	for (int i = 0; i < 4; ++i)
		fp.put(0);//垂直分辨率缺省为0
	for (int i = 0; i < 4; ++i)
		fp.put(0);
	for (int i = 0; i < 4; ++i)
		fp.put(0);//真彩色图象是没有调色板的,故设置为0
	for (int i = 0; i < image_width; ++i)
		for (int j = 0; j < image_heigth; ++j)
			for (int k = 0; k < byte_count; ++k)
			{
				fp.put(pixel[i][j][k]);
			}
	fp.close();
}

这里还是要说明下有难度的一件事情比如int a=0x12345678,如何底层编码也按照一个一个字节12,34,56,78存入文件呢?

编码角度,其实就是把多个字节合起来的数据拆开存入外存,其实很好办,就是强制类型转换加移位。比如int a=0x12345678,

强制转换为一个字节的数据类型 char,那么就得到最低为78,接着你右移8位,就得到56,依此得到34,12。然后你就可以一个一个字节的放入文件。

void bmp::int_to_byte(int p,byte *value)
{
	for(int i=0;i<4;++i)
	{
		value[i]=unsigned char(p);
		p=p>>8;
	}
}

展示:

基于以上的方法(还没写图像处理的算法,所以只是简单的复制)得到了两幅图像

 带reserve的是复制后的图像。用vs以二进制的方式打开文件,两幅图像底层的编码完全一样,算法成功。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值