首页 > 其他分享 >【转载】 CImage类使用

【转载】 CImage类使用

时间:2023-08-16 19:34:01浏览次数:30  
标签:NULL img int image hBitmap 使用 转载 CImage

原文: https://www.cnblogs.com/15157737693zsp/p/6015402.html

 

前言

         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  加载位图文件

 

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


2 与CBitmap转换

 

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


3 获得CImage对象的cdc

 

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


 

4 显示位图

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

   所使用的函数 BitBlt   StretchBlt  Draw等

   以Draw举例:

  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:

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


 

EXAMPLE 2: 画在另一个位图中

 

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


 

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

 

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


 

6 释放资源

 

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

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

 

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

 

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

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

  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( );
 
  1. inline void* CImage::GetBits() throw()  
  2. {  
  3.     ATLASSUME( m_hBitmap != NULL );  
  4.     ATLASSERT( IsDIBSection() );  
  5.   
  6.     return( m_pBits );  
  7. }  

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()

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


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

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()获得的指针指向第一行

 

图像数据首行地址:

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


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


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

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


 

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

 

一个综合例子:

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


 

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
)

 

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


 

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例子:

  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. }  
  18.    


 

 

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

 

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

标签:NULL,img,int,image,hBitmap,使用,转载,CImage
From: https://www.cnblogs.com/jiftle/p/17636007.html

相关文章

  • JFrog CLI 客户端的使用
    概述JFrogCLI是一个智能的命令行客户端工具,它提供了一个简单的交互界面,可以自动访问JFrog仓库,简化指令脚本,便于操作维护,使用更加高效和可靠。官方介绍https://jfrog.com/help/r/jfrog-cli/about-jfrog-cli系统平台CentOSLinux7下载工具官方下载链接: https://jfrog.com/getcli......
  • elementUI使用el-upload组件上传图片
    <el-form-itemlabel="上传图片":rules="[{required:true,message:'必须要上传图片',trigger:'blur'}]"prop="image"><el-upload:action=webSite......
  • vue的template中el-uplaod属性使用变量的方法
    template<el-form-itemlabel="上传图片":rules="[{required:true,message:'必须要上传图片',trigger:'blur'}]"prop="image"><el-upload:action=webSit......
  • 使用hutool封装的Excel工具类
    好用的工具类hutool工具类hutool操作excel这篇文章使用hutool的excel包封装项目中使用的excel工具类;引入包可以简单直接引入hutool-all,但是如果不用其他的话建议单独引入excel包<dependency><groupId>cn.hutool</groupId><artifactId>hutool-......
  • 【转载】c++调用win32API控制打印机打印
    原文:https://blog.csdn.net/cheng448208985/article/details/55510687win32实现将原始数据发送给打印机1、调用OpenPrinter()打开打印机,获取打印机句柄。2、初始化DOCINFO打印机结构体。3、调用StartDocPrinter()表明应用程序准备发送文档数据给打印机。4、调用StartPagePrin......
  • 全面了解JMeter响应断言的使用方法
    JMeter 是一个功能强大的性能测试工具,它可以模拟大量用户并发访问网站或应用程序,以测试其性能和稳定性。在进行性能测试时,我们需要对响应结果进行断言,以确保应用程序或网站的功能和性能符合预期。在JMeter中,响应断言是一种用于检查服务器响应是否符合预期的机制。JMeter提供了......
  • springmvc 使用 DeferredResult
    背景:需求:可以实时获取啄木鸟伍迪的访问数据、排名、积分等数据,可以实时现在在网站后台页面的大屏上;解决方案:可以使用异步请求,springmvc默认的请求都是同步的,也就是请求过去,必须得有处理完成,否则就回阻塞;异步请求是当发起一个请求,可以暂时没有响应,请求回被挂起不阻塞;请求过去,就......
  • 前端vue使用blob下载流文件
    请求后端接口,发现返回的是这么一堆东西 代码:axios:exportfunctionexportEcoCarAppoint(params){returnHttp({url:'/api/jsis/ecoCarAppoint/exportEcoCarAppoint',method:'POST',data:params,responseType:'blob',//设置响应......
  • 在Typora中使用AutoHotkey 2.0实现使用快捷键设置文本颜色
    使用Typora时不能设置文本颜色,总是觉得不方便,于是在网上搜索,发现有个小工具:AutoHotkey,编写脚本后,通过快捷键的方式可以设置Typora的文本颜色。下载软件到https://www.autohotkey.com/这个网址下载AutoHotkey并安装脚本实现网上很多实现方式都是基于AutoHotkeyv1.0、v1.1的,Au......
  • 使用idea进行开发
    使用idea进行开发使用步骤创建一个新的工程​ 自己的jdk安装目录输入工程名,模块名实际创建的样子其他在工程下创建其他模块创建完成创建一个Java文件注意,这里的前面两个是包名,最后一个.后面实际是.demo01.java的意思建立包快捷键创......