CImage(MFC)
CImage类是ATL和MFC共用的一个类,其头文件为atlimage.h,主要用于图片文件的打开,显示与保存。这里需要注意的是,在VS2010 和VS2012的MFC编程中,不需要将头文件包含进来。MFC中要使用CImage类,必须先将头文件包含进来,可以包含在当前代码的CPP文件中,也可以包含在所属类的头文件中,不过最好还是包含在工程的stdafx.h文件中。CImage总共有39个成员函数,下面将在CImage的功能实现中慢慢讲解。
1、保存图片
保存图片只有一个函数,就是Save函数,该函数有两个参数,一个是文件的完整路径和文件名,一个是文件的扩展名。但是如果只有保存和显示图片功能,CImage的Save函数发挥不了太大的作用,不过是一个转存文件的工具。CImage的强大之处在于可以对图片进行修改,再进行保存。
修改图片的函数有这么3个函数可以修改图片,都是像素级的操作。这三个函数分别为SetPixel,SetPixelRGB,SetPixelIndexed。可以通过双重循环对屏幕进行逐点扫描,并把像素颜色值保存到CImage对象中达到截屏的目的。
我们可以用一段很简单的代码来实现将DC(设备上下文)里绘制的图形存入图片文件中。[2]基本的思想是先初始化一个CImage对象,再为它设定大小和位数,也就是图片大小和图片的色彩总数,再用设备上下文绘图。绘制完图形后再建立另外一个设备上下文对象,称为目的DC,将之前绘图的DC称为源DC,目的DC必须与CImage对象关联起来,然后利用BitBlt函数和其他函数将绘图DC的内容拷贝到目的DC中,最后将CImage对象保存到文件中,以下是代码实现(VS2010支持中文变量名):
1 CRect rect; 2 this->GetClientRect(rect); 3 CImage image; 4 image.Create(rect.Width(),rect.Height(),24); 5 CDC* DCpoint=this->GetDC(); 6 DCpoint->Ellipse(20,20,200,200); 7 CDC dstDC; 8 dstDC.CreateCompatibleDC(DCpoint); 9 dstDC.SelectObject(image); 10 dstDC.BitBlt(0,0,rect.Width(),rect.Height(),DCpoint,0,0,SRCCOPY); 11 image.Save(L"D:\\用户目录\\Pictures\\写图片文件.jpg");
2、显示图片
首先看下面这段代码
1 CImage image; 2 image.Load(L"D:\\用户目录\\Pictures\\example.jpg"); 3 image.Draw(GetDC()->m_hDC,CRect(0,0,320,240)); 4 CImage类支持以Load方法读取本地磁盘上的文件,并用Draw方法来显示图片。CIamge类的成员函数中还有很多可以实现显示图片。例如BitBlt办法。如以下代码: 5 image.BitBlt(GetDC()->m_hDC,0,0,320,240,0,0,SRCCOPY);
Bitblt方法同CDC类的Bitblt函数一样,是一比一地复制图像并显示在屏幕上,支持对源图像取反,也就是反色显示。这样功能通过BitBlt的最后一个参数来实现,比如参数为NOTSRCCOPY就是反色显示。
MaskBlt可以将图片与目的图片进行特殊的光栅操作并进行掩码处理。
PlgBlt函数可以将图片拉伸成平行四边形进行显示。
StretchBlt函数可以将图片进行拉伸显示。
3、创建图片
CImage的Creat函数和CreatEx函数用来创建空白图片,编程人员可以利用这个函数来创建图像,并添加代码让用户可以使用鼠标来改变CImage对象的像素颜色,以实现类似于windows画图的功能。
文章来源:百度百科(http://baike.baidu.com/view/5725174.htm?fr=wordsearch)
4、CImage显示透明PNG
在做项目的时候,需要用到透明的png格式的图片,使用CImage类是个不错的选择,但在使用该类的时候,发现显示出来的并不是透明背景的图片, 而且一些黑色边加一大片白色背景的图片,这是怎么回事呢?用ps来看的时候明明就是透明的。于是google一番,找到一些关于这类问题的看法:
以下为转述:
PNG 图片的透明背景总是一片白色,后来才发现这其实是微软GDI+的设计问题,PNG图片是ARGB,使用GDI+载入图片的时候,GDI+会默认已经进行了 预剩运算(PARGB),即每象素的实际值是已经和ALPHA值按比例相乘的结果,实际上它根本就没有做预乘,在使用透明图片的象素ALPHA通道的时 候,CImage内部正是调用的AlphaBlend,没有预乘的图当作预乘的图片处理的结果就是这相当于一张和纯白背景进行了预剩,所以图象总是出现白 色背景。
虽然找到了问题,但是还是要解决的。于是又google一番,使用如下代码来处理:
1 CImage img; 2 HRESULT result = img.Load(_T("(你的工作路径)//keys_base.png")); 3 for(int i = 0; i < img.GetWidth(); i++) 4 { 5 for(int j = 0; j < img.GetHeight(); j++) 6 { 7 unsigned char* pucColor = reinterpret_cast<unsigned char *>(img.GetPixelAddress(i , j)); 8 pucColor[0] = pucColor[0] * pucColor[3] / 255; 9 pucColor[1] = pucColor[1] * pucColor[3] / 255; 10 pucColor[2] = pucColor[2] * pucColor[3] / 255; 11 } 12 }