CImage类

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();
// 将外部图像文件装载到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);
}
}

 

转自:http://hi.baidu.com/cauciee/blog/item/3053490994877438e8248822.html

 

GDI 总结三: CImage类使用

分类: 图形图像处理2011-12-21 09:16 427人阅读 评论(1) 收藏 举报

前言

CImage类是基于GDI+的,但是这里为什么要讲归于GDI?

         主要是基于这样的考虑: 在GDI+环境中,我们可以直接使用GDI+ ,没多少必要再使用CImage类

                                                       但是,如果再GDI环境中,我们要想使用GDI+,有点麻烦,还得加入头文件,加入启动GDI+的代码和关闭GDI+的代码,显得太罗嗦了,GDI  的CBitmap 处理功能又有局限,只能处理BMP格式的图片。 怎么办?这时,我们便可使用CImage类,因为这个类本身封装了GDI+得使用环境,所以无需我们手动设置,简化了我们的操作。  同时,又可以利用GDI+中强大的图片处理功能,及可以简便的与CBitmap对象进行转换 ,大大方便了在GDI环境下,进行各种图片处理工作 。

                                                        其实,将其称作 GDI/ GDI+ 混合编程,这样才更确切些。

为什么引入CImage类?

    CBitmap 类只能处理BMP格式的图片,非常受限。

    而CImage可以处理JPGE GIF BMP PNG多种格式图片,扩展了图片处理功能 且能与CBitmap 进行转换( 因为所载入的位图句柄都是HBITMAP,所以可相互转换),因此引入CImage类进行图像处理

     CImage provides enhanced bitmap support, including the ability to load and save images in JPEG, GIF, BMP, and Portable Network Graphics (PNG) formats

CImage类介绍

     CImage是MFC和ATL共享的新类,它能从外部磁盘中调入一个JPEG、GIF、BMP和PNG格式的图像文件加以显示,而且这些文件格式可以相互转换。

     CImage是VC.NET中定义的一种MFC/ATL共享类,也是ATL的一种工具类,它提供增强型的(DDB和DIB)位图支持,可以装入、显示、转换和保存多种格式的图像文件,包括BMP、GIF、JPG、PNG、TIF等。CImage是一个独立的类,没有基类。(CImage类是基于GDI+的,从VC.NET起引进,VC 6.0中没有。)

      ATL(Active Template Library,活动模板库)是一套基于模板的 C++ 类,用以简化小而快的 COM 对象的编写。

为了在MFC程序中使用CImage类,必须包含ATL的图像头文件atlimage.h:(在VS08 SP1中不用包含)

     #include <atlimage.h>

1  加载位图文件

[cpp] view plaincopyprint?

  1. // CImage可加载的图片文件有JPG,BMP,TIF.PNG等格式  而CBitmap只能加载BMP图片文件
  2. if(!PathFileExists(imgFilePath))  
  3. return NULL; 
  4. CImage nImage; 
  5. nImage.Load(imgFilePath); 
  6. return nImage.Detach();  //返回HBITMAP    可用CBitmap 处理 也可用CImage处理

2 与CBitmap转换

[cpp] view plaincopyprint?

  1. CImage nImage; 
  2. nImage.Load(imgFilePath); 
  3. HBITMAP hBitmap=nImage.Detach(); // 获得位图句柄 用以转换
  4. // 转换方式一:
  5. CBitmap bmp; 
  6. bmp.DeleteObject(); 
  7. bmp.Attach(hBitmap); //  转换为CBitmap对象
  8. // 转换方式二:
  9. CBitmap *pBitmap=CBitmap::FromHandle(nImage.m_hBitmap); 

3 获得CImage对象的cdc

[cpp] view plaincopyprint?

  1. CDC *pDC=CDC::FromHandle(nImage.GetDC()); 
  2. // Use pDC here
  3. nImage.ReleaseDC(); 

4 显示位图

   思路: 将CImage对象 绘制在对应的DC中

   所使用的函数 BitBlt   StretchBlt  Draw等

   以Draw举例:

[cpp] view plaincopyprint?

  1. BOOL Draw( 
  2. HDC hDestDC, 
  3. int xDest, 
  4. int yDest, 
  5. int nDestWidth, 
  6. int nDestHeight, 
  7. int xSrc, 
  8. int ySrc, 
  9. int nSrcWidth, 
  10. int nSrcHeight  
  11. ) const throw( ); 
  12. BOOL Draw( 
  13. HDC hDestDC, 
  14. const RECT& rectDest, 
  15. const RECT& rectSrc  
  16. ) const throw( ); 
  17. BOOL Draw( 
  18. HDC hDestDC, 
  19. int xDest, 
  20. int yDest  
  21. ) const throw( ); 
  22. BOOL Draw( 
  23. HDC hDestDC, 
  24. const POINT& pointDest  
  25. ) const throw( ); 
  26. BOOL Draw( 
  27. HDC hDestDC, 
  28. int xDest, 
  29. int yDest, 
  30. int nDestWidth, 
  31. int nDestHeight  
  32. ) const throw( ); 
  33. BOOL Draw( 
  34. HDC hDestDC, 
  35. const RECT& rectDest  
  36. ) const throw( ); 

Draw performs the same operation as StretchBlt, unless the image contains a transparent color or alpha channel. In that case,Draw performs the same operation as eitherTransparentBlt orAlphaBlend as required.

For versions of Draw that do not specify a source rectangle, the entire source image is the default. For the version ofDraw that does not specify a size for the destination rectangle, the size of the source image is the default and no stretching or shrinking occurs.

EXAMPLE 1:

[cpp] view plaincopyprint?

  1. CImage img; 
  2. img.Load("1.jpg"); 
  3. if (!img.IsNull()) 
  4.     img.Draw(pDC->m_hDC,CRect(0,0,100,100)); 

EXAMPLE 2: 画在另一个位图中

[cpp] view plaincopyprint?

  1. CImage img; 
  2. img.Load(filePath); 
  3. // 获得CImage对象的 CDC
  4. HDC hDC=img.GetDC(); 
  5. CDC *pDC=CDC::FromHandle(hDC); 
  6. CBitmap bmp;// 只是创建了位图对象,但还没有将位图对象与位图资源联系起来
  7. bmp.CreateCompatibleBitmap(pDC,nWidth,nHeight); // 创建新的位图资源
  8. CDC memDC; 
  9. memDC.CreateCompatibleDC(pDC); 
  10. CBitmap *pOld=memDC.SelectObject(&bmp); 
  11. // 将img图像绘制到bmp中
  12. ::SetStretchBltMode(memDC.m_hDC,HALFTONE); 
  13. ::SetBrushOrgEx(memDC.m_hDC,0,0,NULL); 
  14. img.StretchBlt(memDC.m_hDC,CRect(0,0,nWidth,nHeight)/*DestRect*/,CRect(0,0,nWidth,nHeight)/*SourceRect*/,SRCCOPY); 
  15. HBITMAP hBitmap=(HBITMAP)memDC.SelectObject(pOld->m_hObject); // 获得新创建的位图资源句柄
  16. img.ReleaseDC(); 

5 将位图资源与对象进行分离

[cpp] view plaincopyprint?

  1. inline HBITMAP CImage::Detach() throw() 
  2. HBITMAP hBitmap; 
  3.     ATLASSUME( m_hBitmap != NULL ); 
  4.     ATLASSUME( m_hDC == NULL ); 
  5.     hBitmap = m_hBitmap; 
  6.     m_hBitmap = NULL; 
  7.     m_pBits = NULL; 
  8.     m_nWidth = 0; 
  9.     m_nHeight = 0; 
  10.     m_nBPP = 0; 
  11.     m_nPitch = 0; 
  12.     m_iTransparentColor = -1; 
  13.     m_bHasAlphaChannel = false; 
  14.     m_bIsDIBSection = false; 
  15. return( hBitmap ); 

6 释放资源

CBitmap 使用DeleteObject()来主动释放掉位图资源

CImage   没有DeleteObject()函数 ,而是用Destroy()函数来主动释放位图资源

[cpp] view plaincopyprint?

  1. inline void CImage::Destroy() throw() 
  2. HBITMAP hBitmap; 
  3. if( m_hBitmap != NULL ) 
  4.     { 
  5.         hBitmap = Detach(); 
  6.         ::DeleteObject( hBitmap );  //释放位图资源
  7.     } 

CBitmap 析构时,会自动释放掉所占用的位图资源

CImage 析构时,也会自动释放掉所占用的位图资源

[cpp] view plaincopyprint?

  1. inline CImage::~CImage() throw() 
  2.     Destroy(); //释放掉所占用的位图资源
  3.     s_initGDIPlus.DecreaseCImageCount(); 

7 读写图像数据

主要用到3个函数 :

1 )GetBits() 获得数据区的指针

Retrieves a pointer to the actual bit values of a given pixel in a bitmap.

void* GetBits( ) throw( );

[cpp] view plaincopyprint?

  1. inline void* CImage::GetBits() throw() 
  2.     ATLASSUME( m_hBitmap != NULL ); 
  3.     ATLASSERT( IsDIBSection() ); 
  4. return( m_pBits ); 

A pointer to the bitmap buffer. If the bitmap is a bottom-up DIB, the pointer points near the end of the buffer. If the bitmap is a top-down DIB, the pointer points to the first byte of the buffer.

Using this pointer, along with the value returned by GetPitch, you can locate and change individual pixels in an image.

注意: 由GetBits()取得的指针不一定是图片数据的起始行,必须结合GetPitch()的值来确定起始行位置

2)GetPitch()

[cpp] view plaincopyprint?

  1. inline int CImage::GetPitch() const throw() 
  2.     ATLASSUME( m_hBitmap != NULL ); 
  3.     ATLASSERT( IsDIBSection() ); 
  4. return( m_nPitch ); 

获得图像数据每一行的字节数

The pitch of the image. If the return value is negative, the bitmap is a bottom-up DIB and its origin is the lower left corner. If the return value is positive, the bitmap is a top-down DIB and its origin is the upper left corner.

GetBits 与 GetPitch 关系:

当GetPitch()<0时,GetBits()获得的指针指向最后一行

当GetPitch()>0时,GetBits()获得的指针指向第一行

图像数据首行地址:

[cpp] view plaincopyprint?

  1. BYTE *pData=NULL; 
  2. if(img.GetPitch()<0) 
  3.     pData=(BYTE*)img.GetBits()+(img.GetPitch()*(img.GetHeight()-1)); 
  4. else
  5.     pData=(BYTE*)img.GetBits(); 

[cpp] view plaincopyprint?

  1. BYTE *pData=NULL; 
  2. if(img.GetPitch()<0) 
  3.     pData=(BYTE *)img.GetPixelAddress(img.GetHeight()-1,0); 
  4. else
  5.     pData=(BYTE *)img.GetPixelAddress(0,0); 

3)GetBPP() 返回每个像素所占的bit数

[cpp] view plaincopyprint?

  1. inline int CImage::GetBPP() const throw() 
  2.     ATLASSUME( m_hBitmap != NULL ); 
  3. return( m_nBPP ); 

The number of bits per pixel.

This value determines the number of bits that define each pixel and the maximum number of colors in the bitmap

一个综合例子:

[cpp] view plaincopyprint?

  1. void CMyImage::Negatives(void) 
  2. int i, j; 
  3. //图像每一行的字节数
  4. int nRowBytes = GetPitch(); 
  5. int nWidth = GetWidth(); 
  6. int nHeight = GetHeight(); 
  7. //每个像素所占的字节数
  8. int nClrCount = GetBPP() / 8; 
  9. LPBYTE p; 
  10. for(int index = 0; index < nClrCount; index++) 
  11.     { 
  12.         p = (LPBYTE)GetBits(); 
  13. for(i = 0; i < nHeight; i++) 
  14.         { 
  15. for(j = 0; j < nWidth; j++) 
  16.             { 
  17.                 p[j*nClrCount + index] = 255 - p[j*nClrCount + index]; 
  18.             } 
  19. //如果nRowBytes>0  则从开始到结尾
  20. //如果nRowBytes<0, 则从结尾到开始
  21.             p += nRowBytes;  
  22.         } 
  23.     } 

8 保存到图像文件中

Saves an image as the specified file name and type.

HRESULT Save( IStream* pStream, REFGUID guidFileType ) const throw(); HRESULT Save( LPCTSTR pszFileName, REFGUID guidFileType=GUID_NULL )

[cpp] view plaincopyprint?

  1. inline HRESULT CImage::Save( LPCTSTR pszFileName, REFGUID guidFileType ) const throw() 
  2. if( !InitGDIPlus() ) 
  3.     { 
  4. return( E_FAIL ); 
  5.     } 
  6. UINT nEncoders; 
  7. UINT nBytes; 
  8.     Gdiplus::Status status; 
  9.     status = Gdiplus::GetImageEncodersSize( &nEncoders, &nBytes ); 
  10. if( status != Gdiplus::Ok ) 
  11.     { 
  12. return( E_FAIL ); 
  13.     } 
  14.     USES_CONVERSION_EX; 
  15.     Gdiplus::ImageCodecInfo* pEncoders = static_cast< Gdiplus::ImageCodecInfo* >( _ATL_SAFE_ALLOCA(nBytes, _ATL_SAFE_ALLOCA_DEF_THRESHOLD) ); 
  16. if( pEncoders == NULL ) 
  17. return E_OUTOFMEMORY; 
  18.     status = Gdiplus::GetImageEncoders( nEncoders, nBytes, pEncoders ); 
  19. if( status != Gdiplus::Ok ) 
  20.     { 
  21. return( E_FAIL ); 
  22.     } 
  23.     CLSID clsidEncoder = CLSID_NULL; 
  24. if( guidFileType == GUID_NULL ) 
  25.     { 
  26. // Determine clsid from extension
  27.         clsidEncoder = FindCodecForExtension( ::PathFindExtension( pszFileName ), pEncoders, nEncoders ); 
  28.     } 
  29. else
  30.     { 
  31. // Determine clsid from file type
  32.         clsidEncoder = FindCodecForFileType( guidFileType, pEncoders, nEncoders ); 
  33.     } 
  34. if( clsidEncoder == CLSID_NULL ) 
  35.     { 
  36. return( E_FAIL ); 
  37.     } 
  38. LPCWSTR pwszFileName = T2CW_EX( pszFileName, _ATL_SAFE_ALLOCA_DEF_THRESHOLD ); 
  39. #ifndef _UNICODE
  40. if( pwszFileName == NULL ) 
  41. return E_OUTOFMEMORY; 
  42. #endif // _UNICODE
  43. if( m_bHasAlphaChannel ) 
  44.     { 
  45.         ATLASSUME( m_nBPP == 32 ); 
  46.         Gdiplus::Bitmap bm( m_nWidth, m_nHeight, m_nPitch, PixelFormat32bppARGB, static_cast< BYTE* >( m_pBits ) ); 
  47.         status = bm.Save( pwszFileName, &clsidEncoder, NULL ); 
  48. if( status != Gdiplus::Ok ) 
  49.         { 
  50. return( E_FAIL ); 
  51.         } 
  52.     } 
  53. else
  54.     { 
  55.         Gdiplus::Bitmap bm( m_hBitmap, NULL ); 
  56.         status = bm.Save( pwszFileName, &clsidEncoder, NULL ); 
  57. if( status != Gdiplus::Ok ) 
  58.         { 
  59. return( E_FAIL ); 
  60.         } 
  61.     } 
  62. return( S_OK ); 
pStream

A pointer to a stream containing the file name for the image.

pszFileName

A pointer to the file name for the image.

guidFileType

The file type to save the image as. Can be one of the following:

  • ImageFormatBMP   An uncompressed bitmap image.

  • ImageFormatPNG   A Portable Network Graphic (PNG) compressed image.

  • ImageFormatJPEG   A JPEG compressed image.

  • ImageFormatGIF   A GIF compressed image.

Call this function to save the image using a specified name and type. If the guidFileType parameter is not included, the file name's file extension will be used to determine the image format. If no extension is provided, the image will be saved in BMP format.

MSDN例子:

[cpp] view plaincopyprint?

  1.   Copy Code  
  2. // Demonstrating saving various file formats
  3. int _tmain(int argc, _TCHAR* argv[]) 
  4.    CImage myimage; 
  5. // load existing image
  6.    myimage.Load("image.bmp");  
  7. // save an image in BMP format
  8.    myimage.Save("c:\image1.bmp"); 
  9. // save an image in BMP format
  10.    myimage.Save("c:\image2",ImageFormatBMP); 
  11. // save an image in JPEG format
  12.    myimage.Save("c:\image3.jpg"); 
  13. // save an image in BMP format, even though jpg file extension is used
  14.    myimage.Save("c:\image4.jpg",ImageFormatBMP); 
  15. return 0; 

9 应用实例: 将两个图像合并为一个新的图像

[cpp] view plaincopyprint?

  1. //图像路径
  2. CString img1Path; 
  3. CString img2Path; 
  4. CString img3Path; 
  5. img1Path=_T("1.bmp"); 
  6. img2Path=_T("2.bmp"); 
  7. img3Path=_T("3.bmp");  // 将 图片1、2 合并成图片3
  8. CImage img1,img2,img3; 
  9. img1.Load(img1Path); 
  10. img2.Load(img2Path); 
  11. CBitmap bmp; 
  12. CDC memDC; 
  13. HDC hDC=NULL; 
  14. CDC *pDC=NULL; 
  15. CBitmap *pOld=NULL; 
  16. HBITMAP hBitmap=NULL; 
  17. //创建位图
  18. hDC=img1.GetDC(); 
  19. pDC=CDC::FromHandle(hDC); 
  20. bmp.DeleteObject(); 
  21. bmp.CreateCompatibleBitmap(pDC,img1.GetWidth()/2,img1.GetHeight()); 
  22. memDC.DeleteDC(); 
  23. memDC.CreateCompatibleDC(pDC); 
  24. pOld=memDC.SelectObject(&bmp); 
  25. ::SetStretchBltMode(memDC.m_hDC,HALFTONE); 
  26. ::SetBrushOrgEx(memDC.m_hDC,0,0,NULL); 
  27. // 背景置白色
  28. CRgn rectRgn; 
  29. rectRgn.CreateRectRgn(0,0,img1.GetWidth()/2,img1.GetHeight()); 
  30. CBrush brush; 
  31. brush.CreateSolidBrush(RGB(255,255,255)); 
  32. memDC.FillRgn(&rectRgn,&brush); 
  33. //画图
  34. img1.StretchBlt(memDC.m_hDC,CRect(0,0,img1.GetWidth()/2,img1.GetHeight()/2),CRect(0,0,img1.GetWidth(),img1.GetHeight()),SRCCOPY); 
  35. img2.StretchBlt(memDC.m_hDC,CRect(0,img1.GetHeight()/2,img1.GetWidth()/2,img1.GetHeight()),CRect(0,0,img2.GetWidth(),img2.GetHeight()),SRCCOPY); 
  36. hBitmap=(HBITMAP)memDC.SelectObject(pOld->m_hObject); 
  37. img3.Attach(hBitmap);// 载入位图资源
  38. img3.Save(img3Path); // 保存新的位图
  39. img1.ReleaseDC(); 
  40. img1.Destroy(); 
  41. img2.Destroy(); 
  42. img3.Destroy(); 

 

转自:http://blog.csdn.net/shuilan0066/article/details/7080244

你可能感兴趣的:(image)