【数字图像处理】VC++实现图片的读取、显示与存储

数字图像处理(Digital Image Processing)

是指用计算机处理图像,主要包括:
(1)点运算:针对图像的像素进行基本数学运算。点运算可以有效的改变图像的直方图分布,可以有效提高图像的分辨率,以及图像均衡的操作。
(2)几何处理:主要包括图像的坐标 变换,图像的移动、缩小、放大、旋转,多个图像的配准以及图像扭曲校正等。图像的扭曲校正功能可以将变形的图像进行几何校正。
(3)图像增强:图像增强的作用主要是突出图像中重要的信息,同时减弱或者去除不重要的信息。常用方法有直方图增强和为彩色增强。
(4)图像复原:图像复原的主要目的是去除干扰和模糊,从而恢复图像的原样,例如去噪声复原处理。
(5)图像形态学处理:图像形态学是数学形态学的延伸,利用图像形态学处理技术,可以实现图像的腐蚀、细化和分割等效果。
(6)图像编码:利用图像信号的统计特性及人类视觉特性对图像进行高效编码,从而达到压缩图像的目的。
(7)图像重建:利用采集到的数据来重建图像,起源于CT技术的发展,是一门新兴的数字图像处理技术。图像重建的主要算法有代数法、迭代法、傅里叶反投影法和使用最广泛的卷积反投影法等。
(8)模式识别:包括三种方法统计识别法、句法结构模式识别法和模糊识别法。

图像和调色板

图像是由三维客观世界映射到二维所得到的结果,因此一幅图像可以用二维的含数f(x,y)来表示,这里的x,y表示二维空间中一个坐标点的位置,f表示图像在点(x,y)出的某种属性,如亮度,常见的图像是连续的,即f、x、y的取值是连续的。为了是计算机能够对图像进行处理,需要对图像进行采样、量化和编码,从而形成一幅离散的数字图像。因此,通常用I=f(x,y)来表示一幅数字图像,也可以用二维矩阵的形式来描述一幅M*N的数字图像。
在这里插入图片描述
矩阵中的各个元素称为像素,一幅数字图现象是由在水平方向上的M列像素和垂直方向上的N行像素构成的,在数值上等于数字图像在该坐标点处的灰度值。

所谓调色板就是在16色或者256色显示系统中,是图像中出现最频繁的16种或256种颜色所组成的颜色表。对这些颜色按4位或者8位(即0到15或者255)进行编号,每一个编号代表其中的一种颜色。这种颜色编号叫做颜色的索引号,4位或者8位的索引号与24位的颜色值的对应表叫做颜色查找表。使用调色板的图像叫做调色板图像,他们的像素值并不是颜色值,而是颜色在调色板查找表中的索引号。

Windows使用2种不同的位图,即设备相关位图DDB(Device Dependent Bitmap)和设备无关位图DIB(Device Independent Bitmap)。DIB位图文件中包含该位图的逻辑调色板的颜色表,其像素值是该调色板中的颜色索引值。DDB位图中不包含调色板信息,其像素值是该系统调色板中的颜色索引值。在结构上,DIB与DDB的主要区别在于DIB包含一个名为RGBQUUAD的结构,它描述了DIB位图的颜色表。

图片的读取

1.在vs2010中创建MFC基于对话框的应用程序
在这里插入图片描述
2.在资源视图的Dialog界面创建图片显示窗口和控制按钮,方法是在对话框中添加picture control和Button 等控件。分别修改各个控件的ID和Caption。
在这里插入图片描述
3.双击打开按钮,MFC自动添加消息响应函数void CBMP_RSYDlg::OnBnClickedButtonOpen(),并在消息响应函数中添加如下代码:

CFileDialog dlg(TRUE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,"bmp(*.bmp)|*.bmp||",this);
	if (dlg.DoModal()!=IDOK)
	{
		MessageBox("图片打开失败");
		return;
	}
	m_strSrcBmpPath = dlg.GetPathName();

	CFile file;
	file.Open(m_strSrcBmpPath,CFile::modeRead);
	file.Read(m_pBmpFileHeader,14);

	file.Seek(14,CFile::begin);
	file.Read(m_pBmpInfo, 40+256*4);
	if (m_pBmpInfo->bmiHeader.biBitCount==8)//灰度图像,有调色板
	{
		file.Seek(14+40+256*4,CFile::begin);
	}
	else if (m_pBmpInfo->bmiHeader.biBitCount==24)//彩色图像,无调色板
	{
		file.Seek(14+40,CFile::begin);
	}

	int iWidth = m_pBmpInfo->bmiHeader.biWidth;
	int iHeight = m_pBmpInfo->bmiHeader.biHeight;
	int iImgSize = m_pBmpInfo->bmiHeader.biSizeImage;
	int iXPels = m_pBmpInfo->bmiHeader.biXPelsPerMeter;
	int iYPels = m_pBmpInfo->bmiHeader.biYPelsPerMeter;
	int biClrUsed = m_pBmpInfo->bmiHeader.biClrUsed;
	int biClrImportant = m_pBmpInfo->bmiHeader.biClrImportant;

	file.Read(m_pSrcBuf, m_pBmpInfo->bmiHeader.biSizeImage);
	file.Close();

	Invalidate();

4.要想将读取的图像显示出来,需要在OnPaint()函数中载入图像并和picture control关联,具体代码如下:

CDC *m_pDC = GetDC();
	GetDlgItem(IDC_SRCImage)->GetWindowRect(&m_rc);
	ScreenToClient(&m_rc);
	::SetStretchBltMode(m_pDC->GetSafeHdc(),COLORONCOLOR);
	::StretchDIBits(m_pDC->GetSafeHdc(),
		m_rc.left,m_rc.top,m_rc.Width(),m_rc.Height(),
		0,0,m_pBmpInfo->bmiHeader.biWidth,m_pBmpInfo->bmiHeader.biHeight,
		m_pSrcBuf,m_pBmpInfo,
		DIB_RGB_COLORS,SRCCOPY);

5.读取进来的图像经过一系列的处理后,需要将处理后的图像进行保存。双击保存按钮可在源文件中添加消息响应函数void CBMP_RSYDlg::OnBnClickedButtonSave(),并在消息响应函数中添加如下代码:

CFileDialog dlg(FALSE,NULL,NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,"bmp(*bmp)|*.bmp||",this);
	if (dlg.DoModal()!=IDOK)
	{
		MessageBox("图片保存失败!");
		return;
	}
	m_strDstBmpPath = dlg.GetPathName();
	CFile file;
	file.Open(m_strDstBmpPath,CFile::modeCreate|CFile::modeWrite);
	if (m_pBmpInfoDst->bmiHeader.biBitCount==8)
	{
		file.Write(m_pBmpFileHeaderDst,sizeof(BITMAPFILEHEADER));
		file.Write(m_pBmpInfoDst,sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256);
		file.Write(m_pDstBuf,m_pBmpInfoDst->bmiHeader.biSizeImage);
		file.Close();
	}
	else if (m_pBmpInfoDst->bmiHeader.biBitCount==24)
	{
		file.Write(m_pBmpFileHeaderDst,sizeof(BITMAPFILEHEADER));
		file.Write(m_pBmpInfoDst,sizeof(BITMAPINFOHEADER));
		file.Write(m_pDstBuf,m_pBmpInfoDst->bmiHeader.biSizeImage);
		file.Close();
	}

TIPS:
在进行文件的读取时,需要先申请一块内存,并将图片信息放在申请好的内存当中,当内存使用过后最好将内存释放,以免造成内存泄露。而在当进行批量图像的读取与显示的时候,每一张图像的读取都要进行内存的申请与释放,会造成线程的响应变慢,从而影响到整个进程。因此,最好的解决办法是提前申请好一个内存区域,在进程中不进行内存的释放,将图像进行循环读取并清除。这样就需要一块足够大的内存区域,一般是申请BYTE[2048*2048*4]
文件的读取与保存是常用功能,因此打开文件路径的函数需要牢记。

  • 10
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值