數字圖像處理初級——24真彩圖轉8位灰度圖(代碼實現)

特別說明: 本報告中的圖像處理函數有宏定義和變量定義,參考註釋說明。

#define WIDTHBYTES(bits) ((bits+31)/32*4)
#define Cnumber(x,y,z) *(m_pDIBData+(x)*GetBmpRealWidth()+(y)*3+(z))
//用Cnumber(x,y,z)代表從下到上,從左到右的第x行,第y列,第z個顏色分量。

#define Cnumber1(x,y,z) *(n_pDIBData+(x)*GetBmpRealWidth()+(y)*3+(z))//用於備份真彩圖 
#define gray(x,y) *(m_pDIBData+(x)*GetBmpRealWidth()+y) 
#define gray1(x,y) *(n_pDIBData+(x)*GetBmpRealWidth()+y )//用於備份灰度圖 

在此作說明,程序可以在Visual C++6.0,Win10系統下運行。

關注微信公衆號:邁微電子研發社,回覆真彩圖轉灰度圖獲取程序開發源代碼。

一、位圖文件編碼格式

此部分可以參考我上次的博文數字圖像處理初級——位圖縮放(點擊即可到達),第一部分有詳細講解。

二、實現原理

灰度值採用亮度方程計算,按照標準8位BMP灰度圖格式生成新圖像。

#define Cnumber(x,y,z) *(m_pDIBData+(x)*GetBmpRealWidth()+(y)*3+(z))
//用Cnumber(x,y,z)代表從下到上,從左到右的第x行,第y列,第z個顏色分量。

注意幾個點:

  1. 需要申請一塊新空間;
  2. 每行必須爲4的倍數,不足補0;
  3. 需要建立新的顏色表
  4. bih.biBitCount=8;//更改顏色深度
  5. 需要修改圖像實際偏移量bfh.bfOffBits和文件大小bfh.bfSize

三、程序實現

BOOL DIB::Convert24toGray() //24位真彩色轉8位灰度圖
{ 
	int i,j,n; 
	int DataByte; 
	BITMAPINFO* pBMI = NULL;//新定義位圖信息頭結構指針pBMI 
	BYTE* pDIBData = NULL;//新定義指向位圖像素灰度值的指針pDIBData
	
	//判斷打開圖像是否爲 24 位圖 
	if(bih.biBitCount!=24) 
	{ 
		AfxMessageBox("原圖不是 24 位真彩色圖"); 
		return false; 
	} 

	long w=GetDIBWidth();
	if(w%4!=0)//判斷寬度是不是4的倍數
	{
		n=w/4; 
		w=4*n+4;
	} 
	
	DataByte=w;//一行帶有0的數據
	int supply = DataByte - GetDIBWidth(); //補0的個數
	pBMI=(BITMAPINFO*)new char[sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256]; //爲信息頭分配內存空間 
	pDIBData=(BYTE*)new char[GetDIBHeight()*DataByte];//爲新圖像的像素點分配內存空間(長×寬) 
	
	//建立新的顏色表 
	for(i=0;i<256;i++)
	{ 
		pBMI->bmiColors[i].rgbRed= (unsigned char)i; 
		pBMI->bmiColors[i].rgbGreen=(unsigned char)i; 
		pBMI->bmiColors[i].rgbBlue=(unsigned char)i; 
		pBMI->bmiColors[i].rgbReserved=0;
	} 
		
	for(i=0;i<GetDIBHeight();i++) {
		for(j=0;j<GetDIBWidth();j++) //放數據
			*(pDIBData+i*(GetDIBWidth()+supply)+j)=(byte)(0.299*Cnumber(i,j,2)+0.587*Cnumber(i,j,1)+0.114*Cnumber(i,j,0));//灰度值採用亮度方程計算 
		
		for(int k = 0; k<(DataByte-GetDIBWidth()); k++)//補充0
			*(pDIBData+i*supply+(i+1)*GetDIBWidth()) = (byte) 0x00;
	}	

	bih.biBitCount=8;//更改顏色深度
	pBMI->bmiHeader.biClrUsed=256;
    pBMI->bmiHeader.biSizeImage=GetDIBHeight()*DataByte;
	bfh.bfOffBits=sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)* 256;//實際圖形數據偏移量 
	bfh.bfSize=sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256 + GetDIBHeight()*DataByte;//文件總大小 
	memcpy(&pBMI->bmiHeader,&bih,sizeof(BITMAPINFOHEADER)); 
	
	if(m_pBMI!=NULL)// 判斷原圖信息頭是否爲空
	delete m_pBMI;
	m_pBMI=pBMI; 

	if(m_pDIBData!=NULL)//判斷原圖數據是否爲空
	delete m_pDIBData; 
	m_pDIBData=pDIBData; 
	
	return true; 
}

四、實現結果及數據比對

在這裏插入圖片描述

a原圖       b轉後
圖1 彩色轉8位灰度效果圖

在這裏插入圖片描述

a 彩色直接轉灰度後        b 本實驗操作後
圖2 24位彩色轉8位灰度參數對比




再次感謝好友沈同學和引用參考文獻的幫助!

分享一張在南京玄武湖拍的照片,感謝大家的關注與點贊。
在這裏插入圖片描述

上一篇:《多媒體信息處理》課程設計——基於MFC的數字圖像處理初步

下一篇:數字圖像處理初級——位圖縮放(代碼實現)


歡迎各位訂閱我,謝謝大家的點贊和專注!我會繼續給大家分享我大學期間詳細的實踐項目。
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章