Visual studio 2010 翻转位图后正确释放资源
我有一个应用程序,它将非常大的数据集写入位图。[~500MB]我正在自上而下地编写数据补丁。由于BMP文件结构的性质,在写入磁盘后必须将其翻转。(我这样写是因为我假设翻转位图是一个常见的应用程序,我会找到库来完成这项任务) 我正在使用在internet上找到的代码片段来翻转位图。这个:Visual studio 2010 翻转位图后正确释放资源,visual-studio-2010,visual-c++,mfc,Visual Studio 2010,Visual C++,Mfc,我有一个应用程序,它将非常大的数据集写入位图。[~500MB]我正在自上而下地编写数据补丁。由于BMP文件结构的性质,在写入磁盘后必须将其翻转。(我这样写是因为我假设翻转位图是一个常见的应用程序,我会找到库来完成这项任务) 我正在使用在internet上找到的代码片段来翻转位图。这个: // GetInvertedBitmap - Creates a new bitmap with the inverted image // Returns - Handle to a new b
// GetInvertedBitmap - Creates a new bitmap with the inverted image
// Returns - Handle to a new bitmap with inverted image
// hBitmap - Bitmap to invert
// bLateral - Flag to indicate whether to invert laterally or vertically
HBITMAP CRisatImport::GetInvertedBitmap( HBITMAP hBitmap, BOOL bLateral )
{
// Create a memory DC compatible with the display
CDC sourceDC, destDC;
sourceDC.CreateCompatibleDC( NULL );
destDC.CreateCompatibleDC( NULL );
// Get logical coordinates
BITMAP bm;
::GetObject( hBitmap, sizeof( bm ), &bm );
// Create a bitmap to hold the result
HBITMAP hbmResult = ::CreateCompatibleBitmap(CClientDC(NULL),
bm.bmWidth, bm.bmHeight);
// Select bitmaps into the DCs
HBITMAP hbmOldSource = (HBITMAP)::SelectObject( sourceDC.m_hDC, hBitmap );
HBITMAP hbmOldDest = (HBITMAP)::SelectObject( destDC.m_hDC, hbmResult );
if( bLateral )
destDC.StretchBlt( 0, 0, bm.bmWidth, bm.bmHeight, &sourceDC,
bm.bmWidth-1, 0, -bm.bmWidth, bm.bmHeight, SRCCOPY );
else
destDC.StretchBlt( 0, 0, bm.bmWidth, bm.bmHeight, &sourceDC,
0, bm.bmHeight-1, bm.bmWidth, -bm.bmHeight, SRCCOPY );
// Reselect the old bitmaps
::SelectObject( sourceDC.m_hDC, hbmOldSource );
::SelectObject( destDC.m_hDC, hbmOldDest );
return hbmResult;
}
问题是我对上述代码的理解有限。我试图编写一个函数,尽可能地使用MSDN示例代码中的上述代码段。我认为我没有正确地释放所有资源。我似乎无法找出错误所在——主要是因为我对GDI缺乏了解。如果有人指出我做错了什么,我会非常感激
如果我尝试调用这个函数两次,程序就会崩溃——这就是为什么我怀疑我错误地释放了资源
这是我写的函数:
void CRisatImport::flipBitMapSaveAsJPG( CString outputFileName, CString outputJPGName, bool saveAsJpg)
{
// Flip the bitmap to correct odd file structure
HBITMAP hBitmap;
hBitmap = (HBITMAP)::LoadImage(NULL, outputFileName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
hBitmap = GetInvertedBitmap( hBitmap, FALSE );
CImage image;
image.Attach(hBitmap);
image.Save(outputFileName,Gdiplus::ImageFormatBMP);
if(saveAsJpg){
image.Save(outputJPGName,Gdiplus::ImageFormatJPEG);
}
image.Destroy();
DeleteObject( hBitmap );
}
我使用MFC和VS2010来实现这个应用程序——我有4GB的RAM,没有其他应用程序在运行
这是我得到的错误:
将位图句柄附加到CImage时,将句柄的生命周期责任移交给CImage,因此您不想在以后破坏它。但您也在为新位图使用相同的变量名。请尝试以下方法:
void CRisatImport::flipBitMapSaveAsJPG( CString outputFileName, CString outputJPGName, bool saveAsJpg)
{
// Flip the bitmap to correct odd file structure
HBITMAP hBitmapLoad = (HBITMAP)::LoadImage(NULL, outputFileName, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
HBITMAP hBitmapInverted = GetInvertedBitmap( hBitmapLoad , FALSE );
DeleteObject( hBitmapLoad );
CImage image;
image.Attach(hBitmapInverted );
image.Save(outputFileName,Gdiplus::ImageFormatBMP);
if(saveAsJpg){
image.Save(outputJPGName,Gdiplus::ImageFormatJPEG);
}
image.Destroy();
}
我不能测试它,但是GetInverterDBitMap的结果应该放在另一个位图变量中(最后也应该删除它)。实际上,您的代码中有2个位图。另外,由于您正在执行图像销毁,这将销毁附加的位图。代码中的哪个函数会触发断言?我认为image.save()会触发断言。您可能有一次机会分配500 MB的连续内存块,但不会有两次。虚拟内存地址空间碎片不会留下足够大的漏洞。与RAM无关。如今,64位操作系统已经不再是一个问题了。@HansPassant-我同意。我将不得不找到某种方式翻转位图补丁明智。你有没有一个策略?这就解决了资源问题。但事实是,系统无法同时分配500MB。它就像一个小图像的魅力。我必须找到某种方法以补丁方式翻转位图。