将Mat图像转换为bmp图像(1位图)

项目需要将Mat图像转换为bmp图像(1位图)参考了一个大神的写法,发现不能正常运行,稍微做了修改。
参考地址:把opencv Mat 按位存成bmp二值图像 (1bit 1pixel)_suifeng50的专栏-CSDN博客

#include <cstring>
#include <cstdio>
#include<iostream>
#include <fstream>
#include <windows.h>
#include<opencv2/opencv.hpp>

using namespace cv;
using namespace std;
//将mat数组转换为二进制,255用1表示,0用0表示
int  mat2Binary(const  cv::Mat img, int  line_byte, char* data)
{
	int  width = img.cols;
	int  height = img.rows;
	size_t  line_size = line_byte * 8;
	size_t  bit_size = line_size * height;


	char* p = data;  int  offset, v; unsigned  char  temp;
	for (int row = height - 1; row >= 0; row--)
	{
		for (int col = 0; col < width; col++)
		{
			offset = col % 8;
			//v = img.data[row * width + col];
			v = img.at<uchar>(row, col);
			temp = 1;
			temp = temp << (8 - offset - 1);
			if (v == 255)
			{
				*(p + col / 8) |= temp;
			}
			else
			{
				temp = ~temp;
				*(p + col / 8) &= temp;
			}
		}
		//注释掉一下代码,列数否则不能被4整除的图像最后4列会出现黑边
/*		for (int j = width / 8; j < line_byte + 1; j++) {
			p[j] = 0;
		}	*/
		p = p + line_byte;
	}
	return  0;
}

//将Mat图像保存为1位bmp图
int  save1BitImage(const  cv::Mat img, std::string dst)
{
	int  width = img.cols;
	int  height = img.rows;
	const  int  biBitCount = 1;

	//待存储图像数据每行字节数为4的倍数,计算位图每行占多少个字节
	//int  line_byte = (width * biBitCount >> 3 + 3) / 4 * 4;
	int  line_byte = (width * biBitCount / 8 + 5) / 4 * 4;//+3改为+5,否则无法向上对齐,造成崩溃
	char* p_data = (char*)malloc(line_byte * height + 1);//后面加1否则会报heap错误
	//memset(p_data, 0x01, line_byte * height+1);

	//将mat数组转换为二进制,255用1表示,0用0表示
	mat2Binary(img, line_byte, p_data);

	//bmp位图颜色表大小,以字节为单位,灰度图像颜色表为256*4字节,彩色图像颜色表大小为0,二值图为2*4 
	int  color_type_num = 2;
	int  colorTablesize = color_type_num * sizeof(RGBQUAD);
	RGBQUAD* pColorTable = new  RGBQUAD[color_type_num];
	for (int i = 0; i < color_type_num; i++) {
		pColorTable[i].rgbBlue = i * 255;
		pColorTable[i].rgbRed = i * 255;
		pColorTable[i].rgbGreen = i * 255;
		pColorTable[i].rgbReserved = 0;
	}
	//申请位图文件头结构变量,填写文件头信息 
	BITMAPFILEHEADER fileHead;
	fileHead.bfType = 0x4D42;   //bmp类型 
	fileHead.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + colorTablesize + line_byte * height;   //bfSize是图像文件4个组成部分之和,图文件的大小,以字节为单位 
	fileHead.bfReserved1 = 0;//位图文件保留字,必须为0
	fileHead.bfReserved2 = 0;
	fileHead.bfOffBits = 54 + colorTablesize;               //bfOffBits是图像文件前3个部分所需空间之和,位图数据的起始位置     

	//申请位图信息头结构变量,填写信息头信息 
	BITMAPINFOHEADER head;
	head.biBitCount = biBitCount;//每个像素所需的位数,必须是1(双色),(29-30字节)4(16色),8(256色)16(高彩色)或24(真彩色)之一
	head.biCompression = BI_RGB; 位图压缩类型,必须为BI_RGB否则图片打开会有错误
	head.biHeight = height;//位图的高度,以像素为单位
	head.biWidth = width;
	//head.biSize = 40;
	head.biSize = sizeof(BITMAPINFOHEADER);//本结构所占用字节数
	head.biSizeImage = line_byte * height;//位图的大小(其中包含了为了补齐行数是4的倍数而添加的空字节)	
	head.biPlanes = 1;//目标设备的级别,必须为1	
	head.biXPelsPerMeter = 23622;//位图水平分辨率,每米像素数,分辨率设为600
	head.biYPelsPerMeter = 23622;//位图垂直分辨率,每米像素数
	head.biClrImportant = 0;//位图显示过程中重要的颜色数
	head.biClrUsed = 0;//位图实际使用的颜色表中的颜色数

	std::ofstream fp(dst.c_str(), std::ios::binary | std::ios::out);
	if (!fp.is_open()) {
		return  -1;
	}
	fp.write((char*)&fileHead, sizeof(BITMAPFILEHEADER)); //写文件头进文件 
	//写位图信息头进内存   
	fp.write((char*)&head, sizeof(BITMAPINFOHEADER));
	//颜色表,写入文件  
	fp.write((char*)pColorTable, sizeof(RGBQUAD) * color_type_num);
	//写位图数据进文件pBmpBuf 
	fp.write((char*)p_data, height * line_byte);
	fp.close();

	delete[]pColorTable;
	delete[]p_data;
	return  0;
}

int main()
{
	Mat src = imread("D://1750343960224282.png");//加载图像 
	string dst = "D://1750343960224282_binc.bmp";//存放生成1位位图的路径
	cvtColor(src, src, COLOR_BGR2GRAY);	//转为灰度图
	save1BitImage(src, dst);
	Mat src2 = imread("D://1750343960224282_binc.bmp");//加载图像 
	return 0;
}

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值