使用MFC CImage類繪制PNG圖片時遇到的問題


 

 

原文鏈接: 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 )

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM