char转化为cstring_openCV将8bit(1像素对应8bit)图像保存为1bit(1像素对应1bit)

b8c438490a4b8e7a55e7e59b22f892c9.png

前言

openCV处理的图像最小的位深度都是8,即每个像素的灰度值要用8bit存储,二值化处理的图像也是用8bit来存储每个像素的灰度值(0代表黑色,255代表白色),为什么不能用0和1表示呢,即每个像素用1bit存储。这样保存的图像占用的存储空间更小,在某些场合下会发挥重大的作用,下面直接上代码,将位深8bit的图像保存为位深1bit图像。

代码实现

将位深8bit的图像Mat img转化为位深1bit图像数据。

int  8Bit2Binary(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];
			temp = 1;
			temp = temp << (8 - offset - 1);
			if (v == 255)
			{
				*(p + col / 8) |= temp;
			}
			else  
			{
				temp = ~temp;
				*(p + col / 8) &= temp;
			}
		}
		for (int j = width / 8; j < line_byte; j++)
			p[j] = 0;
		p = p + line_byte;
	}
	return  0;
}

将位深8bit的图像保存为位深1bit图像。

int  save1BitImage(const  cv::Mat img, std::string dst)
{
	int  width = img.cols;
	int  height = img.rows;
	const  int  biBitCount = 1;

	//颜色表大小,以字节为单位,灰度图像颜色表为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;
	}

	//待存储图像数据每行字节数为4的倍数 
	int  line_byte = (width * biBitCount >> 3 + 3) / 4 * 4; 
	char * p_data = (char *)malloc(line_byte*height);
	//统计算法执行时间
	double start = static_cast<double>(cv::getTickCount());
	8Bit2Binary(img, line_byte, p_data);
	//统计算法运行时间
	double end = static_cast<double>(cv::getTickCount());
	double run_time = (end - start) / cv::getTickFrequency();
	std::cout << "Run Time1:" << run_time * 1000 << "ms" << std::endl;

	std::ofstream fp(dst.c_str(), std::ios::binary | std::ios::out);

	if (!fp.is_open()) {
		//  cout <<  "open "  << dst << " failed!"  << endl; 
		return  -1;
	}

	//申请位图文件头结构变量,填写文件头信息 
	BITMAPFILEHEADER fileHead;
	fileHead.bfType = 0x4D42;   //bmp类型 

	fileHead.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)
		+ colorTablesize + line_byte*height;               //bfSize是图像文件4个组成部分之和 
	fileHead.bfReserved1 = 0;
	fileHead.bfReserved2 = 0;
	fileHead.bfOffBits = 54 + colorTablesize;               //bfOffBits是图像文件前3个部分所需空间之和     

	fp.write((char *)&fileHead, sizeof(BITMAPFILEHEADER)); //写文件头进文件 

	//申请位图信息头结构变量,填写信息头信息 
	BITMAPINFOHEADER head;
	head.biBitCount = biBitCount;
	head.biClrImportant = 0;
	head.biClrUsed = 0;
	head.biCompression = 0;
	head.biHeight = height;
	head.biPlanes = 1;
	head.biSize = 40;
	head.biSizeImage = line_byte*height;
	head.biWidth = width;
	head.biXPelsPerMeter = 0;
	head.biYPelsPerMeter = 0;

	//写位图信息头进内存   
	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;
}

测试效果

//测试8bit转1bit图像
void test_8Bit2OneBit()
{ 
	Mat src = imread(".test.bmp", 0);//加载图像 
	string dst = ".result.bmp";//存放生成1位位图的路径 
	int a;
	//统计算法执行时间
	double start = static_cast<double>(cv::getTickCount());
	a = save1BitImage(src, dst);
	//统计算法运行时间
	double end = static_cast<double>(cv::getTickCount());
	double run_time = (end - start) / cv::getTickFrequency();
	std::cout << "Run Time:" << run_time * 1000 << "ms" << std::endl;
	system("pause");
}

最后

如果觉得文章对您有帮助的话,别忘了给我个赞,谢谢!,顺便推荐OpenCV学习资料!!!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值