CImage类 from http://www.cnblogs.com/afarmer/archive/2012/03/31/2427273.html

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,Drawperforms 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(); 

转载于:https://www.cnblogs.com/songtzu/archive/2013/01/03/2843400.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/409272.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

新华计算机学校环境好吗,新华电脑校园环境好不好?(二)

随着学校规模的不断扩大和办学层次的逐步提高&#xff0c;新华的办学理念已发生了根本性的变化。在新华全国院校中&#xff0c;校园环境的美化和建设对大学生文化素质的教育有着不可替代的推动作用。在校园总体现划上&#xff0c;特别注重建筑布局和美化布局的相互映衬&#xf…

计算机无法同步时间,为什么在Win7中无法同步计算机时间?

[文章摘要]在win7中&#xff0c;为什么不能同步计算机时间&#xff1f;有什么解决办法吗&#xff1f;接下来&#xff0c;我将向您介绍为什么无法在win7中同步计算机时间的主要症状&#xff0c;可能的原因和解决方法.在win7中&#xff0c;为什么不能同步计算机时间&#xff1f;有…

在职研究生和全日制研究生的区别_“在职研究生”与“全日制研究生”有什么区别?...

“硕士研究生”是介于本科与博士之间的一个学位&#xff0c;与本科教育相比&#xff0c;研究生教育更加注重培养学生研究问题和分析问题的能力。在我国&#xff0c; 研究生可以分为两种形式&#xff1a;在职研究生、全日制研究生。其中&#xff0c;报考“在职研究生”是社会工作…

计算机多媒体设计徽章,酷毙了:Hackaday将会议徽章设计成一台可编程的电脑

Hackaday徽章可以直接挂在你的脖子上&#xff0c;但看起来更像一台小型的掌机&#xff0c;这是Hackaday Superconference的徽章。参加会议的每个人都获得这种徽章&#xff0c;它具有320 x 240彩色显示屏&#xff0c;完整的qwerty键盘和无限的可编程潜力&#xff01;内置的固件运…

后来的我们王俊凯王源机器人_王俊凯杨紫到底是什么关系

先说结论——中餐厅里的梳头姐弟之所以动人&#xff0c;是因为纯粹、纯净、真挚。 既和深厚等词不搭边&#xff0c;也不是cp。下面来分析。一先说最关注的&#xff0c;两人到底有没有情愫&#xff0c;是不是cp。如果有情愫的话&#xff0c;王俊凯对待杨紫会比对其他人优待。对比…

浙江大学计算机博士申请考核,考博经验|2020年浙江大学博士申请考核经验分享...

原标题&#xff1a;考博经验&#xff5c;2020年浙江大学博士申请考核经验分享本文系"研海拾珠"公众号原创&#xff0c;获取更多考博资料考博经验请移步公众号平台。作者 |Domin &#xff0c;浙江大学博士朝着目标坚定不移自我上学起&#xff0c;我爸妈就告诉我好好学…

西北大学计算机排行,世界排名领先,西北大学到底有多厉害?

原标题&#xff1a;世界排名领先&#xff0c;西北大学到底有多厉害&#xff1f;西北大学作为综排TOP9的美国名校&#xff0c;是许多留学生选择名校得最佳选择之一。那么作为世界排名领先的西北大学到底有多厉害&#xff1f;接下来立思辰留学云小编为你详细介绍。西北大学专业排…

是什么东西_隐形牙套附件是什么东西?

最近有一部分小宝贝收到牙套准备初佩戴啦&#xff01;但是有些小宝贝有疑惑了&#xff1a;粘在牙齿上的小凸点是什么东西&#xff1f;为什么要在牙齿上粘这个东西&#xff1f;微微细细询问后&#xff0c;原来让围观群众和正在矫正的同学们一脸懵b的就是——附件。什么是附件&am…

手游服务器验证,手游登录流程

接入第三方渠道后的手游登录流程一、客户端登录渠道流程&#xff1a;1.玩家从客户端输入user_name和password2.登录成功后&#xff0c;返回一个token传入&#xff1a;app_id、app_key、user_name、password返回&#xff1a;token说明&#xff1a;app_id、app_key是由游戏制作方…

OpenCV学习笔记(1)——显示图片

最近开始学习OpenCV了&#xff0c;也打算通过写博客来记录学习opencv的笔记吧。 第一个程序就是比较简单&#xff0c;也是入门级的程序--加载图片并显示出来。 代码如下&#xff1a; #include"highgui.h"int main() {//从文件中提取图像IplImage * imgcvLoadImage(&q…

和包支付的钱哪里来_2019年支付宝年度账单出炉,来看看你究竟花了多少钱

今天早上&#xff0c;打开支付宝付款时&#xff0c;看见搜索框出现2019年账单时&#xff0c;该来的还是要要来。随后&#xff0c;小盾打开支付宝年度帐单看了起来&#xff0c;顿时就心中就出现了这样的疑问&#xff0c;我哪来的这么多钱&#xff1f;我怎么花了这么多钱&#xf…

从RGB到Lab色彩空间的转换

最近一直在学习绘制RGB,HSV,Lab色彩空间的直方图&#xff0c;其中也涉及到互相转换的知识&#xff0c;这是网上看到的介绍的。 虽然若干年前就看过了关于色彩空间的介绍&#xff0c;但是直到今天才自己动手写代码做这件事情。虽然网络上已经有很多现成的例子&#xff0c;但是一…