C语言实现bmp图像底层数据读写与创建

要用C语言实现bmp图像底层数据读写与创建,需要对bmp图像文件格式非常了解,如果不太熟悉bmp图像文件格式请先移步bmp图像文件格式超详解

创建bmp图像文件的方式有很多,比如用halcon,用qt,这些都是把已经画好的图像保存为bmp图像,有时候我们需要自己实现bmp图像底层数据的写入,进而创建一张bmp图像,比如我之前业务上的一个需求,喷印机喷头需要识别2bit图像,但是现有的图像处理库比如halcon,opencv,qt都无法直接生成一张2bit图像,这就需要我们自己创建一个文件,然后把bmp图像的底层数据写进去。

创建方式如下:

	//1.定义2位深图像调色板
	colors2[0].rgbBlue = 0;      // 黑色
	colors2[0].rgbGreen = 0;
	colors2[0].rgbRed = 0;
	colors2[0].rgbReserved = 0;

	colors2[1].rgbBlue = 96;     // 灰色1
	colors2[1].rgbGreen = 96;
	colors2[1].rgbRed = 96;
	colors2[1].rgbReserved = 0;

	colors2[2].rgbBlue = 48;    // 灰色2
	colors2[2].rgbGreen = 48;
	colors2[2].rgbRed = 48;
	colors2[2].rgbReserved = 0;

	colors2[3].rgbBlue = 255;    // 白色
	colors2[3].rgbGreen = 255;
	colors2[3].rgbRed = 255;
	colors2[3].rgbReserved = 0;

	//2.创建并设置BMP文件头和信息头
	BITMAPFILEHEADER fileHeader;
	BITMAPINFOHEADER infoHeader;

	//2.1设置文件头基本信息
	fileHeader.bfType = 0x4D42;
	fileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + (pixelWidth * 2 + 31) / 32 * 4 * pixelHeight;
	fileHeader.bfReserved1 = 0;
	fileHeader.bfReserved2 = 0;
	fileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(colors2);


	//2.2设置信息头基本信息
	infoHeader.biSize = sizeof(BITMAPINFOHEADER);
	infoHeader.biWidth = pixelWidth;
	infoHeader.biHeight = pixelHeight;
	infoHeader.biPlanes = 1;
	infoHeader.biBitCount = 2;
	infoHeader.biCompression = BI_RGB;
	infoHeader.biSizeImage = 0;
	infoHeader.biXPelsPerMeter = 0;
	infoHeader.biYPelsPerMeter = 0;
	infoHeader.biClrUsed = 0;
	infoHeader.biClrImportant = 0;

	//3.写入文件头、信息头和调色板
	ofstream image2bit = ofstream("D:/vsdata/0100.bmp", ios::binary);

	if (!image2bit.is_open())
	{
		qDebug() << "generate2bit: file of 2bit open failed";
		return false;
	}
	image2bit.write(reinterpret_cast<const char*>(&fileHeader), sizeof(BITMAPFILEHEADER));
	image2bit.write(reinterpret_cast<const char*>(&infoHeader), sizeof(BITMAPINFOHEADER));
	image2bit.write(reinterpret_cast<const char*>(&colors2), sizeof(colors2));

	//4.根据业务需求写入图像数据

	//5.写入完毕,关掉文件
	image2bit.close();

那如何读取BMP图像文件的底层数据呢?

	//先打开一个bmp图像文件,这是一个8bit的图像文件
	ifstream inputFile(“D:vsdata/8bit.bmp”, std::ios::binary | std::ios::in);

	int acturalBytesPerLine_eight = pixelWidth;//每行像素有效字节数
	int bytesPerLine_eight = (pixelWidth * 8 + 31) / 32 * 4;//考虑了内存对齐的每行字节数,即总字节数>=每行像素有效字节数
	vector<unsigned char*>allLineData_8bit;//存储读取后的8位深图像数据
	
	//如果文件打开失败,输出调试信息
	if(!inputFile.is_open())
	{
		cout << "generate1bit:8 bit file open error";
	}
	
	inputFile.seekg(1078, std::ios::beg);  //定位到第一行的起始位置,1078是偏移量=文件头+信息头+调色板大小
	for (int i = 0; i < pixelHeight; i++)
	{
		//遍历每一行
		unsigned char* lineData = nullptr;

		try
		{
			lineData = new unsigned char[bytesPerLine_eight];//存储8位深图像的行有效数据部分
		}
		catch (bad_alloc& my_bad_alloc)
		{
			qDebug() << "generate1Bit:lineData bad_alloc:" << my_bad_alloc.what();
			return;
		}
		//注意,这里read的第二个参数是acturalBytesPerLine_eight,因为只读取行有效字节数据,填充的部分不用读取
		inputFile.read((char*)lineData, acturalBytesPerLine_eight);
		allLineData_8bit.push_back(lineData);
	}
	inputFile.close();

你可能感兴趣的:(图像处理,c语言,开发语言,图像处理)