数字图像处理初级——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的数字图像处理初步

下一篇:数字图像处理初级——位图缩放(代码实现)


欢迎各位订阅我,谢谢大家的点赞和专注!我会继续给大家分享我大学期间详细的实践项目。
在这里插入图片描述

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