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; }

  截圖如下:

 

原圖:

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM