vc++加载透明png图片方法-GDI+和CImage两种

转载自:http://blog.csdn.net/zhongbin104/article/details/8730935

先看看GDI+的方法
方法1:

1.GDI+画透明图层(alpha)的png图片


stdafx加入如下:

#include //初始化一下com口 #include "GdiPlus.h" using namespace Gdiplus; #pragma comment(lib,"gdiplus.lib")

开始初始化:
在app类的声明里(.h)加入:

ULONG_PTR m_gdiplusToken;

InitInstance()里加入://若没有usingnamespace Gdiplus; 就要在前面加Gdiplus::

GdiplusStartupInput gdiplusStartupInput;
GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);

重载ExitInstance,加入GdiplusShutdown(m_gdiplusToken);

int CxxxApp::ExitInstance()
{ // TODO: 在此添加专用代码和/或调用基类 GdiplusShutdown(m_gdiplusToken); return CWinApp::ExitInstance();
}

显示图片的过程如下

CClientDC *pDC = new CClientDC(GetDlgItem(IDC_STATIC_PIC));
CRect rect;
GetDlgItem(IDC_STATIC_PIC)->GetWindowRect(&rect);
Graphics graphics(pDC->m_hDC); // Create a GDI+ graphics object Image image(_T("1.png")); // Construct an image graphics.DrawImage(&image, 0, 0, image.GetWidth(), image.GetHeight()); delete pDC;

这是用GDI+来显示图片。

2.CImage绘制带alpha透明图层的png图片


用MFC自带的CImage也可以显示,不过要稍微进行转换才能得到正常的带α通道的png图片!

在画图前进行一次转换,其中Image是CImage的对象

if (Image.GetBPP() == 32) //确认该图像包含Alpha通道 { int i; int j; for (i = 0; i < Image.GetWidth(); i++)
	{ for (j = 0; j < Image.GetHeight(); j++)
		{
			byte *pByte = (byte *)Image.GetPixelAddress(i, j);
			pByte[0] = pByte[0] * pByte[3] / 255;
			pByte[1] = pByte[1] * pByte[3] / 255;
			pByte[2] = pByte[2] * pByte[3] / 255;
		}
	}
}

具体方法如下:

HWND hwnd = GetSafeHwnd(); //获取窗口的HWND ::InvalidateRect( hwnd, NULL, true ); //或者 ::InvalidateRect( hwnd, NULL, false ); ::UpdateWindow(hwnd); //若使用前不想把原来绘制的图片去掉,可以删去上面那三段 CDC *pDC = GetDC();
CImage Image;
Image.Load(strPath); if (Image.IsNull())
{
	MessageBox(_T("没加载成功")); return -1;
} if (Image.GetBPP() == 32) //确认该图像包含Alpha通道 { int i; int j; for (i = 0; i < Image.GetWidth(); i++)
	{ for (j = 0; j < Image.GetHeight(); j++)
		{
			byte *pByte = (byte *)Image.GetPixelAddress(i, j);
			pByte[0] = pByte[0] * pByte[3] / 255;
			pByte[1] = pByte[1] * pByte[3] / 255;
			pByte[2] = pByte[2] * pByte[3] / 255;
		}
	}
}
Image.Draw(pDC->m_hDC, 0, 0);
Image.Destroy();
ReleaseDC(pDC);

代码中内部的框架是对图像的再次处理,对原来进行了修正,这样得到的更加正常,代码实测如下

绘图后效果

3.如果图片是在资源里的时候加载方法又不一样


这时需要两个函数,

对于GDI+如下:

BOOL ImageFromIDResource(UINT nID, LPCTSTR sTR,Image *&pImg)
{
	HINSTANCE hInst = AfxGetResourceHandle();
	HRSRC hRsrc = ::FindResource (hInst,MAKEINTRESOURCE(nID),sTR); // type if (!hRsrc) return FALSE; // load resource into memory DWORD len = SizeofResource(hInst, hRsrc);
	BYTE* lpRsrc = (BYTE*)LoadResource(hInst, hRsrc); if (!lpRsrc) return FALSE; // Allocate global memory on which to create stream HGLOBAL m_hMem = GlobalAlloc(GMEM_FIXED, len);
	BYTE* pmem = (BYTE*)GlobalLock(m_hMem);
	memcpy(pmem,lpRsrc,len);
	GlobalUnlock(m_hMem);
	IStream* pstm;
	CreateStreamOnHGlobal(m_hMem,FALSE,&pstm); // load from stream pImg=Gdiplus::Image::FromStream(pstm); // free/release stuff pstm->Release();
	FreeResource(lpRsrc);
	GlobalFree(m_hMem); return TRUE;
}

这时加载图片的代码变为:

CClientDC *pDC = new CClientDC(GetDlgItem(IDC_STATIC_PIC));
CRect rect;
GetDlgItem(IDC_STATIC_PIC)->GetWindowRect(&rect);
Graphics graphics(pDC->m_hDC); // Create a GDI+ graphics object Image *pimage; // Construct an image ImageFromIDResource(IDB_PNG1,_T("PNG"),pimage);
graphics.DrawImage(pimage, 0, 0,pimage->GetWidth(), pimage->GetHeight()); delete pDC;

CImage时需要如下函数:

BOOL LoadImageFromResource(CImage *pImage, UINT nResID,LPCTSTR lpTyp)
{ if ( pImage == NULL) return false;
	pImage->Destroy(); // 查找资源 HRSRC hRsrc = ::FindResource(AfxGetResourceHandle(), MAKEINTRESOURCE(nResID), lpTyp); if (hRsrc == NULL) return false; // 加载资源 HGLOBAL hImgData = ::LoadResource(AfxGetResourceHandle(), hRsrc); if (hImgData == NULL)
	{
		::FreeResource(hImgData); return false;
	} // 锁定内存中的指定资源 LPVOID lpVoid = ::LockResource(hImgData);
	LPSTREAM pStream = NULL;
	DWORD dwSize = ::SizeofResource(AfxGetResourceHandle(), hRsrc);
	HGLOBAL hNew = ::GlobalAlloc(GHND, dwSize);
	LPBYTE lpByte = (LPBYTE)::GlobalLock(hNew);
	::memcpy(lpByte, lpVoid, dwSize); // 解除内存中的指定资源 ::GlobalUnlock(hNew); // 从指定内存创建流对象 HRESULT ht = ::CreateStreamOnHGlobal(hNew, TRUE, &pStream); if ( ht != S_OK )
	{
		GlobalFree(hNew);
	} else { // 加载图片 pImage->Load(pStream);
		GlobalFree(hNew);
	} // 释放资源 ::FreeResource(hImgData); return true;
}

这时加载图片的代码如下:

HWND hwnd = GetSafeHwnd(); //获取窗口的HWND ::InvalidateRect( hwnd, NULL, true ); //或者 ::InvalidateRect( hwnd, NULL, false ); ::UpdateWindow(hwnd);
CDC *pDC = GetDC();
CImage Image;
LoadImageFromResource(&Image,IDB_PNG1,_T("PNG")); if (Image.IsNull())
{
	MessageBox(_T("没加载成功")); return;
} if (Image.GetBPP() == 32) //确认该图像包含Alpha通道 { int i; int j; for (i=0; i<image.getwidth(); i++)="" {="" <span="">for (j=0; j<image.getheight(); j++)="" {="" byte="" *pbyte="(byte" *)image.getpixeladdress(i,="" j);="" pbyte[<span="">0] = pByte[0] * pByte[3] / 255;
			pByte[1] = pByte[1] * pByte[3] / 255;
			pByte[2] = pByte[2] * pByte[3] / 255;
		}
	}
}
Image.Draw(pDC->m_hDC,0,0);
Image.Destroy();
ReleaseDC(pDC);

要注意的是,最好把绘图放在OnPaint消息响应里,否则,OnSize消息触发OnPaint重绘时可能会把之前的绘图全部清除

时间: 2024-10-26 21:41:08

vc++加载透明png图片方法-GDI+和CImage两种的相关文章

vc++加载透明png图片方法——GDI+和CImage两种

vc++加载透明png图片方法——GDI+和CImage两种 在加载png时遇到了麻烦,后来用了两个方法解决了.一个是用GDI+,另外就是用vs.net MFC自带的CImage. 先看看GDI+的方法 方法1: 1.GDI+画透明图层(alpha)的png图片 stdafx加入如下: #include <comdef.h>//初始化一下com口 #include "GdiPlus.h" using namespace Gdiplus; #pragma comment(li

VC下加载多种格式图片的方法总结IPicture, CxImage, CImage(AtlImage), CPictureEx

尽管VC有提供相应的API和类来操作bmp位图.图标和(增强)元文件,但却不支持jpg.gif和png等格式的图片,而这几种格式却是常常要用到的.这里我给大家介绍两种办法来操作这些格式的图片. 1.用API OleLoadPicture来加载JPG.GIF格式的图片(注:不支持PNG格式,另外GIF只能加载第一帧,且不支持透明) OleLoadPicture 函数实际上创建了一个IPicture类型的COM接口对象,然后我们可以通过这个COM接口来操作图片(实际上你也可以用API OleCrea

vc 加载bmp位图并显示的方法

方法一.显示位图文件 [cpp] view plaincopy HBITMAP hBitmap=(HBITMAP)LoadImage(NULL,_T("xxx.bmp"),Image_Bitmap,0,0,Lr_CreateDibSection|Lr_DefaultSize|Lr_LoadFromFile); //加载bmp文件   xxx.bmp 就是要加载的图片名字 CBitmap bitmap; bitmap.Attach(hBitmap); //关联位图对象 CDC dcima

加载透明图片

可以被FLASH动态加载的背景透明图片大致就GIF,PNG两种 先说说GIF图片,用普通的加载方法加载GIF图片完后只能看到动态图片的第一帧,由动态图变成静态的了 所幸有达人完美解决了这个问题,并封装好类供我们使用,这就是GIFPlayer.下载地址网上搜一下很多,要找不到也可以找我要 GIFPlayer使用示例 package{ /*  QQ: 334973991  */ import flash.net.URLRequest; import flash.display.Sprite; imp

图片懒加载插件lazyload使用方法

一.如何使用: Lazy Load 依赖于 jQuery.引入文件 <script type="text/javascript" src="jquery.js"></script> <script type="text/javascript" src="jquery.lazyload.js"></script> 图片基本属性的设置 <img class="lazy

cocos2dx中加载图片资源的方法,和从内存中获取已经加载的图片资源的方法

游戏中通常需要将常用的资源如:声音,图片,plist文件,提前加载进内存,以加快游戏的流畅度 1.预加载声音: SimpleAudioEngine::getInstance()->preloadBackgroundMusic("boom.mp3"); 加载之后就可以直接播放:SimpleAudioEngine::getInstance()->playBackgroundMusic("boom.mp3"); 2.预加载图片资源: 图片资源的加载分为同步加载

(android开源库android-gif-drawable)第二篇 加载网络gif图片

大家好,  今天给大家带来如何使用 android开源库android-gif-drawable来 加载网络gif图片 同样的DEMO下载地址在 最后 请大家去下载 . 如果gif图片地址无效 了.      请大家自行到网上去寻找一个 gif图片地址 复制过去就可以了.谢谢大家 不会在 eclipse下使用  (android开源库android-gif-drawable)     请看我的这篇博客   (android开源库android-gif-drawable)第一篇 eclipse使用

android客户端加载网络大图片如何避免内存溢出

在Android开发中加载sdcard上的大图片到内存时容易导致OOM异常,常见的解决办法是基于BitmapFactory.Options类提供的方法定义指定的解码方式,设置inJustDecodeBounds属性为true,避免分配内存,返回一个null的Bitmap对象(包含outWidth,outHeightandoutMimeType),然后读取图片的尺寸和类型.再根据屏幕的高和宽对图片进行缩放,最后将缩放的图片加载到内存,主要代码如下: 1 Options opts = new Opt

利用LruCache和DiskLruCache加载网络图片实现图片瀑布流效果(升级版)

MainActivity如下: package cc.patience7; import android.os.Bundle; import android.app.Activity; /** * Demo描述: * 采用瀑布流的形式加载大量网络图片 * 详细分析参见WaterfallScrollView * * 更新说明: * 在原本的的基础上添加了本地缓存DiskLruCache * * 所以在该示例中对于图片的缓存采用了:LruCache + DiskLruCache 的技术 * * 参考