Hi, I am very worried with this routine below. I have been working on it for many nights, trying to figure out why it runs out of memory.
I think I am doing everything correctly... but cannot say for sure. I have looked at many examples in this thread, and other places... but nothing seems to jump out at me at what I might be missing.
I don't know if there are additional things I need to 'reset' or clear out before the loop restarts...., that might be causing the problem of the script eventually crashing.
Thank you for anyone who can figure this out! This has me really stumped. I am disposing the bitmap, ... however, you'll notice %COUNT_SUM_PDATA% grows over time until the script crashes. I had about 50 decent sized PNG images in the folder, and a crash eventually happens!
You need to run this script, with
a_directory_with_some_pngfiles folder in the script directory. I threw about 3 dozen PNG image files that were between 250K-300K in size. The code loop below demonstrates processing of each image, from a file to a bitmap. Extra code comments are below.
Code:
; press a to test loop
a::
Loop
{
Gosub, PROCESS_IMAGE
Tooltip, LOOP DONE! <%COUNT_PROCESSED% PROCESSED>
}
Return
; ---------------------------------------------
; ---------------------------------------------
PROCESS_IMAGE:
; ----- setup test variables
COUNT_PROCESSED=0
COUNT_SUM_HDATA=0
COUNT_SUM_PDATA=0
COUNT_SUM_NSIZE=0
; ---------------------------------------------
Loop, a_directory_with_some_pngfiles\*.*
{
FileGetSize, dataSz , a_directory_with_some_pngfiles\%A_LoopFileName%
FileRead, BinData , a_directory_with_some_pngfiles\%A_LoopFileName%
hexData := Bin2Hex( &BinData, dataSz )
; ^ Convert Image To Hex Data
nSize := StrLen(hexData)//2
Hex2Bin(Buffer,hexData)
hData := DllCall("GlobalAlloc", UInt,2, UInt, nSize)
pData := DllCall("GlobalLock", UInt,hData)
DllCall( "RtlMoveMemory", UInt,pData, UInt,&Buffer, UInt,nSize)
DllCall( "GlobalUnlock", UInt,hData)
DllCall( "ole32\CreateStreamOnHGlobal", UInt,hData, Int,True, UIntP,pStream)
DllCall( "LoadLibrary", Str,"gdiplus" )
VarSetCapacity(si, 16, 0), si := Chr(1)
DllCall( "gdiplus\GdiplusStartup", UIntP,pToken, UInt,&si, UInt,0 )
DllCall( "gdiplus\GdipCreateBitmapFromStream", UInt,pStream, UIntP,bitmap)
DllCall(NumGet(NumGet(1*pStream)+8),Uint,pStream)
GDIplus_GetImageDimension(bitmap, WIDTH_OF_IMAGE, HEIGHT_OF_IMAGE)
DllCall( "gdiplus\GdipDisposeImage", UInt,bitmap)
;FileAppend, %COUNT_PROCESSED% - %HDATA% | %PDATA% | %NSIZE% > %WIDTH_OF_IMAGE% x %HEIGHT_OF_IMAGE%`n,TESTING_OUTPUT.TXT
; ^ Uncomment To See Each File Processed - If processing correctly we should see a %WIDTH_OF_IMAGE% x %HEIGHT_OF_IMAGE%
; - end of loop
COUNT_SUM_HDATA:=COUNT_SUM_HDATA+HDATA
COUNT_SUM_PDATA:=COUNT_SUM_PDATA+PDATA
COUNT_SUM_NSIZE:=COUNT_SUM_NSIZE+NSIZE
COUNT_PROCESSED++
}
FileAppend, %COUNT_SUM_HDATA% | > why does this var grow over time, until script crashes? ---> %COUNT_SUM_PDATA% <--- | %COUNT_SUM_NSIZE%`n,TESTING_OUTPUT.TXT
; ^ test output data
return
Here are the extra stock functions which make it all work

Code:
GDIplus_GetImageDimension(_image, ByRef @imageWidth, ByRef @imageHeight)
{
local r
#GDIplus_lastError =
r := DllCall("GDIplus.dll\GdipGetImageDimension"
, "UInt", _image
, "Float *", @imageWidth
, "Float *", @imageHeight)
If (r != #GDIplusOK)
{
#GDIplus_lastError := "GdipGetImageDimension (" . r . ": " . #GpStatus@%r% . ") " . ErrorLevel
}
@imageWidth := Floor(@imageWidth)
@imageHeight := Floor(@imageHeight)
Return r
}
/*
Bin2Hex() and Hex2Bin()
Machine code functions: Bit Wizardry [ By Laszlo Hars ]
Topic : http://www.autohotkey.com/forum/viewtopic.php?t=21172
Post : http://www.autohotkey.com/forum/viewtopic.php?p=180469#180469
*/
Bin2Hex(addr,len) { ; Bin2HexGOLD(&x,4)
Static fun
If (fun = "")
Hex2Bin(fun,"8B4C2404578B7C241085FF7E2F568B7424108A06C0E8042C0A8AD0C0EA05"
. "2AC2044188018A06240F2C0A8AD0C0EA052AC2410441468801414F75D75EC601005FC3")
VarSetCapacity(hex,2*len+1)
dllcall(&fun, "uint",&hex, "uint",addr, "uint",len, "cdecl")
VarSetCapacity(hex,-1) ; update StrLen
Return hex
}
Hex2Bin(ByRef bin, hex) { ; Hex2Bin(fun,"8B4C24") = MCode(fun,"8B4C24")
Static fun
If (fun = "") {
h:="568b74240c8a164684d2743b578b7c240c538ac2c0e806b109f6e98ac802cac0e104880f8"
. "a164684d2741a8ac2c0e806b309f6eb80e20f02c20ac188078a16474684d275cd5b5f5ec3"
VarSetCapacity(fun,StrLen(h)//2)
Loop % StrLen(h)//2
NumPut("0x" . SubStr(h,2*A_Index-1,2), fun, A_Index-1, "Char")
}
VarSetCapacity(bin,StrLen(hex)//2)
dllcall(&fun, "uint",&bin, "Str",hex, "cdecl")
}