zoukankan      html  css  js  c++  java
  • Bmp图像的数据格式及读取

    数据格式参考:https://www.cnblogs.com/l2rf/p/5643352.html

    一、BMP文件读取

    下面代码通过读取一个二值bmp文件,并将数据以01的形式打印到文件中,代码中对分配的内存没有手动释放。

    union MyByte
    {
    	byte bvalue;
    	struct mytype
    	{
    	byte bit0 : 1;
    	byte bit1 : 1;
    	byte bit2 : 1;
    	byte bit3 : 1;
    	byte bit4 : 1;
    	byte bit5 : 1;
    	byte bit6 : 1;
    	byte bit7 : 1;
    	} type;
    
    };
    
    int main(void)
    {
    	//BMP文件的数据按照从文件头开始的先后顺序分为四个部分:
    	//BITMAPFILEHEADER,位图文件头(bmp file header):  提供文件的格式、大小等信息
    	//BITMAPINFOHEADER,位图信息头(bitmap information):提供图像数据的尺寸、位平面数、压缩方式、颜色索引等信息
    	//RGBQUAD,调色板(color palette):可选,如使用索引来表示图像,调色板就是索引与其对应的颜色的映射表
    	//位图数据(bitmap data):图像数据区
    	MyByte my;
    	my.bvalue = 0xF1;
    	my.type.bit1;
    	fstream fs;
    	string path = "tmp.bmp";
    	fs.open(path, ios::in | ios::binary);
    	if (!fs.is_open())
    	{
                 return -1;
    	}
    
    	BITMAPFILEHEADER bmpFileHeader = { 0 };
    	//读取header
    	//sizeof(BITMAPFILEHEADER)在当前PC上大小为14,而不是16,如果是16需要注意对齐问题
    	fs.read((char *)&bmpFileHeader, sizeof(BITMAPFILEHEADER));
    	//文件标识符,必须为"BM",小端模式,即0x4d42 才是Windows位图文件
    	if (bmpFileHeader.bfType != 0x4D42) 
    	{
    		return -1;
    	};
    
    	BITMAPINFOHEADER bmpInfoHeader = { 0 };
    	fs.read((char *)&bmpInfoHeader, sizeof(BITMAPINFOHEADER));
     
    	if (bmpInfoHeader.biBitCount == 1)
    	{   
    		/*解析二值图像的调色板*/
    		/*二值图像的调色板只有黑白两种颜色,即这边的pRGB只有两个元素,(0,0,0,0)和(255,255,255,0)*/
    		/*第四个值保留,一般用于阿尔法通道*/
    /*biBitCount 小于等于8的情况下,都存有调色板,数据区对应的存储在调色板中的索引值,超过8时,bmp中不存储调色板信息*/ int size = 1 << bmpInfoHeader.biBitCount; RGBQUAD *pRGB = new RGBQUAD[size]; for (int i = 0; i < size; ++i) { fs.read((char *)&pRGB[i], sizeof(RGBQUAD)); } /*计算每行读取的字节数。每行数据4字节对齐,不足4字节的会自动补齐*/ int lineBytes = ((bmpInfoHeader.biWidth * bmpInfoHeader.biBitCount + 31) / 8) / 4 * 4; std::fstream fsout; vector<byte *> v; for (int j = 0; j < bmpInfoHeader.biHeight ; ++j) { byte *buf = new byte[lineBytes]; memset(buf, 0, lineBytes); fs.read((char*)buf, lineBytes); v.push_back(buf); } fsout.open("t1022.txt", ios::out); //默认bmp位图数据存储是相反的,即上面的图像数据存储在数据末端。 //读取时需要颠倒下。 for (int j = bmpInfoHeader.biHeight - 1; j >= 0; --j) { byte * buf = v.at(j); for (int jj = 0; jj < lineBytes; ++jj) { MyByte b; b.bvalue = buf[jj]; //注意字节序,前面的数据存储在高bit位。每比特存储的实质是调色板的索引值,即0表示pRGB[0]的值,这里表示(0,0,0)即黑色 fsout << (unsigned int)b.type.bit7; fsout << (unsigned int)b.type.bit6; fsout << (unsigned int)b.type.bit5; fsout << (unsigned int)b.type.bit4; fsout << (unsigned int)b.type.bit3; fsout << (unsigned int)b.type.bit2; fsout << (unsigned int)b.type.bit1; fsout << (unsigned int)b.type.bit0; } fsout << endl; } fsout.close(); } fs.close(); return 0; }

      截图如下:

    原图:

  • 相关阅读:
    python——二分查找算法
    python实现二分查找
    git merge 与 git rebase的区别
    mysql查询表死锁和结束死锁的方法
    mysql的undo log和redo log
    Python中给List添加元素的4种方法
    输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字
    Python中生成器和迭代器的区别(代码在Python3.5下测试):
    mysql锁
    每天一个linux命令(46):vmstat命令
  • 原文地址:https://www.cnblogs.com/merlinzjl/p/11717405.html
Copyright © 2011-2022 走看看