vc++加载透明png图片方法.docx

上传人:b****1 文档编号:20190103 上传时间:2023-04-25 格式:DOCX 页数:15 大小:62.34KB
下载 相关 举报
vc++加载透明png图片方法.docx_第1页
第1页 / 共15页
vc++加载透明png图片方法.docx_第2页
第2页 / 共15页
vc++加载透明png图片方法.docx_第3页
第3页 / 共15页
vc++加载透明png图片方法.docx_第4页
第4页 / 共15页
vc++加载透明png图片方法.docx_第5页
第5页 / 共15页
点击查看更多>>
下载资源
资源描述

vc++加载透明png图片方法.docx

《vc++加载透明png图片方法.docx》由会员分享,可在线阅读,更多相关《vc++加载透明png图片方法.docx(15页珍藏版)》请在冰豆网上搜索。

vc++加载透明png图片方法.docx

vc++加载透明png图片方法

使用CImage画PNG,原本透明的图片,结果却显示白色/黑色底。

解决办法:

像素转换。

#includevoidCrossImage(CImage&img)//对像素进行转换

{

if (Image.GetBPP() == 32)

{

for(inti=0;i

{

for(intj=0;j

{

UCHAR*cr=(UCHAR*)img.GetPixelAddress(i,j);

cr[0]=cr[0]*cr[3]/255;

cr[1]=cr[1]*cr[3]/255;

cr[2]=cr[2]*cr[3]/255;

}

}

}

}//绘制pngCImageimg;

img.Load("res/smiling.png");

CrossImage(img);

img.AlphaBlend(dc,15,30);

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

在加载png时遇到了麻烦,后来用了两个方法解决了。

一个是用GDI+,另外就是用MFC自带的CImage。

先看看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);

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

绘图后效果

为了方便,封装成一个通用函数:

pWnd是需要显示图片的控件窗口,strPicPath是png图片地址,bAutoFit是否需要自动适应pWnd的窗口

[cpp] viewplaincopy

1.bool ShowPNGInCtrl(CWnd* pWnd,const CString& strPicPath,BOOL bAutoFit)  

2.{  

3.    if (NULL == pWnd)  

4.    {  

5.        return false;  

6.    }  

7.    if (NULL == pWnd->GetSafeHwnd())  

8.    {  

9.        return false;  

10.    }  

11.    if (strPicPath.GetLength()<=0)  

12.    {  

13.        return false;  

14.    }  

15.    try  

16.    {  

17.        CImage img;  

18.        CRect rect;  

19.        int nDPx(0),nDPy(0);//画图的起点  

20.        int nDw(0),nDh(0);//画图的宽和高  

21.        pWnd->GetClientRect(rect);     

22.        HRESULT hr;  

23.        hr = img.Load(strPicPath);  

24.        if (S_OK !

= hr)  

25.        {  

26.            return false;  

27.        }  

28.        std:

:

unique_ptr pDc;  

29.        pDc.reset(new CClientDC(pWnd));  

30.  

31.        if (bAutoFit)  

32.        {  

33.            if (img.GetWidth()>img.GetHeight())//说明图片是长方形  

34.            {  

35.                nDw  = rect.Width();  

36.                nDh  = (int)(nDw * img.GetHeight() / img.GetWidth());  

37.                nDPx = 0;  

38.                nDPy = (int)(rect.Height()/2.0 - nDh/2.0);  

39.                if (nDh>rect.Height())//说明图片控件是横着放,这时候就要再次缩减  

40.                {  

41.                    nDh  =rect.Height();  

42.                    nDw  =(int)( img.GetWidth()*nDh/img.GetHeight());  

43.                    nDPy = 0;  

44.                    nDPx =(int) (rect.Width()/2.0 - nDw/2.0);  

45.                }  

46.            }  

47.            else//说明竖着比较明显  

48.            {  

49.                nDh  = rect.Height();  

50.                nDw  =(int)( img.GetWidth()*nDh/img.GetHeight());  

51.                nDPy = 0;  

52.                nDPx =(int) (rect.Width()/2.0 - nDw/2.0);  

53.                if (nDw>rect.Width())//说明是另外一种情况  

54.                {  

55.                    nDw  = rect.Width();  

56.                    nDh  = (int)(nDw * img.GetHeight() / img.GetWidth());  

57.                    nDPx = 0;  

58.                    nDPy = (int)(rect.Height()/2.0 - nDh/2.0);  

59.                }  

60.            }  

61.        }  

62.        else  

63.        {  

64.            nDw = img.GetWidth();  

65.            nDh = img.GetHeight();  

66.        }  

67.        if (img.GetBPP() == 32) //确认该图像包含Alpha通道  

68.        {  

69.            int i;  

70.            int j;  

71.            for (i=0; i

72.            {  

73.                for (j=0; j

74.                {  

75.                    byte *pByte = (byte *)img.GetPixelAddress(i, j);  

76.                    pByte[0] = pByte[0] * pByte[3] / 255;  

77.                    pByte[1] = pByte[1] * pByte[3] / 255;  

78.                    pByte[2] = pByte[2] * pByte[3] / 255;  

79.                }  

80.            }  

81.        }  

82.  

83.        pDc->SetStretchBltMode(HALFTONE);  

84.        img.Draw(pDc->m_hDC,nDPx,nDPy,nDw,nDh);  

85.        //img.TransparentBlt(pDc->m_hDC,nDPx,nDPy,nDw,nDh,RGB(255, 255, 255));  

86.    }  

87.    catch (...)  

88.    {  

89.        return false;  

90.    }  

91.    return true;  

92.}  

 

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

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

{

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重绘时可能会把之前的绘图全部清除

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > PPT模板 > 商务科技

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1