原文地址:http://blog.163.com/zhengjiu_520/blog/static/3559830620094411431481/
去年开始处理图像时到现在一直有这样一个问题:如果打开一幅位24真彩色图像,进行各种处理,都没有问题,但如果不是真彩色图像,如黑白图、灰度图或伪彩色图,那么只能处理一次,再进行任何一种处理时都会弹出对话框提示:Debug Assertion Failed! File:wingdi.cpp Line:1120 For information on how your program can cause an assertion failure,see the Visual C++ documentation on asserts.
然后,我打开wingdi.cpp,定位到1120行,内容如下:
BOOL CGdiObject::Attach(HGDIOBJ hObject)
{
ASSERT(m_hObject == NULL); // only attach once, detach on destroy 1120行
if (hObject == NULL) return FALSE;
CHandleMap* pMap = afxMapHGDIOBJ(TRUE); // create map if not exist
ASSERT(pMap != NULL);
pMap->SetPermanent(m_hObject = hObject, this);
return TRUE;
}
HGDIOBJ CGdiObject::Detach()
{
HGDIOBJ hObject = m_hObject;
if (hObject != NULL)
{
CHandleMap* pMap = afxMapHGDIOBJ(); // don't create if not exist
if (pMap != NULL) pMap->RemoveHandle(m_hObject);
}
m_hObject = NULL;
return hObject;
}
我调试运G行时,打开调用堆栈,显示部分代码如下:
CGdiObject::Attach(void * 0x6f081467) line 1120 + 28 bytes
CPalette::CreatePalette(tagLOPALETTE * 0x0013f62c) line 431 + 26 bytes
CImageView2::CreateBitmapPalette(CDibImage * 0x00034d10 {CDibImage}) line 151
CImageView2::OnDraw(CDC * 0x0013fac8 {CPaintDC hWnd=0x00010b2e}) line 95 + 15 bytes
选中某一条,定位到各个函数,函数内容及定位的行如下:
void CImageView2::OnDraw(CDC* pDC)
{
CImageDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if( pDoc->statedoc==1 && state2==1 )
{
BYTE* pBitmapData = CDibNew1->GetData();
LPBITMAPINFO pBitmapInfo = CDibNew1->GetInfo();
int m_scale=1;
int bitmapHeight = CDibNew1->GetHeight();
int bitmapWidth = CDibNew1->GetWidth();
int scaledWidth = (int)(bitmapWidth * m_scale);
int scaledHeight = (int)(bitmapHeight * m_scale);
if (CDibNew1->GetRGB()) // Has a color table
{
CPalette * hPalette2=CreateBitmapPalette(CDibNew1);
CPalette * hOldPalette = pDC->SelectPalette(hPalette2, true);
pDC->RealizePalette();
::StretchDIBits(pDC->GetSafeHdc(),0, 0, scaledWidth, scaledHeight,
0, 0, bitmapWidth, bitmapHeight,
pBitmapData, pBitmapInfo,
DIB_RGB_COLORS, SRCCOPY);
pDC->SelectPalette(hOldPalette, true);
::DeleteObject(hPalette2);
}
else
{
StretchDIBits(pDC->GetSafeHdc(), 0, 0, scaledWidth, scaledHeight,
0, 0, bitmapWidth, bitmapHeight, pBitmapData, pBitmapInfo,
DIB_RGB_COLORS, SRCCOPY);
}
}
}
CPalette *CImageView2::CreateBitmapPalette(CDibImage *pBitmap)
{
CPalette hPalette;
struct
{
WORD Version;
WORD NumberOfEntries;
PALETTEENTRY aEntries[256];
} palette = { 0x300, 256 };
LPRGBQUAD pRGBTable = pBitmap->GetRGB();
UINT numberOfColors = pBitmap->GetNumberOfColors();
for(UINT x=0; x<numberOfColors; ++x)
{
palette.aEntries[x].peRed = pRGBTable[x].rgbRed;
palette.aEntries[x].peGreen = pRGBTable[x].rgbGreen;
palette.aEntries[x].peBlue = pRGBTable[x].rgbBlue;
palette.aEntries[x].peFlags = 0;
}
hPalette.CreatePalette((LPLOGPALETTE)&palette);
return &hPalette;
::DeleteObject(hPalette);
}
_AFXWIN_INLINE BOOL CPalette::CreatePalette(LPLOGPALETTE lpLogPalette)
{ return Attach(::CreatePalette(lpLogPalette)); }
通过红字部分的提示和我自己的分析,发现hPalette是全局变量,因为 // only attach once, detach on destroy ,所以在程序运行期间第一次处理时attach了,没有出错,第二次处理时,又要attach,但第一次处理完后还没有detach
,因为它是全局变量,程序结束时才销毁,也就是程序结束时才detach。所以,这样分析,问题就解决了,将hPalette设为局部变量,进入函数后,attach,走出函数时,变量销毁,便dettach。绿色代码是新加的。