首页 基于VC.NET的GDI 编程之CImage

基于VC.NET的GDI 编程之CImage

举报
开通vip

基于VC.NET的GDI 编程之CImage 基于VC.NET的GDI 编程之CImage(VC图像处理新招) 我们知道,Visual C++的CBitmap类和静态图片控件的功能 是比较弱的,它只能显示出在资源中的图标、位图、光标以 及图元文件的内容,而不像VB中的Image控件可以显示出绝 大多数的外部图像文件(BMP、GIF、JPEG等)。因此,想要在 对话框或其他窗口中显示外部图像文件则只能借助于第三方 提供的控件或代码。现在,MFC和ATL共享的新类CImage为图 像处理提供了许多相应的方法,这使得Visual C++在图像方 面的缺憾一去不复返...

基于VC.NET的GDI 编程之CImage
基于VC.NET的GDI 编程之CImage(VC图像处理新招) 我们知道,Visual C++的CBitmap类和静态图片控件的功能 是比较弱的,它只能显示出在资源中的图标、位图、光标以 及图元文件的内容,而不像VB中的Image控件可以显示出绝 大多数的外部图像文件(BMP、GIF、JPEG等)。因此,想要在 对话框或其他窗口中显示外部图像文件则只能借助于第三方 提供的控件或代码。现在,MFC和ATL共享的新类CImage为图 像处理提供了许多相应的方法,这使得Visual C++在图像方 面的缺憾一去不复返了。   CImage类概述   CImage是MFC和ATL共享的新类,它能从外部磁盘中调入 一个JPEG、GIF、BMP和PNG格式的图像文件加以显示,而且 这些文件格式可以相互转换。由于CImage在不同的 Windows操作系统中其某些性能是不一样的,因此在使用时 要特别注意。例如,CImage::PlgBlt和CImage::MaskBlt只 能在 Windows NT 4.0 或更高版本中使用,但不能运行在 Windows 95/98 应用程序中。CImage::AlphaBlend和 CImage::TransparentBlt也只能在 Windows 2000/98或其更 高版本中使用。即使在Windows 2000运行程序还必须将 stdafx.h文件中的WINVER和_WIN32_WINNT的预定义修改成 0x0500才能正常使用。   CImage封装了DIB(设备无关位图)的功能,因而可以让 我们能够处理每个位图像素。它具有下列最酷特性:   1、AlphaBlend支持像素级的颜色混合,从而实现透明 和半透明的效果。   2、PlgBlt能使一个矩形区域的位图映射到一个平行四 边形区域中,而且还可能使用位屏蔽操作。   3、TransparentBlt在目标区域中产生透明图像 ,SetTransparentColor用来设置某种颜色是透明色。   4、MaskBlt在目标区域中产生源位图与屏蔽位图合成的 效果。   使用CImage的一般方法   使用CImage的一般方法是这样的过程:   (1) 打开应用程序的stdafx.h文件添加CImage类的包含 文件: #include <atlimage.h>   (2) 定义一个CImage类对象,然后调用CImage::Load方 法装载一个外部图像文件。   (3) 调用CImage::Draw方法绘制图像。Draw方法具有如 下定义: BOOL Draw( HDC hDestDC, int xDest, int yDest, int nDestWidth, int nDestHeight, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight ); BOOL Draw( HDC hDestDC, const RECT& rectDest, const RECT& rectSrc ); BOOL Draw( HDC hDestDC, int xDest, int yDest ); BOOL Draw( HDC hDestDC, const POINT& pointDest ); BOOL Draw( HDC hDestDC, int xDest, int yDest, int nDestWidth, int nDestHeight ); BOOL Draw( HDC hDestDC, const RECT& rectDest );   其中,hDestDC用来指定绘制的目标设备环境句柄 ,(xDest, yDest)和pointDest用来指定图像显示的位置 ,这个位置和源图像的左上角点相对应。nDestWidth和 nDestHeight分别指定图像要显示的高度和宽度,xSrc、 ySrc、nSrcWidth和nSrcHeight用来指定要显示的源图像的 某个部分所在的位置和大小。rectDest和rectSrc分别用来 指定目标设备环境上和源图像所要显示的某个部分的位置和 大小。   需要说明的是,Draw方法综合了StretchBlt、 TransparentBlt和AlphaBlend函数的功能。默认时,Draw的 功能和StretchBlt相同。但当图像含有透明色或Alpha通道 时,它的功能又和TransparentBlt、AlphaBlend相同。因此 ,在一般情况下,我们都应该尽量调用CImage::Draw方法来 绘制图像。   例如,下面的示例Ex_Image是实现这样的功能:当选择 "文件"ò"打开"菜单命令后,弹出一个文件打开对话框。当 选定一个图像文件后,就会在窗口客户区中显示该图像文件 内容。这个示例的具体步骤如下:   (1) 创建一个默认的单文档程序项目Ex_Image。   (2) 打开stdafx.h文件中添加CImage类的包含文件 atlimage.h。   (3) 在CEx_ImageView类添加ID_FILE_OPEN的COMMAND事 件映射程序,并添加下列代码: void CEx_ImageView::OnFileOpen() {  CString strFilter;  CSimpleArray<GUID> aguidFileTypes;  HRESULT hResult;  // 获取CImage支持的图像文件的过滤字符串  hResult = m_Image.GetExporterFilterString(strFilter,aguidFileT ypes, _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 }   (4) 定位到CEx_ImageView::OnDraw函数处,添加下列 代码: void CEx_ImageView::OnDraw(CDC* pDC) {  CEx_ImageDoc* pDoc = GetDocument();  ASSERT_VALID(pDoc);  if (!m_Image.IsNull()) {   m_Image.Draw(pDC->m_hDC,0,0);  } }   (5) 打开Ex_ImageView.h文件,添加一个公共的成员数 据m_Image: public: CImage m_Image;   (6) 编译并运行。单击"打开"工具按钮,在弹出的对话 框中指定一个图像文件后,单击"打开"按钮,其结果如图 7.21所示。   将图片用其它格式保存   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));   }  } } 图7.22是使用上述代码将某个图像处理后的结果。   变成黑白图片   由于许多图像文件使用颜色表来发挥显示设备的色彩显 示能力,因而将一张彩色图片变成黑色图片时需要调用 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);  } }   至此,我们介绍了GDI+和CImage的一般使用方法和技巧 。当然,它们本身还有许多更深入的方法,由于篇幅所限 ,这里不再一一讨论。 下面列出Ciamge的相关函数: CImage Members Operators operator HBITMAP Returns the Windows handle attached to the CImage object. Construction CImage The constructor. Operations AlphaBlend Displays bitmaps that have transparent or semitransparent pixels. Attach Attaches an HBITMAP to a CImage object. Can be used with either non-DIB section bitmaps or DIB section bitmaps. BitBlt Copies a bitmap from the source device context to this current device context. Create Creates a DIB section bitmap and attaches it to the previously constructed CImage object. CreateEx Creates a DIB section bitmap (with additional parameters) and attaches it to the previously constructed CImage object. Destroy Detaches the bitmap from the CImage object and destroys the bitmap. Detach Detaches the bitmap from a CImage object. Draw Copies a bitmap from a source rectangle into a destination rectangle. Draw stretches or compresses the bitmap to fit the dimensions of the destination rectangle, if necessary, and handles alpha blending and transparent colors. GetBits Retrieves a pointer to the actual pixel values of the bitmap. GetBPP Retrieves the bits per pixel. GetColorTable Retrieves red, green, blue (RGB) color values from a range of entries in the color table. GetDC Retrieves the device context into which the current bitmap is selected. GetExporterFilterString Finds the available image formats and their descriptions. GetImporterFilterString Finds the available image formats and their descriptions. GetHeight Retrieves the height of the current image in pixels. GetMaxColorTableEntries Retrieves the maximum number of entries in the color table. GetPitch Retrieves the pitch of the current image, in bytes. GetPixelAddress Retrieves the address of a given pixel. GetPixel Retrieves the color of the pixel specified by x and y. GetTransparentColor Retrieves the position of the transparent color in the color table. GetWidth Retrieves the width of the current image in pixels. IsDibSection Determines if the attached bitmap is a DIB section. IsIndexed Indicates that a bitmap‘s colors are mapped to an indexed palette. IsNull Indicates if a source bitmap is currently loaded. IsTransparencySupported Indicates whether the application supports transparent bitmaps and was compiled for Windows 2000 or later. LoadFromResource Loads an image from the specified resource. Load Loads an image from the specified file. MaskBlt Combines the color data for the source and destination bitmaps using the specified mask and raster operation. PlgBlt Performs a bit-block transfer from a rectangle in a source device context into a parallelogram in a destination device context. ReleaseDC Releases the device context that was retrieved with CImage::GetDC. ReleaseGDIPlus Releases resources used by GDI+. Must be called to free resources created by a global CImage object. Save Saves an image as the specified type. Save cannot specify image options. SetColorTable Sets red, green, blue RGB) color values in a range of entries in the color table of the DIB section. SetPixelIndexed Sets the pixel at the specified coordinates to the color at the specified index of the palette. SetPixelRGB Sets the pixel at the specified coordinates to the specified red, green, blue (RGB) value. SetPixel Sets the pixel at the specified coordinates to the specified color. SetTransparentColor Sets the index of the color to be treated as transparent. Only one color in a palette can be transparent. StretchBlt Copies a bitmap from a source rectangle into a destination rectangle, stretching or compressing the bitmap to fit the dimensions of the destination rectangle, if necessary. TransparentBlt Copies a bitmap with transparent color from the source device context to this current device context.
本文档为【基于VC.NET的GDI 编程之CImage】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_514943
暂无简介~
格式:pdf
大小:113KB
软件:PDF阅读器
页数:0
分类:互联网
上传时间:2011-08-16
浏览量:16