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重繪時可能會把之前的繪圖全部清除



 
 
 
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM