News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Problem with close an image file.

Started by minor28, December 02, 2010, 01:12:13 PM

Previous topic - Next topic

minor28

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

ToutEnMasm

Have you verify that all functions works well with a debugger ?
I don't see any controls on returned values ?

minor28

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.

Slugsnack

Since you create your DC, instead of getting an existing one, shouldn't you be using DeleteDC() ?

ToutEnMasm

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.


minor28

Yes, the deletedc was the good answer. Thank you both.

Regards