原文鏈接: http://blog.csdn.net/chenlycly/article/details/9193143
為了測試CImage繪制PNG圖片的效果,我們用截圖軟件截得一張360的界面,然后使用PhotoShop等工具在圖片的周邊加上了透明的區域,然后保存成PNG圖片文件。CImage首先從文件中加載,即
CImage* m_pImgBk;
......
m_pImgBk = new CImage;
m_pImgBk->Load( _T("res\\bk.png"));
if ( m_pImgBk->IsNull() ) // 圖片加載失敗
{
delete m_pImgBk;
m_pImgBk = NULL;
}
然后再到測試對話框的OnPaint中繪制,即
void CTestCImageDrawDlg::OnPaint()
{
CDialogEx::OnPaint();
CWindowDC dc(this);
if ( m_pImgBk != NULL )
{
m_pImgBk->Draw(dc.GetSafeHdc(), 30, 30, m_pImgBk->GetWidth(), m_pImgBk->GetHeight() );
}
}
結果發現了下面的一些問題。
1、直接使用CImage來繪制帶透明部分的PNG圖片,透明區域並沒有透掉(非縮放)
按照圖片的原始尺寸繪制到測試對話框界面上,結果透明區域沒有透掉,代碼如下所示。
CWindowDC dc(this);
if ( m_pImgBk != NULL )
{
ImgBk->Draw(dc.GetSafeHdc(), 30, 30, m_pImgBk->GetWidth(), m_pImgBk->GetHeight() );
}
顯示的效果圖如下所示。
經查閱,對於帶透明區域的PNG圖片需要做額外的處理,判斷是否啟用了Alpha透明通道,若啟用則要對之做如下處理:
if ( m_pImgBk->GetBPP() == 32 )
{
for(int i = 0; i < m_pImgBk->GetWidth(); i++)
{
for(int j = 0; j < m_pImgBk->GetHeight(); j++)
{
unsigned char* pucColor = reinterpret_cast<unsigned char *>(m_pImgBk->GetPixelAddress(i , j));
pucColor[0] = pucColor[0] * pucColor[3] / 255;
pucColor[1] = pucColor[1] * pucColor[3] / 255;
pucColor[2] = pucColor[2] * pucColor[3] / 255;
}
}
}
經處理該透掉的區域均被透掉,如下所示。
2、使用CImage::Draw直接繪制縮放的PNG圖片時,則顯示不全、失真嚴重
考慮到在某些情況下,要對PNG圖片進行縮放,所以對縮放繪制效果進行了測試。縮放時要做到長度和寬度的等比例縮放,相關代碼如下所示。
CWindowDC dc(this);
if ( m_pImgBk != NULL )
{
int nDstWidth = 450;
int nDstHeight = (int)( (nDstWidth*1.0/m_pImgBk->GetWidth())*m_pImgBk->GetHeight() ); // 寬和高等比例縮放
m_pImgBk->Draw(dc.GetSafeHdc(), 30, 30, nDstWidth, nDstHeight );
}
查閱MSDN,看是否有相關接口或參數能較好的處理這種縮放的問題。發現在CImage::Draw中可以添加Gdiplus::InterpolationMode的參數,GO過去看了一下,可以選用Gdiplus::InterpolationModeHighQuality高質量類型,發現縮放失真改善了許多,但本該透掉的透明部分卻變黑了,如下所示。
所以,CImage處理帶透明部分的PNG圖片,特別是縮放時是有缺陷的。后來改用gdi+的Image類,則沒有類似的問題。其實CImage內部也是使用gdi+實現的,具體為什么會出現上述問題上不明確。可以直接使用gdi+的Image類來處理PNG圖片。使用Image類是借助Gdiplus::Graphics來繪制的,即使用Image來加載圖片,使用Gdiplus::Graphics將Image中的圖片繪制到界面DC上,相關代碼如下所示。
Gdiplus::Graphics graphics( dc );
graphics.DrawImage( m_pImage, 30, 30, nDstWidth, nDstHeight )