HI,
I'm stuck with the array function of AudioGenie to get a picture from a file. Here is my code; Could you please help me?
To test you'll need AudioGenie3.dll, Gdi.ahk and a mp3 file with an included picture.
The code is basically the same as in this
post where it worked just fine.
Code:
OnExit, Exit
#Include, Gdip.ahk ;include GDI+
hAudioGenie3 := DllCall( "LoadLibrary", Str,"AudioGenie3.dll" ) ;load AudioGenie3
SS_BITMAP = 0xE
Gui, 1:Add, Picture, w500 h500 +%SS_BITMAP% vPctControl HwndhPctControl, ;control to hold the picture
Gui, 1:Show, AutoSize Center, Test ;normal AHK GUI
AudioGenie(hPctControl)
Return
AudioGenie(hPctControl){
global pToken
If (!pToken := Gdip_Startup()){ ; Start gdi+
MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
Return
}
mp3FileA := "test2.mp3" ;specify mp3 file
ATOU(mp3FileU,mp3FileA)
DllCall( "AudioGenie3\AUDIOAnalyzeFileW", Str,mp3FileU ) ;open mp3 file
;get MaxNumberOfAPIC Frames
APIC = 0x41504943 ;Frame ID "APIC" as Hex Number
FrameCountAPIC := DllCall("AudioGenie3\ID3V2GetFrameCountW", Int,APIC )
If (FrameCountAPIC < 1)
MsgBox, No Picture in MP3 file
MaxLen = 5000000 ;size of array in bytes; assume large picture
VarSetCapacity(PicAsBin, MaxLen, 0)
nSize := DllCall("AudioGenie3\ID3V2GetPictureArrayW", UInt,&PicAsBin, Int,MaxLen, Int,FrameCountAPIC)
If nSize < 0
MsgBox, % UTOA( DllCall("AudioGenie3\AUDIOGetLastErrorTextW") )
; NewSize := VarSetCapacity(PicAsBin, -1) ;<= doesn't work, it shrinks the var to much
; MsgBox, %nSize% %NewSize%
;testing binary data by writing it to file ;<= this works, picture is jpg and can be opened in image editor
; PicAsHex := Bin2Hex(&PicAsBin,nSize) ;convert it to hex
; FileName = B.jpg ;set temp file name
; BinWrite(FileName, PicAsHex) ;write hex data to binary temp file
hData := DllCall("GlobalAlloc", UInt,2, UInt,nSize) ;<= from here downwards somewhere is the mistake
pData := DllCall("GlobalLock", UInt,hData)
DllCall("RtlMoveMemory", UInt,pData, UInt,&PicAsBin, UInt,nSize)
DllCall("GlobalUnlock", UInt,hData)
DllCall("ole32\CreateStreamOnHGlobal", UInt,hData, Int,1, UIntP,pStream) ;Use COM
DllCall( "gdiplus\GdipCreateBitmapFromStream", UInt,pStream, UIntP,pBitmap )
DllCall( NumGet(NumGet(1*pStream)+8 ), UInt,pStream ) ;Release COM
hBitmap := Gdip_CreateHBITMAPFromBitmap(pBitmap)
SetImage(hPctControl, hBitmap)
; The bitmap we made from the image may be deleted
Gdip_DisposeImage(pBitmap)
DeleteObject(hBitmap)
}
GuiClose:
Esc::
Exit:
Gdip_Shutdown(pToken)
DllCall("FreeLibrary", UInt, hAudioGenie3)
ExitApp
Return
; by Laszlo
; www.autohotkey.com/forum/topic4546.html
BinWrite(file, data, n=0, offset=0)
{
; Open file for WRITE (0x40..), OPEN_ALWAYS (4): creates only if it does not exists
h := DllCall("CreateFile","str",file,"Uint",0x40000000,"Uint",0,"UInt",0,"UInt",4,"Uint",0,"UInt",0)
IfEqual h,-1, SetEnv, ErrorLevel, -1
IfNotEqual ErrorLevel,0,Return,0 ; couldn't create the file
m = 0 ; seek to offset
IfLess offset,0, SetEnv,m,2
r := DllCall("SetFilePointerEx","Uint",h,"Int64",offset,"UInt *",p,"Int",m)
IfEqual r,0, SetEnv, ErrorLevel, -3
IfNotEqual ErrorLevel,0, {
t = %ErrorLevel% ; save ErrorLevel to be returned
DllCall("CloseHandle", "Uint", h)
ErrorLevel = %t% ; return seek error
Return 0
}
TotalWritten = 0
m := Ceil(StrLen(data)/2)
If (n <= 0 or n > m)
n := m
Loop %n%
{
StringLeft c, data, 2 ; extract next byte
StringTrimLeft data, data, 2 ; remove used byte
c = 0x%c% ; make it number
result := DllCall("WriteFile","UInt",h,"UChar *",c,"UInt",1,"UInt *",Written,"UInt",0)
TotalWritten += Written ; count written
if (!result or Written < 1 or ErrorLevel)
break
}
IfNotEqual ErrorLevel,0, SetEnv,t,%ErrorLevel%
h := DllCall("CloseHandle", "Uint", h)
IfEqual h,-1, SetEnv, ErrorLevel, -2
IfNotEqual t,,SetEnv, ErrorLevel, %t%
Return TotalWritten
}
/*
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) { ; Bin2Hex(&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")
}
ATOU( ByRef Unicode, Ansi ) { ; Ansi to Unicode
VarSetCapacity( Unicode, (Len:=StrLen(Ansi))*2+1, 0 )
Return DllCall( "MultiByteToWideChar", Int,0,Int,0,Str,Ansi,UInt,Len, Str,Unicode, UInt,Len )
}
UTOA( pUnicode ) { ; Unicode to Ansi
VarSetCapacity( Ansi,(nSz:=DllCall( "lstrlenW", UInt,pUnicode )+1) )
DllCall( "WideCharToMultiByte", Int,0, Int,0, UInt,pUnicode, UInt,nSz
, Str,Ansi, UInt,nSz+1, Int,0, Int,0 )
Return Ansi
}
EDIT: Found the problem. Forgot to start the GDI..... It's working now