将图片用其它格式保存
CImage::Save方法能将一个图像文件按另一种格式来保存,它的原型如下:
| HRESULT Save( LPCTSTR pszFileName, REFGUID guidFileType= GUID_NULL); |
其中,pszFileName用来指定一个文件名,guidFileType用来指定要保存的图像文件格式,当为GUID_NULL时,其文件格式由文件的扩展名来决定,这也是该函数的默认值。它还可以是GUID_BMPFile(BMP文件格式)、GUID_PNGFile(PNG文件格式)、GUID_JPEGFile(JPEG文件格式)和GUID_GIFFile(GIF文件格式)。
例如,下面的过程是在Ex_Image示例基础上进行的,我们在CEx_ImageView类添加ID_FILE_SAVE_AS的COMMAND事件映射程序,并添加下列代码:
| void CEx_ImageView::OnFileSaveAs() { if (m_Image.IsNull()) { MessageBox("你还没有打开一个要保存的图像文件!"); return; } CString strFilter; strFilter = "位图文件|*.bmp|JPEG 图像文件|*.jpg| \ GIF 图像文件|*.gif|PNG 图像文件|*.png||"; CFileDialog dlg(FALSE,NULL,NULL,NULL,strFilter); if ( IDOK != dlg.DoModal()) return; // 如果用户没有指定文件扩展名,则为其添加一个 CString strFileName; CString strExtension; strFileName = dlg.m_ofn.lpstrFile; if (dlg.m_ofn.nFileExtension == 0) { switch (dlg.m_ofn.nFilterIndex) { case 1: strExtension = "bmp"; break; case 2: strExtension = "jpg"; break; case 3: strExtension = "gif"; break; case 4: strExtension = "png"; break; default: break; } strFileName = strFileName + '.' + strExtension; } // 图像保存 HRESULT hResult = m_Image.Save(strFileName); if (FAILED(hResult)) MessageBox("保存图像文件失败!"); } |
柔化和锐化处理
在图像处理中,我们通常用一些数学手段,对图像进行除去噪声、强调或抽取轮廓特征等图像空间的变换。所谓"图像空间的变换"是借助于一个称之为模板的局部像素域来完成的,不同的模板具有不同的图像效果。
1. 柔化
图像的柔化是除去图像中点状噪声的一个有效方法。所谓柔化,是指使图像上任何一个像素与其相邻像素的颜色值的大小不会出现陡突的一种处理方法。设在一个3 x 3的模板中其系数为:
中间有底纹的表示中心元素,即用那个元素作为处理后的元素。很明显,上述模板(称之为Box模板)是将图像上每个像素用它近旁(包括它本身)的9个像素的平均值取代。这样处理的结果在除噪的同时,也降低图像的对比度,使图像的轮廓模糊。为了避免这一缺陷,我们对各点引入加权系数,将原来的模板改为:
新的模板可一方面除去点状噪声,同时能较好地保留原图像的对比度,因此该模板得到了广泛的应用。由于这个模板是通过二维高斯(Gauss)函数得到的,故称为高斯模板。
2. 锐化
锐化和柔化恰恰相反,它通过增强高频分量减少图像中的模糊,因此又称为高通滤波。锐化处理在增强图像边缘效果的同时增加了图像的噪声。常用的锐化模板是拉普拉斯模板:
用此模板处理后的图像,轮廓线条将明显得到增强。轮廓线以外的部分将变得较暗,而轮廓线部分将变得比较明亮。
使用程序对模板进行运算时,要考虑到溢出点的处理。所谓溢出点,指的是大于255或小于0的点。处理时,可令大于255的点取255,而小于0的点取其正值。
3. 实现代码
实现柔化和锐化时,我们先调用CImage::GetPixel来依次读取相应的像素,然后用柔化和锐化模板进行处理,最后调用CImage::SetPixel函数将处理后的像素写回到CImage对象中。具体的代码如下:
| void FilterImage(CImage* image, int nType) { if (image->IsNull()) return; int smoothGauss[9] = {1,2,1,2,4,2,1,2,1}; // 高斯模板 int sharpLaplacian[9] = {-1,-1,-1,-1,9,-1,-1,-1,-1}; // 拉普拉斯模板 int opTemp[9]; float aver; // 系数 if ( nType > 1) nType = 0; switch( nType ){ case 0: // 高斯模板 aver = (float)(1.0/16.0); memcpy( opTemp, smoothGauss, 9*sizeof(int)); break; case 1: // 拉普拉斯模板 aver = 1.0; memcpy( opTemp, sharpLaplacian, 9*sizeof(int)); break; } int i,j; int nWidth = image->GetWidth(); int nHeight = image->GetHeight(); for (i = 1; i < nWidth-1; i++){ for (j = 1; j < nHeight-1; j++){ int rr = 0, gg = 0, bb = 0; int index = 0; for (int col = -1; col <= 1; col++){ for (int row = -1; row <= 1; row++){ COLORREF clr = image->GetPixel( i+row, j+col); rr += GetRValue(clr) * opTemp[index]; gg += GetGValue(clr) * opTemp[index]; bb += GetBValue(clr) * opTemp[index]; index++; } } rr = (int)(rr*aver); gg = (int)(gg*aver); bb = (int)(bb*aver); // 处理溢出点 if ( rr > 255 ) rr = 255; else if ( rr < 0 ) rr = -rr; if ( gg > 255 ) gg = 255; else if ( gg < 0 ) gg = -gg; if ( bb > 255 ) bb = 255; else if ( bb < 0 ) bb = -bb; // 错位重写以避免前一个像素被新的像素覆盖 image->SetPixel( i-1, j-1, RGB(rr,gg,bb)); } } } |

