數字圖像處理初級——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個顏色分量。
注意幾個點:
- 需要申請一塊新空間;
- 每行必須爲4的倍數,不足補0;
- 需要建立新的顏色表
- bih.biBitCount=8;//更改顏色深度
- 需要修改圖像實際偏移量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;
}
四、實現結果及數據比對
再次感謝好友沈同學和引用參考文獻的幫助!
分享一張在南京玄武湖拍的照片,感謝大家的關注與點贊。
上一篇:《多媒體信息處理》課程設計——基於MFC的數字圖像處理初步
歡迎各位訂閱我,謝謝大家的點贊和專注!我會繼續給大家分享我大學期間詳細的實踐項目。