【windows gdi+】GDI+ Image类加载图片时异常问题处理与分析
問題描述:
項目里一個控件,需要加載本地圖片,單張第一次加載的時候可以的,但是重新選擇其他圖片,會出現圖片顯示異常的現象。
直接上圖,圖片部分顯示不全了。
問題分析:
一開始懷疑現象是有個圖片重復選擇后顯示是好的,其他某幾個圖很容易復現,就懷疑是圖片問題,查了半天jpg圖片完整性,發現圖片也沒什么區別,后面又查分辨率,在DrawImage()里修改分辨率為偶數了也不行。。。最后只能看代碼了,發現是代碼里自己清理GLOBAL內存了。其實之前有項目我遇到清理GLOBAL內存導致圖片顯示不全或者異常的問題。時間太久忘記了。還是記錄一下吧。
知識附錄:
1, 是Bitmap(RT_BITMAP)類型的圖片無法加載, RT_BITMAP是預定義類型, 資源里面沒有bmp文件的頭,?SizeofResource 的返回值要比圖片文件少幾個字節,因為少了這幾個字節, 所以GDI+會返回invalid parameter錯誤。
2, 從IStream里面創建出來的Image對象會引用到堆里面的GLOBAL內存, 如果GLOBAL內存hBuffer被釋放了, 創建的Image的內容就會被破壞,有時只能畫出一小部分圖片, 有時整個圖片有大片的亂碼,好像是編碼失敗的樣子, 視當時的內存狀況而定。
另外調用Image的Clone也沒用,深層次想Clone不是真正的深拷貝,還是依賴那個GLOBAL內存的,如果那個內存被銷毀了,Clone的圖片也會異常。
只有在銷毀或者析構的時候才能清理那個GLOBAL內存,否則會導致顯示異常(不是100%出現,而是間歇性出現,但是肯定會出現)。
這是看到的demo,拷貝過來的,可以看看,注意看注釋。
?CYourClass::~CYourClass() {for(IMG_VECTOR::iterator?it?=?m_arImage.begin();?it?!=?m_arImage.end();?it++)delete?*it;for(HGLB_VECTOR::iterator?it?=?m_arGlobal.begin();?it?!=?m_arGlobal.end();?it++){::GlobalUnlock(*it);::GlobalFree(*it);} }void?CYourClass::AddImage(HMODULE?hInst,?UINT?nResourceID,?LPCTSTR?lpType) {if(lpType?==?RT_BITMAP){//GDI+?can?not?load?RT_BITMAP?resouce,?//because?they?are?predefined?resource,?//they?don't?contains?the?image?file?header.assert(FALSE);return;}HRSRC?hResource?=?::FindResource(hInst,?MAKEINTRESOURCE(nResourceID),?lpType);if?(!hResource)return;DWORD?imageSize?=?::SizeofResource(hInst,?hResource);if?(!imageSize)return;const?void*?pResourceData?=?::LockResource(::LoadResource(hInst,?hResource));if?(!pResourceData)return;HGLOBAL?hBuffer?=?::GlobalAlloc(GMEM_FIXED,?imageSize);if?(NULL?==?hBuffer)return;void*?pBuffer?=?::GlobalLock(hBuffer);if?(pBuffer){CopyMemory(pBuffer,?pResourceData,?imageSize);IStream*?pStream?=?NULL;if?(::CreateStreamOnHGlobal(hBuffer,?FALSE,?&pStream)?==?S_OK){Gdiplus::Image?*?pImage?=?Gdiplus::Image::FromStream(pStream);pStream->Release();if?(pImage){?if?(pImage->GetLastStatus()?==?Gdiplus::Ok?&&pImage->GetWidth()?>?0){m_arImage.push_back(pImage);//it?seems?the?image?will?take?usage?of?the?global?memory.//so?the?global?memory?should?be?kept?until?the?image?destroy.//GDI++此種打開本地文件的方式占用了這片內存,只有在你銷毀圖片時才能銷毀這片 //內存,否則會破壞你的圖片,導致顯示異常m_arGlobal.push_back(hBuffer);return;}delete?pImage;}}::GlobalUnlock(hBuffer);}::GlobalFree(hBuffer); }?總結
以上是生活随笔為你收集整理的【windows gdi+】GDI+ Image类加载图片时异常问题处理与分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: if语句的一个错误记录,多了个“;”号
- 下一篇: 腾讯微博虽然停运,但其仍是一款成功的产品