CImage -对话框(柔化,锐化)保存图片

1,打开图片,图片画到pictrue控件上

 代码如下:

     CString strFilter;
  CSimpleArray<GUID> aguidFileTypes;
  HRESULT hResult;

  // 获取CImage支持的图像文件的过滤字符串
  hResult = m_Image.GetExporterFilterString(strFilter,aguidFileTypes,
_T( "All Image Files") );
  if (FAILED(hResult)) {
   MessageBox("GetExporterFilter调用失败!");
   return;
  }
  CFileDialog dlg(TRUE, NULL, NULL, OFN_FILEMUSTEXIST, strFilter);
  if(IDOK != dlg.DoModal()) 
   return;

  m_Image.Destroy();
  // 将外部图像文件装载到CImage对象中
  hResult = m_Image.Load(dlg.GetFileName());
  if (FAILED(hResult)) {
   MessageBox("调用图像文件失败!");
   return;
  }

  // 设置主窗口标题栏内容
  CString str;
  str.LoadString(AFX_IDS_APP_TITLE);
  AfxGetMainWnd()->SetWindowText(str + " - " +dlg.GetFileName());

  Invalidate(); // 强制调用OnDraw

2.保存图片:

  代码如下:

     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("保存图像文件失败!");
}
3.

柔化和锐化处理

  在图像处理中,我们通常用一些数学手段,对图像进行除去噪声、强调或抽取轮廓特征等图像空间的变换。所谓"图像空间的变换"是借助于一个称之为模板的局部像素域来完成的,不同的模板具有不同的图像效果。

  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));
   }
  }
}
4.黑白图片

变成黑白图片

  由于许多图像文件使用颜色表来发挥显示设备的色彩显示能力,因而将一张彩色图片变成黑色图片时需要调用CImage::IsIndexed来判断是否使用颜色表,若是则修改颜色表,否则直接将像素进行颜色设置。例如下面的代码:


程序代码:

void CEx_ImageView::MakeBlackAndwhite(CImage* image)
{
  if (image->IsNull()) return;

  if (!image->IsIndexed()) {
   // 直接修改像素颜色
   COLORREF pixel;
   int maxY = image->GetHeight(), maxX = image->GetWidth();
   byte r,g,b,avg;
   for (int x=0; x<maxX; x++) {
    for (int y=0; y<maxY; y++) {
     pixel = image->GetPixel(x,y);
     r = GetRValue(pixel);
     g = GetGValue(pixel);
     b = GetBValue(pixel);
     avg = (int)((r + g + b)/3);
     image->SetPixelRGB(x,y,avg,avg,avg);
    }
   }
  } else {
   // 获取并修改颜色表
   int MaxColors = image->GetMaxColorTableEntries();
   RGBQUAD* ColorTable;
   ColorTable = new RGBQUAD[MaxColors];
   image->GetColorTable(0,MaxColors,ColorTable);
   for (int i=0; i<MaxColors; i++)
   {
    int avg = (ColorTable[i].rgbBlue + ColorTable[i].rgbGreen + ColorTable[i].rgbRed)/3;
    ColorTable[i].rgbBlue = avg;
    ColorTable[i].rgbGreen = avg;
    ColorTable[i].rgbRed = avg;
   }
   image->SetColorTable(0,MaxColors,ColorTable);
   delete(ColorTable);
  }
}
本文来自编程入门网:http://www.bianceng.cn/Programming/VC_NET/200705/1066_3.htm

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值