博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
vc++加载透明png图片方法-GDI+和CImage两种
阅读量:6948 次
发布时间:2019-06-27

本文共 4851 字,大约阅读时间需要 16 分钟。

 

转载自: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
for (j=0; j
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重绘时可能会把之前的绘图全部清除
 
 
 
 
 
 
你可能感兴趣的文章
51单片机交通灯(定时器+38译码器+中断)
查看>>
vue 总结
查看>>
深入理解java虚拟机(二):java内存溢出实战
查看>>
31.QPainter-rotate()函数分析-文字旋转不倾斜,图片旋转实现等待
查看>>
直接通过Binder的onTransact完成跨进程通信
查看>>
非域环境下使用证书部署数据库(SqlServer2008R2)镜像
查看>>
JavaScript Practices
查看>>
JS中如何alert对象
查看>>
MySQL的四种事务隔离级别
查看>>
创建maven工程的时候卡死的解决办法
查看>>
Eclipse将引用了第三方jar包的Java项目打包成jar文件的两种方法
查看>>
微信小程序保存图片功能实现
查看>>
【Shiro】小读Shiro Filter(未完待续)
查看>>
Android环信即时通讯集成坑爹 注册报错208解决
查看>>
Flink及主流流框架spark,storm比较
查看>>
mysql按位的索引判断位的值
查看>>
一套简约漂亮的响应式博客园主题皮肤
查看>>
异机环境不完全恢复
查看>>
程序员如何修炼管理思维
查看>>
js获取时间戳
查看>>