vc++加载透明png图片方法-GDI+和CImage两种
2015-07-06 14:49
831 查看
转载自:http://blog.csdn.net/zhongbin104/article/details/8730935
先看看GDI+的方法
方法1:
开始初始化:
在app类的声明里(.h)加入:
InitInstance()里加入://若没有usingnamespace Gdiplus; 就要在前面加Gdiplus::
重载ExitInstance,加入GdiplusShutdown(m_gdiplusToken);
显示图片的过程如下
这是用GDI+来显示图片。
具体方法如下:
代码中内部的框架是对图像的再次处理,对原来进行了修正,这样得到的更加正常,代码实测如下
绘图后效果
对于GDI+如下:
这时加载图片的代码变为:
用CImage时需要如下函数:
这时加载图片的代码如下:
另
要注意的是,最好把绘图放在OnPaint消息响应里,否则,OnSize消息触发OnPaint重绘时可能会把之前的绘图全部清除
先看看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重绘时可能会把之前的绘图全部清除
相关文章推荐
- C语言入门:03.关键字、标识符、注释
- 《C语言及程序设计》程序阅读——位运算及其应用
- C++编译器符号表有哪些内容?(程序员面试笔试笔记47页提到----符号表)
- c语言位运算有什么作用?
- C语言学习笔记:16_位运算
- [C语言]一个很实用的服务端和客户端进行UDP通信的实例
- 黑马程序员——C语言—结构体变量存储原理
- C语言学习笔记:15_c语言中的进制操作.c
- C++数组和指针
- C++变量和基本类型
- 1001. A+B Format (20)
- [LeetCode] Power of Two
- 队列的C++实现
- 值得推荐的C/C++框架和库(转)
- C++文件的读写操作
- C语言中strcpy,strcmp,strlen,strcat函数原型
- c++继承体系
- 研究实验一 搭建一个精简的C语言开发环境
- C++中inline函数详解
- C++学习小结之语句