其他关于此类的介绍:

http://blog.csdn.net/wayaoqiang/article/details/7620745点击打开链接

http://blog.sina.com.cn/s/blog_5a82024e0100c84g.html点击打开链接

http://blog.csdn.net/wangji163163/article/details/1780508点击打开链接

http://blog.csdn.net/huamin1990/article/details/5349947点击打开链接

前言

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 plain copy
  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 plain copy
  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 plain copy
  1. CDC *pDC=CDC::FromHandle(nImage.GetDC());
  2. // Use pDC here
  3. nImage.ReleaseDC();

4 显示位图

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

所使用的函数 BitBlt   StretchBlt  Draw等

以Draw举例:

[cpp] view plain copy
  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 plain copy
  1. CImage img;
  2. img.Load("1.jpg");
  3. if (!img.IsNull())
  4. {
  5. img.Draw(pDC->m_hDC,CRect(0,0,100,100));
  6. }

EXAMPLE 2: 画在另一个位图中

[cpp] view plain copy
  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 plain copy
  1. inline HBITMAP CImage::Detach() throw()
  2. {
  3. HBITMAP hBitmap;
  4. ATLASSUME( m_hBitmap != NULL );
  5. ATLASSUME( m_hDC == NULL );
  6. hBitmap = m_hBitmap;
  7. m_hBitmap = NULL;
  8. m_pBits = NULL;
  9. m_nWidth = 0;
  10. m_nHeight = 0;
  11. m_nBPP = 0;
  12. m_nPitch = 0;
  13. m_iTransparentColor = -1;
  14. m_bHasAlphaChannel = false;
  15. m_bIsDIBSection = false;
  16. return( hBitmap );
  17. }

6 释放资源

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

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

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

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

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

[cpp] view plain copy
  1. inline CImage::~CImage() throw()
  2. {
  3. Destroy(); //释放掉所占用的位图资源
  4. s_initGDIPlus.DecreaseCImageCount();
  5. }

7 读写图像数据

主要用到3个函数 :

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

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

 
void* GetBits( ) throw( );
[cpp] view plain copy
  1. inline void* CImage::GetBits() throw()
  2. {
  3. ATLASSUME( m_hBitmap != NULL );
  4. ATLASSERT( IsDIBSection() );
  5. return( m_pBits );
  6. }

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 plain copy
  1. inline int CImage::GetPitch() const throw()
  2. {
  3. ATLASSUME( m_hBitmap != NULL );
  4. ATLASSERT( IsDIBSection() );
  5. return( m_nPitch );
  6. }

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

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 plain copy
  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 plain copy
  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 plain copy
  1. inline int CImage::GetBPP() const throw()
  2. {
  3. ATLASSUME( m_hBitmap != NULL );
  4. return( m_nBPP );
  5. }

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

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 plain copy
  1. inline HRESULT CImage::Save( LPCTSTR pszFileName, REFGUID guidFileType ) const throw()
  2. {
  3. if( !InitGDIPlus() )
  4. {
  5. return( E_FAIL );
  6. }
  7. UINT nEncoders;
  8. UINT nBytes;
  9. Gdiplus::Status status;
  10. status = Gdiplus::GetImageEncodersSize( &nEncoders, &nBytes );
  11. if( status != Gdiplus::Ok )
  12. {
  13. return( E_FAIL );
  14. }
  15. USES_CONVERSION_EX;
  16. Gdiplus::ImageCodecInfo* pEncoders = static_cast< Gdiplus::ImageCodecInfo* >( _ATL_SAFE_ALLOCA(nBytes, _ATL_SAFE_ALLOCA_DEF_THRESHOLD) );
  17. if( pEncoders == NULL )
  18. return E_OUTOFMEMORY;
  19. status = Gdiplus::GetImageEncoders( nEncoders, nBytes, pEncoders );
  20. if( status != Gdiplus::Ok )
  21. {
  22. return( E_FAIL );
  23. }
  24. CLSID clsidEncoder = CLSID_NULL;
  25. if( guidFileType == GUID_NULL )
  26. {
  27. // Determine clsid from extension
  28. clsidEncoder = FindCodecForExtension( ::PathFindExtension( pszFileName ), pEncoders, nEncoders );
  29. }
  30. else
  31. {
  32. // Determine clsid from file type
  33. clsidEncoder = FindCodecForFileType( guidFileType, pEncoders, nEncoders );
  34. }
  35. if( clsidEncoder == CLSID_NULL )
  36. {
  37. return( E_FAIL );
  38. }
  39. LPCWSTR pwszFileName = T2CW_EX( pszFileName, _ATL_SAFE_ALLOCA_DEF_THRESHOLD );
  40. #ifndef _UNICODE
  41. if( pwszFileName == NULL )
  42. return E_OUTOFMEMORY;
  43. #endif // _UNICODE
  44. if( m_bHasAlphaChannel )
  45. {
  46. ATLASSUME( m_nBPP == 32 );
  47. Gdiplus::Bitmap bm( m_nWidth, m_nHeight, m_nPitch, PixelFormat32bppARGB, static_cast< BYTE* >( m_pBits ) );
  48. status = bm.Save( pwszFileName, &clsidEncoder, NULL );
  49. if( status != Gdiplus::Ok )
  50. {
  51. return( E_FAIL );
  52. }
  53. }
  54. else
  55. {
  56. Gdiplus::Bitmap bm( m_hBitmap, NULL );
  57. status = bm.Save( pwszFileName, &clsidEncoder, NULL );
  58. if( status != Gdiplus::Ok )
  59. {
  60. return( E_FAIL );
  61. }
  62. }
  63. return( S_OK );
  64. }
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 plain copy
  1. Copy Code
  2. // Demonstrating saving various file formats
  3. int _tmain(int argc, _TCHAR* argv[])
  4. {
  5. CImage myimage;
  6. // load existing image
  7. myimage.Load("image.bmp");
  8. // save an image in BMP format
  9. myimage.Save("c:\image1.bmp");
  10. // save an image in BMP format
  11. myimage.Save("c:\image2",ImageFormatBMP);
  12. // save an image in JPEG format
  13. myimage.Save("c:\image3.jpg");
  14. // save an image in BMP format, even though jpg file extension is used
  15. myimage.Save("c:\image4.jpg",ImageFormatBMP);
  16. return 0;
  17. }

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

[cpp] view plain copy
  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();

Cimage类的介绍及使用相关推荐

  1. CImage类的介绍与使用

    CImage类的介绍与使用 程序代码下载处:http://download.csdn.net/source/2098910 下载处:http://hi.baidu.com/wangleitongxin ...

  2. 【图像处理】CImage类的简单应用

    CImage类的介绍与使用    CImage类是ATL和MFC共用的一个类,其头文件为atlimage.h,主要用于图片文件的打开,显示与保存.这里需要注意的是,在VS2010和VS2012的MFC ...

  3. CImage类的使用介绍!

    链接参考:http://www.cnblogs.com/juncheng/articles/1600730.html CImage是MFC和ATL共享的新类,它能从外部磁盘中调入一个JPEG.GIF. ...

  4. 【Visual C++】游戏开发笔记十四 游戏画面绘图(四) 华丽的CImage类

    本系列文章由zhmxy555编写,转载请注明出处. http://qianmo.blog.51cto.com/5127279/875711 作者:毛星云 邮箱: happylifemxy@qq.com ...

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

    CImage类 Visual C++的CBitmap类的功能是比较弱的,它只能显示出在资源中的图标.位图.光标以及图元文件的内容,而不像VB中的Image控件可以显示出绝大多数的外部图像文件(BMP. ...

  6. 用CImage类来显示PNG JPG等图片

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 系统环境 ...

  7. CImage类 from http://blog.sina.com.cn/s/blog_487547aa0100an6k.html

    CImage类(一)     学习图像处理一年了,一直没能做出一个像样的VC图像处理程序,主要因为没能弄懂别人写的CDib类.前不久听说Visual Studio.net2003里新加了个专门用于图像 ...

  8. MFC中CImage类显示的半透明PNG存在的问题以及处理方法

    在MFC中自己也做过很多关于如何实现图片半透明的方法,包括抠图,图像数据计算等,但是使用MFC中CImage的时候有时候是透明的,有时候透明部分为白色!让人难以置信,最后在不经意间发现了这边文章才恍然 ...

  9. CImage类之GetBits、GetPixel、GetPitch、GetBPP应用

    CImage类之GetBits.GetPitch.GetPixel.GetBPP应用 函数介绍 GetBits void* GetBits() throw(); 获取一个指向位图的实际内存地址的指针. ...

  10. 【无标题】c++ MFC图像处理CImage类常用操作代码

    原文作者:aircraft 原文地址:https://www.cnblogs.com/DOMLX/p/9598974.html 我看了一下发现关于c++下的CImage图像处理类 的图像处理相关的介绍 ...

最新文章

  1. js中window.location.search的用法和作用
  2. 3dContactPointAnnotationTool开发日志(二十)
  3. Web安全的三个攻防姿势
  4. 低价购买(洛谷 1108)
  5. JS之检索子字符串的search方法
  6. 与「韦神」齐名,他35岁任教清华!18岁一战成名,数学界颜值巅峰
  7. mysql python连接时、指定的ip地址被转接了_pythonmysql.connector模块使用了错误的IP地址...
  8. Python结合Tableau,万字长文搞定传统线下连锁店数据分析
  9. UVA10190 Divide, But Not Quite Conquer!【等差数列】
  10. 大数据分析技术有什么特点
  11. Kotlin的魔能机甲——KtArmor插件篇(二)
  12. antDesign 自定义分页样式
  13. 两码一号:整体方案回顾
  14. 会编程的都来玩玩这个游戏吧,看看你的编程水平.
  15. Spring Boot 异步线程静态获取request对象为空 RequestContextHolder 为空 Java 异步线程获取request为空
  16. flv.js php,B站视频开源代码flv.js+HTML5无flash播放视频
  17. 如何看一篇文章的分数
  18. 【Linux】冯诺依曼体系结构与操作系统概念理解
  19. matlab自带函数实现高斯滤波
  20. 计算机实习日记第一天

热门文章

  1. Solaris系统下修改IP地址
  2. Java | ProGuard——java代码混淆利器
  3. Java合并两个有序数组
  4. c语言输入的代码格式错误的是什么意思,详解输入输出格式(C语言代码)
  5. “斗”转星移,高精度(NTP网络授时)北斗授时系统
  6. gps高斯utm_UTM坐标系统与高斯
  7. 阿里笔试题解(2020.4.17场)
  8. CAD转JPG时设置转换质量
  9. JavaScript红宝书、犀牛书(2本)简介
  10. jdk1.8的新特性之--Rhion变为Nashorn