CImage类的介绍与使用
CImage类的介绍与使用
程序代码下载处:http://download.csdn.net/source/2098910
下载处:http://hi.baidu.com/wangleitongxing/blog/item/9063b03e5e20f3c97c1e71c8.html
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事件映射程序,并加入�下列代码:
程序代码:
void CEx_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函数处,加入�下列代码:
程序代码:
void CEx_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) 编译并执行。单击"打开"工具button,在弹出的对话框中指定一个图像文件后,单击"打开"button。
将图片用其他格式保存
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() //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来推断是否使用颜色表,若是则改动颜色表,否则直接将像素进行颜色设置。比如以下的代码:
程序代码:
void CEx_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=new RGBQUAD[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
}
CImage类的介绍与使用的更多相关文章
- CImage类的使用介绍!
链接参考:http://www.cnblogs.com/juncheng/articles/1600730.html CImage是MFC和ATL共享的新类,它能从外部磁盘中调入一个JPEG.GIF. ...
- 用CImage类来显示PNG、JPG等图片
系统环境:Windows 7软件环境:Visual Studio 2008 SP1本次目的:实现VC单文档.对话框程序显示图片效果 CImage 是VC.NET中定义的一种MFC/ATL共享类,也是A ...
- GDI 总结三: CImage类使用
前言 CImage类是基于GDI+的.可是这里为什么要讲归于GDI? 主要是基于这种考虑: 在GDI+环境中,我们能够直接使用GDI+ ,没多少必要再使用CImage类 可是,假设再 ...
- CImage类
CImage封装了DIB(设备无关位图)的功能,因而可以让我们能够处理每个位图像素.这里介绍GDI+和CImage的一般使用方法和技巧. TAG: GDI CImage 后处理 我们知道,Vi ...
- CImage类提供了GetBits()函数原理及实现
CImage类提供了GetBits()函数来读取数据区,GetBits()函数返回的是图片最后一行第一个像素的地址,网上有人说返回指针的起始位置是不同的,有些图片返回的是左上角像素的地址,有些是左下角 ...
- c++ MFC图像处理CImage类常用操作代码
原文作者:aircraft 原文地址:https://www.cnblogs.com/DOMLX/p/9598974.html MFC图像处理CImage类常用操作 CImage类头文件为#inclu ...
- 【VS开发】GDI+ 用CImage类来显示PNG、JPG等图片
系统环境:Windows 7 软件环境:Visual Studio 2008 SP1 本次目的:实现VC单文档.对话框程序显示图片效果 CImage 是VC.NET中定义的一种MFC/ATL共享类,也 ...
- 一个比CBitmap更优秀的类 -- CImage类
Visual C++的CBitmap类的功能是比较弱的,它只能显示出在资源中的图标.位图.光标以及图元文件的内容,而不像VB中的Image控件可以显示出绝大多数的外部图像文件(BMP.GIF.JPEG ...
- oc-12-NSString 类简单介绍及用法
// 11-[掌握]NSString 类简单介绍及用法 #import <Foundation/Foundation.h> int main(int argc, const char * ...
随机推荐
- 如何使用robots不让百度和google收录
如何使用robots不让百度和google收录 有没有想过,如果我们某个站点不让百度和google收录,那怎么办? 搜索引擎已经和我们达成一个约定,如果我们按约定那样做了,它们就不要收录. 这个写 ...
- android搭建环境错误 daemon not running. starting it now on port 5037 ADB server didn't ACK
android搭建环境错误 daemon not running. starting it now on port 5037 ADB server didn't ACK ADB server didn ...
- SPOJ1811最长公共子串问题(后缀自动机)
题目:http://www.spoj.com/problems/LCS/ 题意:给两个串A和B,求这两个串的最长公共子串. 分析:其实本题用后缀数组的DC3已经能很好的解决,这里我们来说说利用后缀自动 ...
- MySQl 存储过程+游标
DROP PROCEDURE IF exists pro_Insertflightplan_stat; create procedure pro_Insertflightplan_stat(exec ...
- Android滑动事件冲突
首先,我们假设这样一个场景:一个ViewPager里面嵌套一个ViewPager,内部滑动方向和外部滑动方向一样时,该怎么解决这一冲突呢? 针对滑动冲突这里给出两种解决方案:外部拦截法,内部拦截法. ...
- DLL运行时动态加加载的问题
1.error C2440: 'initializing' : cannot convert from 'int (__stdcall *)(void)' to 'void (__cdecl *)(c ...
- PHP自练项目中个人中心创建,修改,验证(服务器端和客户端验证)
当注册成功到登录后进入个人中心,查看和修改自己的资料 第一步:创建个人中心: <?php //定义个常量,用来授权调用includes里面的文件 define('IN_TG',true); // ...
- 谓词--Predicate
去苹果的的技术官网搜索-Predicate就会找到相关的文档-Predicate Programming Guide 1,创建谓词时 %@是变量时不加单双引号,常量是加单引号,加双引号需要转义符号\ ...
- Qt见解:Post 与 Get 的区别(Get将参数直接与网址整合为一个整体,而Post则将其拆为两个部分)
第一次接触Qt的Http项目,今天看了一下Post和Get的基本使用方法,就开始尝试了.原先以为Post专门用于向服务器发送请求,然后接收服务器应答的: 而Get只是单纯从服务器获取资源,比如下载这个 ...
- Uva 3226 Symmetry
题目给出一些点的坐标(横坐标,纵坐标),没有重叠的点,求是否存在一条竖线(平行于y轴的线),使线两边的点左右对称. 我的思路:对于相同的纵坐标的点,即y值相同的点,可以将x的总和计算出,然后除以点的数 ...