• vc++加载透明png图片方法——GDI+和CImage两种 ,vs2005 vs2008 PNG背景


    先看看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 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++)
    	{
    		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重绘时可能会把之前的绘图全部清除
  • 相关阅读:
    表单工具可以什么
    页面嵌套的方式展现报表
    EChars图类型
    SVG图类型
    JSP <c:import>和<jsp:include>区别【转】
    Servlet配置
    jsp的scope属性【转载】
    Cookie、Session【转载】
    page、request、session、application区别【转载】
    C++笔记------static 和 const 在类中用法
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13318768.html
Copyright © 2020-2023  润新知