数字图像处理初级——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的数字图像处理初步
欢迎各位订阅我,谢谢大家的点赞和专注!我会继续给大家分享我大学期间详细的实践项目。