I have a tiff file about 6 MB. When I open it the used memory is about 370 MB. That's OK.
When I close the image the memory is not freed. I cannot figure out why.
Since the image is so big I load it in a compatible context and copy it to context with BitBlt. This because quicker paintings. I load the file with gdiplus and copy data to a dib section and the closen the gdiplus.
Closing gdiplus reduces memory but remaining memory is not freed when the image is closed.
This is a simplified code snippet to show how I have done it.
LoadBitmapFromFile proc pFileName:dword
invoke GdiplusStartup,addr token,addr gdiSI,0
invoke MultiByteToWideChar,CP_ACP,0,pFileName,-1,addr buffer,sizeof buffer
invoke GdipLoadImageFromFile,addr buffer,addr ppImage
;Allocate memory for BITMAPINFOHEADER
mov eax,sizeof BITMAPINFOHEADER
invoke HeapAlloc,hHeap,HEAP_ZERO_MEMORY,eax
mov pBMI,eax
mov dword ptr[edi].BITMAPINFOHEADER.biSize,sizeof BITMAPINFOHEADER
invoke GdipGetImageHeight,ppImage,offset PixH
mov eax,PixH
mov dword ptr[edi].BITMAPINFOHEADER.biHeight,eax
invoke GdipGetImageWidth,ppImage,offset PixW
mov eax,PixW
mov dword ptr[edi].BITMAPINFOHEADER.biWidth,eax
invoke GdipGetImagePixelFormat,ppImage,addr PixelFormat
.if PixelFormat>=PixelFormat24bppRGB
mov word ptr[edi].BITMAPINFOHEADER.biBitCount,24
.endif
;calucate image size
mov dword ptr[edi].BITMAPINFOHEADER.biSizeImage,eax
mov word ptr [edi].BITMAPINFOHEADER.biPlanes,1
mov dword ptr[edi].BITMAPINFOHEADER.biCompression,BI_RGB
invoke GetDC,hBITMAP
mov hDC,eax
invoke CreateCompatibleDC,hDC
mov hCDC,eax
invoke CreateDIBSection,hDC,pBMI,DIB_RGB_COLORS,0,0,0
mov hDIB,eax
invoke SelectObject,hCDC,eax
mov hDIBObj,eax
invoke GdipCreateFromHDC,hCDC,addr graphics
invoke GdipDrawImageI,graphics,ppImage,0,0
invoke GdipBitmapLockBits,ppImage,addr rect,ImageLockModeRead,PixelFormat24bppRGB,offset pPixelData
invoke StretchDIBits,hCDC,0,0,PixW,PixH,0,0,PixW,PixH,pPixelData,pBMI,DIB_RGB_COLORS,SRCCOPY
invoke GdipBitmapUnlockBits,ppImage,offset pPixelData
invoke GdipDisposeImage,ppImage
invoke GdipDeleteGraphics,graphics
invoke GdiplusShutdown,token ;shutdown the GDI+ system
invoke RedrawWindow,hMain,0,0,RDW_INVALIDATE or RDW_ERASENOW or RDW_ALLCHILDREN
LoadBitmapFromFile endp
CloseBitmap proc
invoke HeapFree,hHeap,HEAP_NO_SERIALIZE,pBMI
invoke HeapFree,hHeap,HEAP_NO_SERIALIZE,pPixelData
invoke ReleaseDC,hBITMAP,hDC
invoke DeleteObject,hDIBObj
invoke DeleteObject,hDIB
invoke ReleaseDC,hBITMAP,hCDC
CloseBitmap endp
As I have understand it this should release all memory spaces for bitmap. Any ideas what could bee wrong
Best regards
Have you verify that all functions works well with a debugger ?
I don't see any controls on returned values ?
I was goint to answer yes I have, but hesitated. I have verifyed all returnvalues in LoadBitmapFromFile process but not in CloseBitmap proc. I have not have any problems there before so I neglected to check there. After doing that I discovered that pPixelData is not pointing to bitmap values.
I modified the code like this:
....
invoke CreateDIBSection,hDC,pBMI,DIB_RGB_COLORS,addr ppvBits,0,0
....
invoke GdipCreateFromHDC,hCDC,addr graphics
invoke GdipDrawImageI,graphics,ppImage,0,0
invoke GdipDisposeImage,ppImage ;release the image
invoke GdipDeleteGraphics,graphics ;release graphics
invoke GdiplusShutdown,token ;shutdown the GDI+ system
invoke RedrawWindow,hMain,0,0,RDW_INVALIDATE or RDW_ERASENOW or RDW_ALLCHILDREN
The image is drawn as usual and works fine. The pointer ppvBits is pointing to bitmap values. The memory should released by the system when the dib is deleted.
invoke DeleteObject,hDIBObj returns true.
invoke DeleteObject,hDIB returns true
invoke ReleaseDC,hBITMAP,hCDC returns false
invoke ReleaseDC,hBITMAP,hDC returns true.
The question is why hCDC is not released.
Since you create your DC, instead of getting an existing one, shouldn't you be using DeleteDC() ?
deletdc is the good answer
msdn citation
Quote
The CreateCompatibleDC function can only be used with devices that support raster operations. An application can determine whether a device supports these operations by calling the GetDeviceCaps function.
When you no longer need the memory device context, call the DeleteDC function to delete it.
Yes, the deletedc was the good answer. Thank you both.
Regards