利用CImage完成图片的显示、拷贝、绘制及转换图片格式

Windows C++图像处理:CImage类加载、保存与像素操作实战指南 在Windows C++开发中,图像处理是常见的需求,涉及图像的加载、保存、显示与像素级操作。其核心原理通常基于设备无关位图(DIB)和图形设备接口(GDI/GDI+),通过内存中的像素数据块进行高效读写。这项技术的价值在于为桌面应用提供了原生、轻量级的图像处理能力,无需引入庞大的第三方库,即可实现常见格式(如BMP、JPEG、PNG)的支持。在应用场景上,尤其适合MFC/ATL项目、需要生成独立exe的小型工具,以及对部署依赖敏感的内部应用。本文聚焦于Windows平台内置的CImage类,它正是基于GD 阅读详情

近日一个利用VC编写的程序需要在界面上显示图片,经过查阅资料利用CImage方得实现。将相关技术点整理如下,以供以后参考。

一、             图片的载入

如果需要在界面上显示的是已经存在的图片,那么需要将待显示的图片载入至CImage对象之中,CImage提供了四个载入函数:

 

HRESULT Load(LPCTSTR pszFileName) throw( );

HRESULT Load(IStream* pStream) throw();

void LoadFromResource(HINSTANCE hInstance, LPCTSTR pszResourceName) throw( );

void LoadFromResource(HINSTANCE hInstance, UINT nIDResource) throw( );

 

如果需要显示的图片在程序运行时需要更换则通常使用第一个函数Load(LPCTSTR pszFileName)载入图片,参数pszFileName指定要载入的图片文件;如果需要显示的图片是固定不变的,则通常使用第三个LoadFromResource(HINSTANCE hInstance, LPCTSTR pszResourceName)或第四个函数LoadFromResource(HINSTANCE hInstance, UINT nIDResource)载入图片,这两个函数是从资源中取得图片信息,每一个参数是包含有待载入图片的模块实例句柄,第二个参数是资源的ID或名称。

以下代码分别通过Load和LoadFromResource载入了图片:

 

CImage m_image1;        // 实际代码中,被声明成了类成员a

CImage m_image2;        // 实际代码中,被声明成了类成员

m_image1.Load("G://VC显示图片//PIC//aa.jpg");

m_image2.LoadFromResource(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP1));

  

二、             图片的显示

将图片载入CImage对象的目的是将其在界面之中显示出来,显示图像用到的核心函数是Draw,Draw提供了6个重载函数,通过参数名称,很容易了解参数的含义,其原型如下:

 

BOOL Draw(

   HDC hDestDC,

   int xDest,

   int yDest,

   int nDestWidth,

   int nDestHeight,

   int xSrc,

   int ySrc,

   int nSrcWidth,

   int nSrcHeight

) const throw( );

 

BOOL Draw(

   HDC hDestDC,

   const RECT& rectDest,

   const RECT& rectSrc

) const throw( );

 

BOOL Draw(

   HDC hDestDC,

   int xDest,

   int yDest

) const throw( );

 

BOOL Draw(

   HDC hDestDC,

   const POINT& pointDest

) const throw( );

 

BOOL Draw(

   HDC hDestDC,

   int xDest,

   int yDest,

   int nDestWidth,

   int nDestHeight

) const throw( );

 

BOOL Draw(

   HDC hDestDC,

   const RECT& rectDest

) const throw( );

 

如果要以控件的大小来显示图片,可以通过以下代码实现:

 

[cpp]  view plain copy
  1. if(m_image2.IsNull())    //判断有无图像  
  2.         return;  
  3.   
  4. // 取得客户区尺寸  
  5. CRect zcRect;  
  6. GetDlgItem(IDC_STATIC_PIC2)->GetClientRect(&zcRect);  
  7.   
  8. // 将图像显示在界面之上  
  9. m_image2.Draw(GetDlgItem(IDC_STATIC_PIC2)->GetDC()->m_hDC,  
  10.                             zcRect.left,  
  11.                             zcRect.top,  
  12.                             zcRect.Width(),  
  13.                             zcRect.Height());  

 

如果希望以图像原图大小显示图像,则可以在显示图像之前通过SetWindowPos函数调整控件大小,使得图像可以以原始大小显示。以下代码演示了该情况:

 

[cpp]  view plain copy
  1. if(m_image1.IsNull())  
  2.     return;  
  3.   
  4. // 将整控件调整为与图像同一尺寸   
  5. GetDlgItem(IDC_STATIC_PIC)->SetWindowPos(NULL,  
  6.                     0,0,m_image1.GetWidth(), m_image1.GetHeight(),   
  7.                     SWP_NOMOVE);     
  8.   
  9. CRect zcRect;  
  10. GetDlgItem(IDC_STATIC_PIC)->GetClientRect(&zcRect);  
  11.   
  12. m_image1.Draw(GetDlgItem(IDC_STATIC_PIC)->GetDC()->m_hDC,  
  13.                             zcRect.left,  
  14.                             zcRect.top,  
  15.                             zcRect.Width(),  
  16.                             zcRect.Height());  
  

 

当然如果不在意控件尺寸必须与图像尺寸一致的话,也可以不调整控件尺寸,而直接在调用Draw方法时以图像尺寸来设定其第四个和第五个参数。

 

注意:显示出的图片在被其它窗口遮住以后,或者当前窗口最小化后,再次显示程序界面时刚才设定的图片将踪影全无,所以必须对它们进行重绘。因此可以将显示图片的代码放在一个单独的函数中,然后在OnPaint中进行调用(不知道有没有更简单的方法,希望知道的网友告诉我)。

 

三、             图片的拷贝

也可以利用CImage的BitBlt函数实现将一个图片拷贝至另一个图片之上,其效果相当于将一张图片放置于另一张图片之上。这个功能似乎不会经常用到。函数BitBlt的原型如下:

 

BOOL BitBlt(

   HDC hDestDC,

   int xDest,

   int yDest,

   DWORD dwROP = SRCCOPY

) const throw( );

BOOL BitBlt(

   HDC hDestDC,

   const POINT& pointDest,

   DWORD dwROP = SRCCOPY

) const throw( );

BOOL BitBlt(

   HDC hDestDC,

   int xDest,

   int yDest,

   int nDestWidth,

   int nDestHeight,

   int xSrc,

   int ySrc,

   DWORD dwROP = SRCCOPY

) const throw( );

BOOL BitBlt(

   HDC hDestDC,

   const RECT& rectDest,

   const POINT& pointSrc,

   DWORD dwROP = SRCCOPY

) const throw( );

 

例如,希望将image2中存储的图像拷贝至image1中,可以通过以下代码实现:

 

m_image2.BitBlt(m_image1.GetDC(),0,0);

 

执行上述代码后,需要重新在界面绘制m_image1,否则只有在重新界面时拷贝的效果才可以显现出来。

 

四、             在内存中绘图

有时候需要在界面上动态绘图,但是如果直接在界面上绘图可能会引发闪烁的问题,可以通过先在CImage对象中绘图,然后将CImage对象显示于界面的方式降低这种感觉。假定m_image3是一个CImage对象,而我们需要画一个三角形然后将其在界面显示,可以通过以下代码完成。

 

[cpp]  view plain copy
  1. if(!m_image3.IsNull())  
  2. {  
  3.     m_image3.Destroy();   
  4. }  
  5.   
  6. m_image3.Create(100, 100, 32);  
  7.   
  8. HDC hdc = m_image3.GetDC();  
  9. CDC *pDC=new CDC;   
  10. pDC->Attach(hdc);  
  11. CPen penRed(PS_SOLID, 2, RGB(255,0,0));  
  12. CPen* oldPen = pDC->SelectObject(&penRed);  
  13. pDC->MoveTo(50, 10);  
  14. pDC->LineTo(10,90);  
  15. pDC->LineTo(90,90);  
  16. pDC->LineTo(50,10);  
  17. DeleteObject(pDC->SelectObject(oldPen));   
  18.   
  19. ReleaseDC(pDC);     
  20.   
  21. CRect zcRect;  
  22. GetDlgItem(IDC_STATIC_PIC3)->GetClientRect(&zcRect);  
  23. m_image3.Draw(GetDlgItem(IDC_STATIC_PIC3)->GetDC()->m_hDC,  
  24.                     zcRect.left,  
  25.                     zcRect.top,  
  26.                     zcRect.Width(),  
  27.                     zcRect.Height());  

 

五、             转换图片格式

通过CImage的Load函数可以导入多种格式的图片文件,或者我们也可以直接在内存中绘制出一张图画,这些图像信息最终可能需要转换成指定的图片压缩格式。利用CImage的Save函数完成这种转换是非常容易的。函数Save的原型如下:

 

HRESULT Save(

   IStream* pStream,

   REFGUID guidFileType

) const throw();

HRESULT Save(

   LPCTSTR pszFileName,

   REFGUID guidFileType= GUID_NULL

) const throw();

 

参数guidFileType指定了需要保存的结果类型,其允许的值及含义如下:

ImageFormatBMP   未压缩的位图

ImageFormatPNG   PNG压缩格式

ImageFormatJPEG  JPEG 压缩格式

ImageFormatGIF   GIF压缩格式

 

对于Save函数的第二种重载形式,也可以将guidFileType设定为GUID_NULL或者不设定(guidFileType将默认为GUID_NULL),此时Save函数将通过第一个参数pszFileName指定的文件名后缀的值来识别需要保存的格式。例如m_image1中导入的是JPEG格式的图片,通过以下代码,可以将其转换成后缀为.bmp的位图及后缀为.gif的GIF压缩格式图。

 

m_image1.Save("G://aa.bmp");

m_image1.Save("G://aa.gif");

 

欢迎访问梦断酒醒的博客http://www.yanzhijun.com

 

GDI 总结三: CImage类使用 若对您有所启发 欢迎打赏 古典小说网 致力于打造极致阅读体验 首创卡拉OK读书方式 首创,桌面大屏幕TXT阅读方式 前言 CImage类是基于GDI+的,但是这里为什么要讲归于GDI? 主要是基于这样的考虑: 在GDI+环境中,我们可以直接使用GDI+ ,没多少必要再使用CImage类 ... 阅读详情

相关推荐

VC++图片类型之间的相互转换(附源码)

上一篇文章我们说到了如何识别图片文件的真实类型,那本篇我们将讲述如何实现不同图片类类型的相互转换。

dvlinker的技术专栏 2916

CImage 类及其常用成员函数用法详解 二

本文像详细介绍了CImage的图像处理成员函数及其用法,并用示例演示了图像显示成员函数及其重载函数及图像保存等函数的用法,每一代码都经过实际编译验证过。

billliu66的博客 1838

MFC中基于CImage类在静态控件上显示图片

MFC中基于CImage类在静态控件上显示图片,我目前使用的是VS2012,不知道和其他编程版本上是否存在问题,如果存在兼容问题,也可以直接打开CImageBaseMfcDlg.cpp文件,直接查看程序,通过参考应该能够顺利实现在静态控件上显示想要的图片。

CImage 类

CImage提供增强的位图支持,包括加载和保存采用 JPEG、GIF、BMP 和可移植网络图形格式的图像 (PNG) 格式。 说明 无法在 Windows 运行时中执行的应用程序中使用此类及其成员。 语法 class CImage 成员 公共构造函数 公共构造函数 “属性” 说明 CImage::CImage 构造函数。 公共方法 公共方法 “属性” 说明 CImage::AlphaBlend 显示具有透明或半透明像素的位图。 CImage:.

顺其自然~专栏 2704

CImage的一般使用方法和技巧

CImage的一般使用方法和技巧 Visual C++的CBitmap类的功能是比较弱的,它只能显示出在资源中的图标、位图、光标以及图元文件的内容,而不像VB中的Image控件可以显示出绝大多数的外部图像文件(BMP、GIF、JPEG等)。如果想要在对话框或其他窗口中显示外部图像文件则只能借助于第三方提供的控件或代码,未免过于繁琐. 现在,.net引入了一个功能非常强大的新类 ----- CImage.有了CImage类,Visual C++在图像方面的缺憾将一去不复返。CImage是MFC和ATL共享的新类,它能从外部磁盘中调入一个JPEG、GIF、BMP和PNG格式的图像文件加以显示,而且这些文件格式可以相互转换。例如通过简单的几句,就可以实现CImage类和CBitmap类实例的:

高通410随身WiFi刷OpenWRT与Debian双系统一键集成方案

本文详细介绍高通410随身WiFi设备刷入OpenWRT与Debian双系统的一键集成方案。通过虎王工作室提供的一键刷机包,用户可轻松实现双系统部署,兼顾OpenWRT的网络功能与Debian的完整应用服务,适用于网络加速、服务器部署等多种场景,并提供了硬件资源分配与系统切换的实用指南。

docker7nomad的博客 1138

利用CImage完成图片的显示、拷贝、绘制及转换图片格式 .

近日一个利用VC编写的程序需要在界面上显示图片,经过查阅资料利用CImage方得实现。将相关技术点整理如下,以供以后参考。 一、             图片的载入 如果需要在界面上显示的是已经存在的图片,那么需要将待显示的图片载入至CImage对象之中,CImage提供了四

1455

UE4_后期处理六—夜视仪、扫描线

观察下面一组蓝图节点的效果:当把角色的自定义深度通道开启:画面效果如图:这样我们就得到了一个这样的黑白蒙版。

Growthofnotes的博客 1734

图形拷贝

利用CImage完成图片的显示、拷贝、绘制及转换图片格式    近日一个利用VC编写的程序需要在界面上显示图片,经过查阅资料利用CImage方得实现。将相关技术点整理如下,以供以后参考。一、             图片的载入如果需要在界面上显示的是已经存在的图片,那么需要将待显示的图片载入至CImage对象之中,CImage提供了四个载入函数: HRESULT Load(

sciencsongtiefei的专栏 612

【心得】Back trader避坑指南(一)——关于安装过程的问题

我认为一开始比较容易卡住的地方,主要是安装上面的问题。我给大家整理的这个版本是我能跑通的版本,还有一些好用的神器,手把手教你怎么装!

weixin_38347757的博客 1303

详细分析一下华为自研的MetaERP系统中的合并报表流程与规则

华为MetaERP合并报表系统针对其全球化复杂业务量身定制,采用五层自动化架构:统一数据采集、多币种转换、智能对账协同、规则化抵消处理及多维分析输出。系统核心在于可配置的智能规则引擎,涵盖股权合并范围、内部交易抵消、未实现利润计算等复杂场景,实现多准则并行处理。相比传统软件,该系统深度集成业务数据、支持准实时合并,并通过参数化配置快速适应组织变革,成为华为全球财务管控的"数字神经中枢",在效率、准确性和安全性上具有显著优势。

金牌架构师 673

VC++使用CImage在内存中Jpeg转换Bmp图片

VC++中Jpeg与Bmp图片格式互转应该是会经常遇到,Jpeg相比Bmp在图片大小上有很大优势。 本文重点介绍使用现有的CImage类在内存中进行转换,不需要保存为文件,也不需要引入第三方库。 Libjpeg库在8以后也支持了内存读取和转换,不过使用起来较为麻烦,还需要手动编译,用CImage类完全可以实现,代码更简洁。 实现方法: VC++对Jpeg、Png图片的操作主要使用CImag...

weixin_34310369的博客 279

基于simulink的低通滤波器(Low-pass Filter, LPF)

摘要:本文详细介绍了如何在Simulink中搭建低通滤波器进行噪声抑制仿真。通过定义系统需求(50Hz信号+250Hz噪声)、添加信号源、设计6阶巴特沃斯低通滤波器(截止频率100Hz)、连接各模块并配置仿真参数,最终实现高频噪声的有效滤除。该教程包含从模型创建到结果分析的完整流程,为信号处理系统开发提供了基础框架,并可进一步扩展为自适应滤波等高级应用。所需MATLAB版本为R2023a及以上,需安装Simulink和DSPSystemToolbox。

amy_mhd的博客 1303

PHP 缩放图片

对于网站前端上传的图片,在后台处理时有必要对其进行缩放以生成大小统一的缩略图。在PHP中,可以很方便的使用GD库来完成这一任务。下面的CImage类的静态方法CreateThumbnail()函数可以接受原图像文件名称,缩略图宽高,生成的缩略图文件名称等参数来生成保持原图纵横比的缩略图。函数基本上体现了PHP生成缩略图的方法,功能上还可以作进一步的扩充,如根据缩略图文件名称来生成指定格式的缩略图。

MoreWindows Blog 1万+

PLC为西门子的S7-1200,舵机为 DS3218,PLC控制舵机旋转程序实现?

🏆 本文收录于《全栈Bug调优(实战版)》专栏,致力于分享我在项目实战过程中遇到的各类Bug及其原因,并提供切实有效的解决方案。无论你是初学者还是经验丰富的开发者,本文将为你指引出一条更高效的Bug修复之路,助你早日登顶,迈向财富自由的梦想🚀!同时,欢迎大家关注、收藏、订阅本专栏,更多精彩内容正在持续更新中。让我们一起进步,Up!Up!Up!    备注: 部分问题/难题源自互联网,经过精心筛选和整理,结合数位十多年大厂实战经验资深大佬经验总结所得,数条可行方案供所需之人参考。

**My Coding Family** 999

泛微OA与泛微OA之间打通实现统一待办配置

问题:学校OA与集团OA均为泛微Ecology8.0 ,由于流程审批互通的需要,要将两套OA系统打通,实现跨系统的流程流转。

symstandsun的博客 2270

VC下加载多种格式图片的方法总结

From: http://www.cnblogs.com/Daywei/archive/2011/03/19/1988848.html 尽管VC有提供相应的API和类来操作bmp位图、图标和(增强)元文件,但却不支持jpg、gif和png等格式的图片,而这几种格式却是常常要用到的。这里我给大家介绍两种办法来操作这些格式的图片。 1.用API OleLoadPicture来加载JPG、G

JoeBlackZQQ的专栏 1758

YOLOv11改进策略【模型轻量化】| 替换骨干网络 CVPR-2024 RepViT 轻量级的Vision Transformers架构

本文记录的是基于RepVit的YOLOv11轻量化改进方法研究。RepVit的网络结构借鉴ViT的设计理念,通过分离的token mixe和减少推理时的计算和内存成本,同时减少扩展比率并增加宽度,降低延迟,并通过来弥补参数大幅减少的问题,提高了准确性。本文在替换骨干网络中配置了原论文中的和五种模型,以满足不同的需求。

Limiiiing的博客 2976

游戏开发笔记十四 游戏画面绘图(四) 华丽的CImage类

本系列文章由zhmxy555编写,转载请注明出处。 http://blog.youkuaiyun.com/zhmxy555/article/details/7422922 作者:毛星云 邮箱: happylifemxy@qq.com 欢迎邮件交流编程心得 我们知道,Visual C++中的CBitmap类的功能简直太弱小了,这曾经让Visual C

ATHENAMAX的专栏 877

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

MFC打印图片

需求描述:有一段程序生成了一个图片,但是没有打印图片的功能,现在要把这个功能加上去。 最终的代码实现如下: //add by slient begin void CBarcodeDlg::OnPrintPicture() { /*DWORD dwflags=PD_ALLPAGES|PD_NOPAGENUMS|PD_USEDEVMODECOPIES|PD_SELECTION|PD_HIDE

2096

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

上一篇: 使用GDI+屏幕截图内存中压缩为jpg
下一篇: BMP文件结构
wangluozhangleilei
博客等级 码龄16年 87粉丝 22原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值