`

VC中的CImage类

阅读更多
    今天查找如何实现DIB位图的背景透明的资料时,发现有论坛上有人问到CImage类的透明问题,于是对其很感兴趣。于是搜集了一些资料,发现以下内容对该类的介绍和使用介绍比较详细,于是就拷贝至此,以备后用。
    以下内容摘自博客:http://hi.baidu.com/68400165/blog/item/f5d55508040e4fc83ac76343.html
    Visual C++的CBitmap类的功能是比较弱的,它只能显示出在资源中的图标、位图、光标以及图元文件的内容,而不像VB中的Image控件可以显示出绝大多数的外部图像文件(BMP、GIF、JPEG等)。如果想要在对话框或其他窗口中显示外部图像文件则只能借助于第三方提供的控件或代码,未免过于繁琐.
   现在,.net引入了一个功能非常强大的新类 ----- CImage.有了CImage类,Visual C++在图像方面的缺憾将一去不复返。CImage是MFC和ATL共享的新类,它能从外部磁盘中调入一个JPEG、GIF、BMP和PNG格式的图像文件加以显示,而且这些文件格式可以相互转换。例如通过简单的几句,就可以实现CImage类和CBitmap类实例的:

HBITMAP hBitmap=image.Detach();
CBitmap bmp;
bmp.Attach(hBitmap);

这样一来,就又回归到以前操纵CBitmap的方式了.CImage本身封装了DIB(设备无关位图)的功能,因而能够处理每个位图像素。
它具有下列最酷特性:
  1、AlphaBlend支持像素级的颜色混合,从而实现透明和半透明的效果。
  2、PlgBlt能使一个矩形区域的位图映射到一个平行四边形区域中,而且还可能使用位屏蔽操作。
  3、TransparentBlt在目标区域中产生透明图像,SetTransparentColor用来设置某种颜色是透明色。
  4、MaskBlt在目标区域中产生源位图与屏蔽位图合成的效果。

由于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的一般方法

  使用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,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();//detach the orignal bitmap of the image if exits and destroy it.
 // 将外部图像文件装载到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("保存图像文件失败!");

将图片用其它格式保存

  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("保存图像文件失败!");
变成黑白图片

  由于许多图像文件使用颜色表来发挥显示设备的色彩显示能力,因而将一张彩色图片变成黑色图片时需要调用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);
 }
}
       对于CImage这个类,自己也尝试着做了试验,发现在我当前用的系统(Vista系统)下作了BMP、JPG位图的显示以及指定颜色透明的简单测试,发现此类实现这些功能比较简单,使用起来也比较方便。

       另外发现,对图像进行缩放显示时,显示出来的图像存在颜色失真。此时,只需在调用image.TransparentBlt之前,设置将要显示位图的DC的缩放模式就可以解决问题了。即:

       pDC->SetStretchMode(COLORONCOLOR);

       image.TransparentBlt(pDC->GetSafeHdc(),0,0,200,200,RGB(0, 0, 0));

       但是,由于刚刚接触这个类,对它的一些方法的兼容性存在一些怀疑和担心。比如,它的实现使指定颜色透明的方法TransparentBlt能否在Windows2000及以上的Windows系统中都正常实现呢?曾经用过MFC中的CDC的实现指定颜色透明的函数TransparentBlt,在Vista系统下运行正常,可是在XP系统下却出现了问题,结果只好放弃该函数而另找方法。不知道这个类是否也存在这样的问题。

      总之,CImage类功能可能确实是很强大,但是其使用时的系统兼容性问题不知道会怎么样,还需要进一步研究。
分享到:
评论

相关推荐

    vc6使用CImage的示例程序

    `CImage`类是VC6中处理图像的强大工具,通过它,开发者可以在MFC应用中轻松地进行图像显示和处理。`TestCImage`项目就是一个很好的实践平台,帮助初学者理解和掌握`CImage`的使用方法,进一步提升图像处理能力。通过...

    CImage for VC 经过修改的VC可以使用的CImage类

    在标准的Visual C++库中,CImage类并不直接适用于MFC(Microsoft Foundation Classes)项目,但经过修改后,开发者可以让CImage在VC环境下无缝工作,扩展了MFC的应用范围。 在“CImage for VC”这个修改版中,...

    vc6.0调用vs2008 CImage类

    本主题聚焦于一个具体的技术挑战:如何在较旧的Visual C++ 6.0(VC6.0)环境中调用由Visual Studio 2008(VS2008)中的CImage类构建的动态链接库(DLL)。这个过程涉及到跨编译器和跨版本的接口设计,对于初学者来说...

    vc6可使用的CImage类

    在给定的标题“vc6可使用的CImage类”中,我们可以推断这个压缩包可能包含了一个CImage的扩展或封装,使得它可以在较旧的Visual C++ 6.0环境下使用,尽管CImage类最初是在Visual Studio 2005中引入的。 在描述中...

    VC6 CImage加载DLL

    然而,随着技术的发展,某些功能在早期版本中可能并不完善,例如,VC6原生并不支持`CImage`类。`CImage`是Visual Studio 2005及以后版本中引入的一个类,它提供了对图像处理的方便接口,包括加载、显示和保存各种...

    CImage类打开和保存jpeg、bmp、gif和png格式图片

    在Windows编程环境中,CImage类是一个非常实用的工具,它为开发者提供了方便的方式来处理和操作图像,特别是JPEG、BMP、GIF和PNG这四种常见的图像格式。CImage类是Microsoft ATL(Active Template Library)的一部分...

    vs2008写的供vc使用CImage的DLL——CimageTest.rar

    vc下用不了CImage,网上说的改这改那搞半天没成果,纯粹浪费时间,vc本身根本不支持CImage。本程序:提供在vc下使用CImage的方法——用vs写的dll,通过其导出需要用到的CImage的成员函数。 亲身验证,绝对有效。不会...

    vc6调用vs2010 CImage类.rar

    本案例中的主题是关于在较旧的Visual C++ 6.0(VC6)环境中如何利用新版本Visual Studio(VS2010)中的CImage类。CImage是Microsoft Foundation Class (MFC) 库中的一个类,它提供了方便的图像处理功能。然而,由于...

    用CImage类在VS2008平台上实现的MFC单文档多幅图片的读入

    的环境中,使用MFC (Microsoft Foundation Classes) 创建一个单文档界面(SDI, Single Document Interface)应用来读取和显示多幅图片,我们可以借助ATL(Active Template Library)中的CImage类。以下是通过这个...

    CImage类(C++),图片处理,任意角度旋转

    在C++编程环境中,图像处理是一项常见的任务,而CImage类是Microsoft的MFC(Microsoft Foundation Classes)库提供的一种方便的图像操作工具。这个类允许开发者进行一系列的图像操作,如加载、显示、保存和编辑图像...

    用CImage类实现图象实例.rar_TestDShow WJImage.h_cimage_cimage vc_图像 压缩_图像

    在本文中,我们将深入探讨如何使用CImage类在VC++环境中进行图像处理,以及与之相关的TestDShow WJImage.h、CImage类、CImage_VC、图像压缩和图像处理等概念。 首先,CImage是Microsoft Foundation Class (MFC) 库...

    vc用Cimage显示png图片

    用Cimage显示png图片,最简单的程序了。

    VC.NET基于CImage类打开图像并转换格式的方法演示.rar

    VC.NET基于CImage类打开图像并转换格式的方法演示,CImage是MFC和ATL共享的新类,它可以加载JPEG、GIF、BMP和PNG格式的图像并显示出来,而且可以在所能识别的文件格式间相互转换,是一个较基础的图像操作类,源代码...

    Cimage加载图片,并实现旋转缩放功能

    在Cimage中,你可以使用`CImage`类来创建一个图像对象,然后通过这个对象调用各种方法来处理图像。例如,使用`load`函数加载图片文件: ```cpp CImage image; if (!image.load("path_to_your_image.jpg")) { // ...

    CImage类对图像显示及保存

    用MFC的CImage类完成图像的显示和保存是VC图像处理最基础工作。

    VC.netCImage.rar_cimage_vc.net

    在.NET框架中,`CImage`是一个非常有用的类,它主要用在Visual C++ .NET环境中,用于处理图像。这个类提供了丰富的功能,包括加载、显示、编辑和保存各种图像文件格式,如BMP、JPEG、PNG等。`CImage`类是Microsoft的...

    用Cimage类进行图像的载入和保存

    在C++编程环境中,尤其是Windows应用开发中,`Cimage` 类是一个常用工具,用于处理图像的载入、显示和保存。在这个例子中,我们看到一个名为 `CChildView` 的自定义视图类,它扩展了 `CWnd` 类,并且包含与 `Cimage`...

    Mfc图像处理框架 VC编程 图像显示与处理Cimage显示OPencv处理

    MFC是Microsoft为Windows应用程序开发提供的一套类库,而CImage是MFC中的一个类,用于支持GDI+功能,包括图像的加载、显示和基本操作。OpenCV则是一个强大的开源计算机视觉库,广泛用于图像处理和计算机视觉任务。 ...

    CImage 源码+demo

    CImage库中的JPEG支持,使得我们可以处理压缩后的图像,而不会丢失太多细节。这在处理大量图片数据时,能有效节省存储空间。 PNG(Portable Network Graphics)是一种无损压缩的位图格式,尤其适合网页图像和透明...

Global site tag (gtag.js) - Google Analytics