VC++如何将rc资源中的图片加载到MFC的CImage对象中(附源码)

       MFC中提供了处理图片的CImage类,可以加载.bmp.jpg.png.tif.gif等多种图片,然后通过DC绘制到窗口上。

VC++如何将rc资源中的图片加载到MFC的CImage对象中(附源码)_第1张图片

       CImage类支持通过路径加载图片,也可以从rc资源中去加载图片文件,但从资源加载图片时,除了bitmap位图类型之外,处理的都比较复杂,需要调用FindResource、SizeofResource、LoadResource、GlobalAlloc、GlobalLock、CreateStreamOnHGlobal等一系列接口将rc资源中的图片加载内存中,然后再加载到CImage对象中。

       对于png图片,考虑其像素中可能包含alpha透明通道,需要做个alpha预乘,因为CImage内部时调用API函数AlphaBlend去处理图片绘制的,AlphaBlend要求绘制前要做alpha通道预乘。

       将rc资源中图片加载到CImage对象中的代码实现如下:

CImage* LoadCImage( UINT nID, LPCTSTR lpszType, HINSTANCE hInstance )
{
	CImage* pImage = NULL;

	// 如果是位图类型,可以直接调用LoadFromResource去加载
	if( RT_BITMAP == lpszType )
	{
		pImage = new CImage();
		pImage->LoadFromResource( hInstance, nID );
		if ( !pImage->IsNull() )
		{
			return pImage;
		}
		else
		{
			WriteLog( _T("[LoadCImage]CImage::LoadFromResource失败") );

			delete pImage;
			pImage = NULL;
			return NULL;
		}
	}	

	CUIString strLog;
	HRSRC hRsrc = ::FindResource( hInstance, MAKEINTRESOURCE(nID), lpszType ); 
	ASSERT( hRsrc != NULL );
	if ( NULL == hRsrc ) 
	{
		WriteLog( _T("[LoadCImage]::FindResource失败") );
		return NULL;
	}

	DWORD dwSize = ::SizeofResource( hInstance, hRsrc );
	LPBYTE lpRsrc = (LPBYTE)::LoadResource( hInstance, hRsrc );
	ASSERT( lpRsrc != NULL );
	if ( NULL == hRsrc ) 
	{
		WriteLog( _T("[LoadCImage]::LoadResource失败") );
		return NULL;
	}

	HGLOBAL hMem = ::GlobalAlloc( GMEM_FIXED, dwSize );
	if ( NULL == hMem ) 
	{
		WriteLog( _T("[LoadCImage]::GlobalAlloc失败") );

		::FreeResource( lpRsrc );
		return NULL;
	}

	LPBYTE pMem = (LPBYTE)::GlobalLock( hMem );
	if ( NULL == pMem ) 
	{
		WriteLog( _T("[LoadCImage]::GlobalLock失败") );

		::GlobalUnlock( hMem );
		::GlobalFree( hMem );
		::FreeResource( lpRsrc );
		return NULL;
	}

	memcpy( pMem, lpRsrc, dwSize );
	IStream * pStream = NULL;
	HRESULT hr = ::CreateStreamOnHGlobal( hMem, FALSE, &pStream );
	if ( pStream != NULL && hr == S_OK ) 
	{
		pImage = new CImage();
		HRESULT hrs = pImage->Load( pStream );

		pStream->Release();

		//释放
		::GlobalUnlock( hMem );
		::GlobalFree( hMem );
		::FreeResource( lpRsrc );

		if ( hrs == S_OK )
		{
			if ( pImage->GetBPP() == 32 )
			{
				for(int i = 0; i < pImage->GetWidth(); i++)   
				{   
					for(int j = 0; j < pImage->GetHeight(); j++)   
					{   
						// 获取像素对应位置的RGB值的起始地址,如果作为一个整数值,从二进制的
						// 位构成来看,从高位到低位依次是alpha,b,g,r。如果从ARGB值的起始
						// 地址开始按字节逐个访问,低位存放在低内存地址上,所以pucColor[0]到
						// pucColor[3]依次是r,g,b,alpha,所以下面预乘的是pucColor[3]
						unsigned char* pucColor = reinterpret_cast( pImage->GetPixelAddress(i , j) ); 
						// CImage内部对带透明通道的图片的绘制,使用AlphaBlend来处理,AlphaBlend
						// 需要对rgb颜色进行alpha通道值预乘  
						pucColor[0] = pucColor[0] * pucColor[3] / 255;   
						pucColor[1] = pucColor[1] * pucColor[3] / 255;   
						pucColor[2] = pucColor[2] * pucColor[3] / 255;   
					}   
				}
			}

			return pImage;
		}
		else
		{
			delete pImage;
			pImage = NULL;
			return NULL;
		}
	}
	else
	{
		WriteLog( _T("[LoadCImage]::CreateStreamOnHGlobal失败") );

		::GlobalUnlock( hMem );
		::GlobalFree( hMem );
		::FreeResource( lpRsrc );
		return NULL;
	}
}

你可能感兴趣的:(VC++常用功能代码封装,rc资源,图片,加载,CImage)