Tested in XP SP3 32-Bit with AHK 1.0 and AHK_Lw 1.1
- Parameters:
Image : A handle to either GDI or GDIPlus Bitmap.
ICON is not supported owing to complex code required for Alpha transparency.
Buffer : Variable to hold raw image data.
Type : BMP DIB RLE JPG JPEG JPE JFIF GIF TIF TIFF PNG.
JPG is default
Quality : For JPG, pass a value from 0 to 100. For TIF pass 6, only if you required uncompressed image.
If a value is not passed, default compression will be applied
Note: GDI+ needs to be initialized before calling this function. I presume you already have gdip.ahk in UserLib
GdiPlus_SaveImageToBuffer( Image, ByRef Buffer, Type="JPG", nQuality="" ) { /* Code adapted by SKAN for Wicked, Created / Last Modified: 09-Oct-2012 http://www.autohotkey.com/community/viewtopic.php?&t=93472 Credit Sean: Screen Capture with Transparent Windows and Mouse Cursor http://www.autohotkey.com/community/viewtopic.php?t=18146 http://www.autohotkey.com/community/viewtopic.php?p=408135#p408135 How to convert Image data (JPEG/PNG/GIF) to hBITMAP ? http://www.autohotkey.com/community/viewtopic.php?p=147029#p147029 */ ; Test for GDI / GDIPlus bitmap If DllCall( "GetObjectType", UInt,Image ) = 7 DllCall( "gdiplus\GdipCreateBitmapFromHBITMAP", UInt,Image, UInt,0, UIntP,pBM ) Else If DllCall( "gdiplus\GdipGetImageType", UInt,Image, UIntP,ErrorLevel ) = 0 pBM := Image Else Return 0 ; Determine Encoder CLSID DllCall( "gdiplus\GdipGetImageEncodersSize", UIntP,nCount, UIntP,nSize ) VarSetCapacity( ci,nSize ) DllCall( "gdiplus\GdipGetImageEncoders", UInt,nCount, UInt,nSize, UInt,&ci ) Loop %nCount% { If ( ( pStr := NumGet( ci, Ix := 76 * (A_Index-1) + 44 ) ) && A_IsUnicode ) Extns := DllCall( "MulDiv", UInt,pStr, Int,1, Int,1, Str ) Else VarSetCapacity( Extns, nSize := DllCall( "lstrlenW", UInt,pStr ) + 1, 0 ) , DllCall( "WideCharToMultiByte", UInt,0, UInt,0, UInt,pStr, Int,-1, Str,Extns , Int,nSize, Int,0, Int,0 ) If ( ( Found := InStr( Extns, "*." Type ) ) && ( pEnc := &ci + Ix - 44 ) ) Break } IfLess, Found, 1, Return 0 ; Determine Encoder Parameters in case of JPG/TIF pEncP := 0 If ( InStr( ".JPG.JPEG.JPE.JFIF", "." . Type ) && nQuality <> "" ) { nQuality := ( nQuality < 0 || nQuality > 100 ) ? 75 : nQuality DllCall( "gdiplus\GdipGetEncoderParameterListSize", UInt,pBM, UInt,pEnc, UIntP,nSz ) VarSetCapacity( pi,nSz,0 ) DllCall( "gdiplus\GdipGetEncoderParameterList", UInt,pBM, UInt,pEnc, Int,nSz, UInt,&pi ) Loop % NumGet(pi) If ( NumGet( pi, 28*(A_Index-1)+20 ) = 1 && NumGet( pi, 28*(A_Index-1)+24 ) = 6 ) { pEncP := &pi + 28*(A_Index-1) NumPut( nQuality, NumGet( NumPut( 4, NumPut( 1,pEncP+0 ) + 20 ) ) ) Break } } Else If ( InStr( ".TIF.TIFF", "." . Type ) && nQuality <> "" ) { nQuality := ( nQuality < 2 || nQuality > 6 ) ? 6 : nQuality DllCall( "gdiplus\GdipGetEncoderParameterListSize", UInt,pBM, UInt,pEnc, UIntP,nSz ) VarSetCapacity( pi,nSz,0 ) DllCall( "gdiplus\GdipGetEncoderParameterList", UInt,pBM, UInt,pEnc, Int,nSz, UInt,&pi ) Loop % NumGet(pi) If ( NumGet( pi,28*(A_Index-1)+20 )=5 && NumGet( NumGet( pi,28*(A_Index-1)+28) )=2 ) { pEncP := &pi + 28*(A_Index-1) NumPut( nQuality, NumGet( NumPut( 1, NumPut( 1,pEncP+0) + 16 ) + 4 ) ) Break } } ; Save Image to Stream and copy it to Buffer DllCall( "ole32\CreateStreamOnHGlobal", UInt,0, Int,1, UIntP,pStream ) DllCall( "gdiplus\GdipSaveImageToStream", UInt,pBM, UInt,pStream, UInt,pEnc, UInt,pEncP ) DllCall( "gdiplus\GdipDisposeImage", UInt,pBM ) DllCall( "ole32\GetHGlobalFromStream", UInt,pStream, UIntP,hData ) pData := DllCall( "GlobalLock", UInt,hData ) nSize := DllCall( "GlobalSize", UInt,pData ) VarSetCapacity( Buffer, nSize, 0 ) DllCall( "RtlMoveMemory", UInt,&Buffer, UInt,pData, UInt,nSize ) DllCall( "GlobalUnlock", UInt,hData ) DllCall( NumGet( NumGet( 1*pStream ) + 8 ), UInt,pStream ) DllCall( "GlobalFree", UInt,hData ) Return nSize }
The older counter part:
GDIPlus_hBitmapFromBuffer()
GDIPlus_hBitmapFromBuffer( ByRef Buffer, nSize ) { ; Last Modifed : 21-Jun-2011 ; Adapted version by SKAN www.autohotkey.com/forum/viewtopic.php?p=383863#383863 ; Original code by Sean www.autohotkey.com/forum/viewtopic.php?p=147029#147029 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( "gdiplus\GdipCreateBitmapFromStream", UInt,pStream, UIntP,pBitmap ) DllCall( "gdiplus\GdipCreateHBITMAPFromBitmap", UInt,pBitmap, UIntP,hBitmap, UInt ,DllCall( "ntdll\RtlUlongByteSwap",UInt ,DllCall( "GetSysColor", Int,15 ) <<8 ) | 0xFF000000 ) DllCall( "gdiplus\GdipDisposeImage", UInt,pBitmap ) DllCall( NumGet( NumGet(1*pStream)+8 ), UInt,pStream ) ; IStream::Release Return hBitmap }On a related note:
MiniZIP.ahk - AutoHotkey Wrapper for minizip.dll
With MZ_ZipAddMem() you may write 'buffer converted screenshots' directly into a password protected zip file.