Jump to content

GdipSaveImageToStream and Win 8.1


Andreik
 Share

Recommended Posts

Can someone try to call this function from gdiplus.dll on a Windows 8.1 machine and confirm that is working or not? I am pretty sure it worked well on other versions but now I still get this error:

 

+>16:15:55 Starting AutoIt3Wrapper v.14.801.2025.0 SciTE v.3.4.4.0   Keyboard:00000809  OS:WIN_81/  CPU:X64 OS:X64    Environment(Language:0809)

!>16:09:50 AutoIt3.exe ended.rc:-1073741819

 

A simple code for test can be this one:

#AutoIt3Wrapper_UseX64=n
#include <ScreenCapture.au3>
#include <Memory.au3>


_GDIPlus_Startup()

Local $hBitmap = _ScreenCapture_Capture('',0,0,-1,-1,False)
_GDIPlus_SaveImageToStream($hBitmap)
_GDIPlus_Shutdown()

Func _GDIPlus_SaveImageToStream($hBitmap, $iQuality = 50, $Encoder = "jpg") ;coded by Andreik, modified by UEZ, FS
    Local $tParams
    Local $tData
    Local $pData
    Local $pParams

    Local $sImgCLSID = _GDIPlus_EncodersGetCLSID($Encoder)
    Local $tGUID = _WinAPI_GUIDFromString($sImgCLSID)
    Local $pEncoder = DllStructGetPtr($tGUID)

    If $Encoder == "jpg" Or $Encoder == "jpeg" Then
        $tParams = _GDIPlus_ParamInit(1)
        $tData = DllStructCreate("int Quality")
        DllStructSetData($tData, "Quality", $iQuality) ;quality 0-100
        $pData = DllStructGetPtr($tData)
        _GDIPlus_ParamAdd($tParams, $GDIP_EPGQUALITY, 1, $GDIP_EPTLONG, $pData)
        $pParams = DllStructGetPtr($tParams)
    Else
        $pParams = 0
    EndIf

    Local $hStream = DllCall("ole32.dll", "uint", "CreateStreamOnHGlobal", "ptr", 0, "bool", True, "ptr*", 0)
    If @error Then Return SetError(1, 0, 0)
    $hStream = $hStream[3]
    DllCall($ghGDIPDll, "uint", "GdipSaveImageToStream", "ptr", $hBitmap, "ptr", $hStream, "ptr", $pEncoder, "ptr", $pParams)
    _GDIPlus_BitmapDispose($hBitmap)
    Local $hMemory = DllCall("ole32.dll", "uint", "GetHGlobalFromStream", "ptr", $hStream, "ptr*", 0)
    If @error Then Return SetError(2, 0, 0)

    $hMemory = $hMemory[2]
    Local $iMemSize = _MemGlobalSize($hMemory)
    Local $pMem = _MemGlobalLock($hMemory)

    $tData = DllStructCreate("byte[" & $iMemSize & "]", $pMem)
    Local $bData = DllStructGetData($tData, 1)
    Local $tVARIANT = DllStructCreate("word vt;word r1;word r2;word r3;ptr data;ptr")

    DllCall("oleaut32.dll", "long", "DispCallFunc", "ptr", $hStream, "dword", 8 + 8 * @AutoItX64, "dword", 4, "dword", 23, "dword", 0, "ptr", 0, "ptr", 0, "ptr", DllStructGetPtr($tVARIANT)) ;<a href='http://msdn.microsoft.com/en-us/library/windows/desktop/ms221473(v=vs.85' class='bbc_url' title='External link' rel='nofollow external'>http://msdn.microsoft.com/en-us/library/windows/desktop/ms221473(v=vs.85</a>).aspx
    _MemGlobalFree($hMemory)

    Return $bData
EndFunc   ;==>_GDIPlus_SaveImageToStream

When the words fail... music speaks.

Link to comment
Share on other sites

The crash occurs because you provide a GDI bitmap handle to the functions not a GDI+ bitmap handle.

Try this:

 

Local $hHBitmap = _ScreenCapture_Capture('',0,0,-1,-1,False)
Local $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hHBitmap)
_GDIPlus_SaveImageToStream($hBitmap)
_WinAPI_DeleteObject($hHBitmap)
_GDIPlus_BitmapDispose($hBitmap)
_GDIPlus_Shutdown()

I create this version some time ago which is based on your version:

Func _GDIPlus_StreamImage2BinaryString($hBitmap, $sFormat = "JPG", $iQuality = 80, $bSave = False, $sFilename = @ScriptDir & "\Converted.jpg") ;coded by UEZ 2013 build 2014-01-25; based on the code by Andreik
    Local $sImgCLSID, $tGUID, $tParams, $tData
    Switch $sFormat
        Case "JPG"
            $sImgCLSID = _GDIPlus_EncodersGetCLSID($sFormat)
            $tGUID = _WinAPI_GUIDFromString($sImgCLSID)
            $tData = DllStructCreate("int Quality")
            DllStructSetData($tData, "Quality", $iQuality) ;quality 0-100
            Local $pData = DllStructGetPtr($tData)
            $tParams = _GDIPlus_ParamInit(1)
            _GDIPlus_ParamAdd($tParams, $GDIP_EPGQUALITY, 1, $GDIP_EPTLONG, $pData)
        Case "PNG", "BMP", "GIF", "TIF"
            $sImgCLSID = _GDIPlus_EncodersGetCLSID($sFormat)
            $tGUID = _WinAPI_GUIDFromString($sImgCLSID)
        Case Else
            Return SetError(1, 0, 0)
    EndSwitch
    Local $hStream = _WinAPI_CreateStreamOnHGlobal() ;http://msdn.microsoft.com/en-us/library/ms864401.aspx
    If @error Then Return SetError(2, 0, 0)
    _GDIPlus_ImageSaveToStream($hBitmap, $hStream, DllStructGetPtr($tGUID), DllStructGetPtr($tParams))
    If @error Then Return SetError(3, 0, 0)

    Local $hMemory = _WinAPI_GetHGlobalFromStream($hStream) ;http://msdn.microsoft.com/en-us/library/aa911736.aspx
    If @error Then Return SetError(4, 0, 0)
    Local $iMemSize = _MemGlobalSize($hMemory)
    If Not $iMemSize Then Return SetError(5, 0, 0)
    Local $pMem = _MemGlobalLock($hMemory)
    $tData = DllStructCreate("byte[" & $iMemSize & "]", $pMem)
    Local $bData = DllStructGetData($tData, 1)
    _WinAPI_ReleaseStream($hStream) ;http://msdn.microsoft.com/en-us/library/windows/desktop/ms221473(v=vs.85).aspx
    _MemGlobalFree($hMemory)
    If $bSave Then
        Local $hFile = FileOpen($sFilename, 18)
        If @error Then Return SetError(6, 0, $bData)
        FileWrite($hFile, $bData)
        FileClose($hFile)
    EndIf
    Return $bData
EndFunc   ;==>_GDIPlus_StreamImage2BinaryString

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...