CImage类的介绍与使用

程序代码下载处:http://download.csdn.net/source/2098910

下载处:http://hi.baidu.com/wangleitongxing/blog/item/9063b03e5e20f3c97c1e71c8.html

备注:这个程序是在xp系统,vs2008下做的,当初测试没出什么问题。

昨天(2014-11-11)我下了程序在win7下面测试,出现了评论里说的问题,解决方法我已经写在评论里面了。主要是因为路径的问题。大家参照着修改测下应该就没问题了。

Visual C++的CBitmap类和静态图片控件的功能是比较弱的,它只能显示出在资源中的图标、位图、光标以及图元文件的内容,而不像VB中的Image控件可以显示出绝大多数的外部图像文件(BMP、GIF、JPEG等)。因此,想要在对话框或其他窗口中显示外部图像文件则只能借助于第三方提供的控件或代码。现在,MFC和ATL共享的新类CImage为图像处理提供了许多相应的方法,这使得Visual C++在图像方面的缺憾一去不复返了。

CImage类概述

CImage是MFC和ATL共享的新类,它能从外部磁盘中调入一个JPEG、GIF、BMP和PNG格式的图像文件加以显示,而且这些文件格式可以相互转换。由于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封装了DIB(设备无关位图)的功能,因而可以让我们能够处理每个位图像素。它具有下列最酷特性:

1、AlphaBlend支持像素级的颜色混合,从而实现透明和半透明的效果。

2、PlgBlt能使一个矩形区域的位图映射到一个平行四边形区域中,而且还可能使用位屏蔽操作。

3、TransparentBlt在目标区域中产生透明图像,SetTransparentColor用来设置某种颜色是透明色。

4、MaskBlt在目标区域中产生源位图与屏蔽位图合成的效果。

使用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)在view类中添加成员变量CImage m_Image;

CEx_ImageView类添加ID_FILE_OPEN的COMMAND事件映射程序,并添加下列代码:

程序代码:

voidCEx_ImageView::OnFileOpen()//Cyan:添加

{

// TODO: 在此添加命令处理程序代码

CString strFilter;

CSimpleArray<GUID>aguidFileTypes;

HRESULT hResult;  //获取CImage支持的图像文件的过滤字符串

hResult=m_Image.GetExporterFilterString(strFilter,aguidFileTypes,_T("All Image Files"));

if(FAILED(hResult))

{

MessageBox(_T("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(_T("调用图像文件失败!"));

return;

}

//设置主窗口标题栏内容

CString str;

str.LoadString(AFX_IDS_APP_TITLE);

AfxGetMainWnd()->SetWindowTextW(str+_T("-")+dlg.GetFileName());

Invalidate();//强制调用OnDraw函数

}

(4)定位到CEx_ImageView::OnDraw函数处,添加下列代码:

程序代码:

voidCEx_ImageView::OnDraw(CDC*pDC)

{

CEx_ImageDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

//if (!pDoc)

//return;

// TODO: 在此处为本机数据添加绘制代码

// Cyan:添加

if(!m_Image.IsNull())

{

m_Image.Draw(pDC->m_hDC,0,0);

}

}

(5)打开Ex_ImageView.h文件,添加一个公共的成员数据m_Image:

程序代码:

public:   CImage m_Image;(Cyan:我觉得设置成私有成员比较好)

 (6)编译并运行。单击"打开"工具按钮,在弹出的对话框中指定一个图像文件后,单击"打开"按钮。

将图片用其它格式保存

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事件映射程序,并添加下列代码:

程序代码:

voidCEx_ImageView::OnFileSaveAs()  //Cyan:添加

{

// TODO: 在此添加命令处理程序代码

if(m_Image.IsNull())

{

MessageBox(_T("请打开要另存的图像!"));

return;

}

CString strFilter;

strFilter="bmp位图文件|*.bmp|JPEG图像文件|*.jpg|GIF图像文件|*.gif|PNG图像文件|*.png||";

CFileDialog dlg(FALSE,NULL,NULL,NULL,strFilter);

if(IDOK!=dlg.DoModal())

return;

//如果没有指定文件扩展名,则为其添加一个

CString strFileName,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+_T(".")+strExtension;

}

//图像保存

HRESULT hResult=m_Image.Save(strFileName);

if(FAILED(hResult))

{

MessageBox(_T("保存图像文件失败!"));

}

}

彩色图像转换成灰度图像

由于许多图像文件使用颜色表来发挥显示设备的色彩显示能力,因而将一张彩色图片变成黑色图片时需要调用CImage::IsIndexed来判断是否使用颜色表,若是则修改颜色表,否则直接将像素进行颜色设置。例如下面的代码:

程序代码:

voidCEx_ImageView::OnToGray()//Cyan:添加

{

// TODO: 在此添加命令处理程序代码

if(m_Image.IsNull())

return;

if(!m_Image.IsIndexed())

{

//直接修改像素颜色

COLORREF pixel;

int maxY=m_Image.GetHeight();

int maxX=m_Image.GetWidth();

byte r,g,b,avg;

for(int x=0;x<maxX;x++)

{

for(int y=0;y<maxY;y++)

{

pixel=m_Image.GetPixel(x,y);

r=GetRValue(pixel);

g=GetGValue(pixel);

b=GetBValue(pixel);

avg=(int)(((int)r+g+b)/3);

m_Image.SetPixelRGB(x,y,avg,avg,avg);

}

}

}

else

{

//获取并修改颜色表

int maxColors=m_Image.GetMaxColorTableEntries();

RGBQUAD* lpColorTable;

lpColorTable=newRGBQUAD[maxColors];

m_Image.GetColorTable(0,maxColors,lpColorTable);

for(int i=0;i<maxColors;i++)

{

int avg=(lpColorTable[i].rgbRed+lpColorTable[i].rgbGreen+lpColorTable[i].rgbBlue)/3;

lpColorTable[i].rgbRed=avg;

lpColorTable[i].rgbGreen=avg;

lpColorTable[i].rgbBlue=avg;

}

m_Image.SetColorTable(0,maxColors,lpColorTable);

delete(lpColorTable);

}

Invalidate();//强制调用OnDraw

}  

// 我是来自2017/1/11的作者,上面这个函数,访问图像数据的效率很低,访问图像数据,最好用数据指针,效率高

CImage类的介绍与使用相关推荐

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

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

  2. CImage类的使用介绍!

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

最新文章

  1. 源码推荐:collectionView拖拽,仿凤凰FM iOS 局部监听键盘再也不会挡住输入框
  2. JavaScript内存优化
  3. mysql定时执行存储过程
  4. 一般人不清楚--博士群体的择偶标准是什么?
  5. poj-1979 dfs
  6. AngularDart4.0 指南- 表单
  7. 短代码的java打地鼠_使用JavaScript实现网页版Pongo设计思路及源代码分享
  8. 摄像机成像公式、外参、内参(转载)
  9. 原生js制作PC端轮播图
  10. Navicat安装(一篇通解)
  11. 「Android - SoundPool使用」
  12. android 监听短信并发送到服务器
  13. Java课程设计-实验室预约管理系统
  14. 经济危机与金融危机的学术解释与通俗到庸俗的解释,包你明白
  15. 数学语言缩写 c连续d可导,数学分析(1)复习题
  16. Chrome 和 Edge 浏览器的一些User-Agent请求头
  17. 【Trie】vijos p1028 魔族密码
  18. 音乐播放,进度条,上一首下一首,暂停/播放
  19. docker修改端口映射,技术总监都拍手叫好
  20. 打造一流品质,路虎与固特异轮胎强强联手

热门文章

  1. Shell--常用小工具(sort、uniq、tr、cut)
  2. 2023 docker安装gitlab-ce
  3. Linux学习笔记05、CentOS 7的中文输入法设置
  4. 天堂2单机启动不了mysql_单机天堂2运行不了 求助
  5. 天堂2java环境变量修改办法2
  6. DSP程序 调试总结
  7. 红外图像处理算法介绍
  8. MySQL消费两次会员以及两次消费时间间隔
  9. 分享一波关于做Kaggle比赛,Jdata,天池的经验,看完我这篇就够了。
  10. 写一个手机“c语言编译器”能运行的贪吃蛇代码