vc++載入透明png圖片方法——GDI+和CImage兩種

來源:互聯網
上載者:User

這幾天放假在家無聊編一個程式,在載入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(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 objectImage image(_T("1.png")); // Construct an imagegraphics.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); // typeif (!hRsrc)return FALSE;// load resource into memoryDWORD len = SizeofResource(hInst, hRsrc);BYTE* lpRsrc = (BYTE*)LoadResource(hInst, hRsrc);if (!lpRsrc)return FALSE;// Allocate global memory on which to create streamHGLOBAL 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 streampImg=Gdiplus::Image::FromStream(pstm);// free/release stuffpstm->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 objectImage *pimage; // Construct an imageImageFromIDResource(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++){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);


另要注意的是,最好把繪圖放在OnPaint訊息響應裡,否則,OnSize訊息觸發OnPaint重繪時可能會把之前的繪圖全部清除

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.