Jump to content
c.haslam

DllStructCreate not allocating memory for byte array?

Recommended Posts

In the code that follows, it appears that DllStructCreate() is not allocating memory in

$tag = 'byte val['&$iLength&']'
.
.
Static Local $tvalue = DllStructCreate($tag)

Running the code below, the problem does not show, but it does show in a much longer script: there _GDIPlus_ImageSaveToFile only writes about 30K bytes when it should write about 1MB, which it does when the code is

$tag = 'char val['&$iLength&']'
.
.
Static Local $tvalue = DllStructCreate($tag)

It should write about 1 MB.

I suggest caution in running the code below. On my PC, it caused a second instance of SciTE to appear at the top left of the Desktop, showing only the title bar, with a width of only approximately 200 pixels! Then rebooting the PC showed this at login. Further, double-clicking on the SciTE shortcut on the Desktop showed SciTE in the same way! (After running Regedit, and searching for SciTE, the shortcut behaves normally.)

I would appreciate help in determining whether or not there is a bug in DLLStructCreate, preferably a way which does not clobber Windows. Of course, It is possible that there is a bug in my code.

I have made $tvalue Static in the hope that this might make the code run properly. Doing this did not help.

My code is based on code written by Authenticity and ChrisL.

#include <GDIPlus.au3>
#include <Array.au3>
Opt('MustDeclareVars',1)

; Property Item structure
Global Const $tagGDIPPROPERTYITEM = _
    "uint id;" & _          ; ID of this property
    "ulong length;" & _     ; Length of the property value, in bytes
    "word type;" & _        ; Type of the value, as one of TAG_TYPE_XXX constants
    "ptr pvalue;"           ; pointer to property value

; Image property types constants
; Ref: https://www.media.mit.edu/pia/Research/deepview/exif.html
Global Const $GDIP_PROPERTYTAGTYPEUBYTE = 1
Global Const $GDIP_PROPERTYTAGTYPEASCII = 2
Global Const $GDIP_PROPERTYTAGTYPEUSHORT = 3
Global Const $GDIP_PROPERTYTAGTYPEULONG = 4
Global Const $GDIP_PROPERTYTAGTYPEURATIONAL = 5
Global Const $GDIP_PROPERTYTAGTYPESBYTE = 6
Global Const $GDIP_PROPERTYTAGTYPEUNDEFINED = 7
Global Const $GDIP_PROPERTYTAGTYPESSHORT = 8
Global Const $GDIP_PROPERTYTAGTYPESLONG = 9
Global Const $GDIP_PROPERTYTAGTYPESRATIONAL = 10
Global Const $GDIP_PROPERTYTAGTYPESFLOAT = 11
Global Const $GDIP_PROPERTYTAGTYPEDFLOAT = 12
main()

Func main()
    _GDIPlus_Startup()

    Local $hImage = _GDIPlus_ImageLoadFromFile('H:\temp\AP test data\DSC00824 - Copy.jpg')

    Local $ar = _GDIPlus_ImageGetAllPropertyItemsEx($hImage)
    Local $propsAr[UBound($ar,1)-1][5],$vec,$j=-1
    For $i = 1 To $ar[0][0]
        If $ar[$i][3]<>0 Then   ; pValue -- for Sony!
            $j += 1
            $propsAr[$j][0] = $ar[$i][0]    ; id
            $propsAr[$j][1] = $ar[$i][1]    ; length
            $propsAr[$j][2] =$ar[$i][2]; type
            $vec = _GDIPlus_ImageGetPropertyItemValue($ar[$i][1],$ar[$i][2],$ar[$i][3])
            $propsAr[$j][3] = $vec[0]   ; val1
            Switch $ar[$i][2]
                Case 5,10   ; $GDIP_PROPERTYTAGTYPEURATIONAL,$GDIP_PROPERTYTAGTYPESRATIONAL
                    $propsAr[$j][4] = $vec[1]
                Case Else
                    $propsAr[$j][4] = ''
            EndSwitch
        EndIf
    Next
    ReDim $propsAr[$j+1][5]

    For $i = 0 To UBound($propsAr,1)-1
        Switch $propsAr[$i][2]  ; type
            Case 5,10   ; $GDIP_PROPERTYTAGTYPEURATIONAL,$GDIP_PROPERTYTAGTYPESRATIONAL
                _GDIPlus_ImageSetPropertyItemEx($hImage,$propsAr[$i][0],$propsAr[$i][1], _
                    $propsAr[$i][2],$propsAr[$i][3],$propsAr[$i][4])
            Case Else
                _GDIPlus_ImageSetPropertyItemEx($hImage,$propsAr[$i][0],$propsAr[$i][1], _
                    $propsAr[$i][2],$propsAr[$i][3])
        EndSwitch
    Next
    _GDIPlus_ImageSaveToFile($hImage,'H:\b\1.jpg')
    _GDIPlus_ImageDispose($hImage)
    _GDIPlus_Shutdown()
EndFunc

Func _GDIPlus_ImageGetAllPropertyItemsEx($hImage)
    Local $iI, $iCount, $tBuffer, $pBuffer, $iBuffer, $tPropertyItem, $aSize, $aPropertyItems[1][1], $aResult

    $aSize = _GDIPlus_ImageGetPropertySize($hImage)
    If @error Then Return SetError(@error, @extended, -1)

    $iBuffer = $aSize[0]
    $tBuffer = DllStructCreate("byte[" & $iBuffer & "]")
    $pBuffer = DllStructGetPtr($tBuffer)
    $iCount = $aSize[1]

    $aResult = DllCall($__g_hGDIPDll, "uint", "GdipGetAllPropertyItems", "hwnd", $hImage, "uint", $iBuffer, "uint", $iCount, "ptr", $pBuffer)
    If @error Then Return SetError(@error, @extended, -1)
    If $aResult[0] Then Return SetError(10, $aResult[0], False)

    ReDim $aPropertyItems[$iCount + 1][4]
    $aPropertyItems[0][0] = $iCount

    For $iI = 1 To $iCount
        $tPropertyItem = DllStructCreate($tagGDIPPROPERTYITEM, $pBuffer)
        $aPropertyItems[$iI][0] = DllStructGetData($tPropertyItem, "id")
        $aPropertyItems[$iI][1] = DllStructGetData($tPropertyItem, "length")
        $aPropertyItems[$iI][2] = DllStructGetData($tPropertyItem, "type")
        $aPropertyItems[$iI][3] = DllStructGetData($tPropertyItem, "pvalue")
        $pBuffer += DllStructGetSize($tPropertyItem)
    Next

    Return $aPropertyItems
EndFunc

Func _GDIPlus_ImageGetPropertyItemValue($iLength, $iType, $pValue)
    Static Local $tvalue
    Switch $iType
        Case 1,6    ; $GDIP_PROPERTYTAGTYPEUBYTE,$GDIP_PROPERTYTAGTYPESBYTE
            $tvalue = DllStructCreate('byte val',$pValue)
        Case 2      ; $GDIP_PROPERTYTAGTYPEASCII
            $tvalue = DllStructCreate('char val['&$iLength&']',$pValue)
        Case 3      ; $GDIP_PROPERTYTAGTYPEUSHORT
            $tvalue = DllStructCreate('ushort val',$pValue)
        Case 4      ; $GDIP_PROPERTYTAGTYPEULONG
            $tvalue = DllStructCreate('ulong val',$pValue)
        Case 5      ; $GDIP_PROPERTYTAGTYPEURATIONAL
            $tvalue = DllStructCreate('ulong val1;ulong val2',$pValue)
        Case 7      ; $GDIP_PROPERTYTAGTYPEUNDEFINED
            ; undefined, per specification, but may be a long but is sometimes a string
            $tvalue = DllStructCreate('byte val['&$ilength&']',$pValue) ; see _GDIPlus_ImageSetPropertyItemEx
;~          $tvalue = DllStructCreate('char val['&$ilength&']',$pValue)
        Case 8      ; $GDIP_PROPERTYTAGTYPESSHORT
            $tvalue = DllStructCreate('short val',$pValue)
        Case 9      ; $GDIP_PROPERTYTAGTYPEULONG
            $tvalue = DllStructCreate('ulong val',$pValue)
        Case 10     ; $GDIP_PROPERTYTAGTYPESRATIONAL
            $tvalue = DllStructCreate('ulong val1;ulong val2',$pValue)
        Case 11     ; $GDIP_PROPERTYTAGTYPESFLOAT
            $tvalue = DllStructCreate('float val',$pValue)
        Case 12     ; $GDIP_PROPERTYTAGTYPEDFLOAT
            $tvalue = DllStructCreate('double val',$pValue)
    EndSwitch
    If @error Then Return SetError(@error,0,-1)
    Switch $iType
            Case 5,10   ; $GDIP_PROPERTYTAGTYPEURATIONAL,$GDIP_PROPERTYTAGTYPESRATIONAL
            Local $aRet[2]
            $aRet[0] = DllStructGetData($tvalue,'val1')
            $aRet[1] = DllStructGetData($tvalue,'val2')
        Case Else
            Local $aRet[1]
            $aRet[0] = DllStructGetData($tvalue,'val')
    EndSwitch
    Return $aRet
EndFunc

Func _GDIPlus_ImageGetPropertySize($hImage)
    Local $aSize[2], $aResult

    $aResult = DllCall($__g_hGDIPDll, "uint", "GdipGetPropertySize", "hwnd", $hImage, "uint*", 0, "uint*", 0)
    If @error Then Return SetError(@error, @extended, -1)

    $aSize[0] = $aResult[2]
    $aSize[1] = $aResult[3]
    Return $aSize
EndFunc   ;==>_GDIPlus_ImageGetPropertySize

Func _GDIPlus_ImageSetPropertyItemEx($hImage,$id,$iLength,$iType,$value1,$value2=-1)
    Local $tProp = DllStructCreate($tagGDIPPROPERTYITEM)
    DllStructSetData($tProp,'id',$id)
    DllStructSetData($tProp,'type',$itype)
    DllStructSetData($tProp,'length',$ilength)
    Local $tag
    Switch $iType
        Case $GDIP_PROPERTYTAGTYPEUBYTE,$GDIP_PROPERTYTAGTYPESBYTE
            $tag = 'byte val'
        Case $GDIP_PROPERTYTAGTYPEASCII
            $tag = 'char val['&$iLength&']'
        Case $GDIP_PROPERTYTAGTYPEUSHORT
            $tag = 'ushort val'
        Case $GDIP_PROPERTYTAGTYPEULONG
            $tag = 'ulong val'
        Case $GDIP_PROPERTYTAGTYPEURATIONAL
            $tag =  'ulong val1;ulong val2'
        Case $GDIP_PROPERTYTAGTYPEUNDEFINED
            ; undefined, per specification, but may be a long but is sometimes a string
            $tag = 'byte val['&$iLength&']' ; causes saving to jpeg to write junk
;~          $tag = 'char val['&$iLength&']'
        Case $GDIP_PROPERTYTAGTYPESSHORT
            $tag = 'short val'
        Case $GDIP_PROPERTYTAGTYPEULONG
            $tag = 'ulong val'
        Case $GDIP_PROPERTYTAGTYPESRATIONAL
            $tag =  'long val1;long val2'
        Case $GDIP_PROPERTYTAGTYPESFLOAT
            $tag = 'float val'
        Case $GDIP_PROPERTYTAGTYPEDFLOAT
            $tag = 'double val'
    EndSwitch
    Static Local $tvalue = DllStructCreate($tag)
    Switch $iType
        Case $GDIP_PROPERTYTAGTYPEURATIONAL,$GDIP_PROPERTYTAGTYPESRATIONAL
            DllStructSetData($tvalue,'val1',$value1)
            DllStructSetData($tvalue,'val2',$value2)
        Case Else
            DllStructSetData($tvalue,1,$value1)
    EndSwitch
    DllStructSetData($tProp,'pvalue',DllStructGetPtr($tvalue))

    Local $aResult = DllCall($__g_hGDIPDll, "int", "GdipSetPropertyItem", "hwnd", $hImage, "ptr", _
    DllStructGetPtr($tProp))
    If @error Then Return SetError(@error, @extended, -1)
    If $aResult[0] Then Return SetError(10, $aResult[0], -1)

    Return $aResult[0] = 0
EndFunc

I have seen $iLength be as much as 37 KB for $GDIP_PROPERTYTAGTYPEUNDEFINED.

Is there is a bug, how can this be demonstrated to the developers in a few lines of code (without clobbering Windows)?

 

Edited by c.haslam

Spoiler

CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard

 

Share this post


Link to post
Share on other sites

I have now found, with code similar to that in the first post, that a script can produce different results when run several times. My new testing shows that there are inconsistent results in handling property types other than $GDIP_PROPERTYTAGTYPEUNDEFINED.

A result consists of:

  • ArrayDisplay .png file, showing the id, length, type and value(s) of each of the properties
  • Output file size reported by the script
  • @extended (GDIPLUS Status value) from _GDIPlus_ImageSaveToFile()

I know what val1 and val2 should be from Irfanview. The output file size should be 916K, it being a copy of the input file. The Status value should be zero.

I ran the script 7 times:

  • 3 displayed the values of the first 27 properties OK in _ArrayDisplay() and most of properties 30 to 63 as zeroes when they should be non-zero, output file size as 36K and GDIP Status as 7 (Win32 error)
  • 3 displayed the values of all properties correctly in _ArrayDisplay(), file size as 916K and GDIP status as 0 (OK)
  • 1 the values of the first 27 properties as zeros (which is wrong), file size as 916K and GDIP status as 0 (OK)

The PC is running AOK (except as noted in Post1, which happened once). I have an AutoIt script which runs automatically daily with no problems. So the cause of this odd behavior is either a subtle error in my code or a bug in AutoIt.

My thoughts turn to the idea that there is a memory leak somewhere, possibly caused by my code. The input file has not changed.

I am wondering how I can allocate memory to structs independent of DllStructCreate(). Doing so might identify the problem. Do I use _MemGlobalAlloc() to allocate memory and _MemGlobalFree() to release it in _GDIPlus_ImageGetPropertyItemValue()? If so, with what parameters?

The code follows, and the attached .png's show _ArrayDisplay() results.

 

#include <GDIPlus.au3>
#include <Array.au3>
Opt('MustDeclareVars',1)
;~ #include "..\cDebug.au3"

; Property Item structure
Global Const $tagGDIPPROPERTYITEM = _
    "uint id;" & _          ; ID of this property
    "ulong length;" & _     ; Length of the property value, in bytes
    "word type;" & _        ; Type of the value, as one of TAG_TYPE_XXX constants
    "ptr pvalue;"           ; pointer to property value

; Image property types constants
; Ref: https://www.media.mit.edu/pia/Research/deepview/exif.html
Global Const $GDIP_PROPERTYTAGTYPEUBYTE = 1
Global Const $GDIP_PROPERTYTAGTYPEASCII = 2
Global Const $GDIP_PROPERTYTAGTYPEUSHORT = 3
Global Const $GDIP_PROPERTYTAGTYPEULONG = 4
Global Const $GDIP_PROPERTYTAGTYPEURATIONAL = 5
Global Const $GDIP_PROPERTYTAGTYPESBYTE = 6
Global Const $GDIP_PROPERTYTAGTYPEUNDEFINED = 7
Global Const $GDIP_PROPERTYTAGTYPESSHORT = 8
Global Const $GDIP_PROPERTYTAGTYPESLONG = 9
Global Const $GDIP_PROPERTYTAGTYPESRATIONAL = 10
Global Const $GDIP_PROPERTYTAGTYPESFLOAT = 11
Global Const $GDIP_PROPERTYTAGTYPEDFLOAT = 12

OnAutoItExitRegister(FinishUp)

main()

Func main()
    _GDIPlus_Startup()

    Local $hImage = _GDIPlus_ImageLoadFromFile('H:\temp\AP test data\DSC00824 - Copy.jpg')
    Local $propsAr = GetProperties($hImage)

Local $dAr = $propsAr
For $i = 0 To UBound($propsAr,1)-1
    $dAr[$i][0] = Hex($propsAr[$i][0],4)
Next
_ArrayDisplay($dAr,'At line '&@ScriptLineNumber,'',0,Default,'id|length|type|val1|val2')

    For $i = 0 To UBound($propsAr,1)-1
        Switch $propsAr[$i][2]  ; type
            Case 5,10   ; $GDIP_PROPERTYTAGTYPEURATIONAL,$GDIP_PROPERTYTAGTYPESRATIONAL
                _GDIPlus_ImageSetPropertyItemEx($hImage,$propsAr[$i][0],$propsAr[$i][1], _
                    $propsAr[$i][2],$propsAr[$i][3],$propsAr[$i][4])
            Case Else
                _GDIPlus_ImageSetPropertyItemEx($hImage,$propsAr[$i][0],$propsAr[$i][1], _
                    $propsAr[$i][2],$propsAr[$i][3])
        EndSwitch
    Next
    $propsAr = GetProperties($hImage)   ; causes save file to fail
;~ _ArrayDisplay($propsAr,@ScriptLineNumber)
    Local $ouFilspc = 'H:\b\1.jpg'
    _GDIPlus_ImageSaveToFile($hImage,$ouFilspc)
    If @error Then MsgBox(0,'_GDIPlus_ImageSaveToFile','@error '&@error&' @extended '&@extended)
    _GDIPlus_ImageDispose($hImage)
    Local $vec = FileGetTime($ouFilspc)
    MsgBox(0,@ScriptLineNumber,'Output: file size '&FileGetSize($ouFilspc)& _
        ' bytes at '&StringFormat('%s-%02s-%02s %02s:%02s',$vec[0],$vec[1],$vec[2],$vec[3],$vec[4]))
EndFunc

Func GetProperties($hImage)
    Local $ar = _GDIPlus_ImageGetAllPropertyItemsEx($hImage)
    Local $propsAr[UBound($ar,1)-1][5],$vec,$j=-1
    For $i = 1 To $ar[0][0]
        If Not ($ar[$i][3]=0 Or ($ar[$i][2]=2 And $ar[$i][1]=0)) Then   ; pValue, type, length -- for Sony!
            $j += 1
            $propsAr[$j][0] = $ar[$i][0]    ; id
            $propsAr[$j][1] = $ar[$i][1]    ; length
            $propsAr[$j][2] =$ar[$i][2]; type
            $vec = _GDIPlus_ImageGetPropertyItemValue($ar[$i][1],$ar[$i][2],$ar[$i][3])
            $propsAr[$j][3] = $vec[0]   ; val1
            Switch $ar[$i][2]
                Case 5,10   ; $GDIP_PROPERTYTAGTYPEURATIONAL,$GDIP_PROPERTYTAGTYPESRATIONAL
                    $propsAr[$j][4] = $vec[1]
                Case Else
                    $propsAr[$j][4] = ''
            EndSwitch
        EndIf
    Next
    ReDim $propsAr[$j+1][5]
    Return $propsAr
EndFunc

Func _GDIPlus_ImageGetAllPropertyItemsEx($hImage)
    Local $iI, $iCount, $tBuffer, $pBuffer, $iBuffer, $tPropertyItem, $aSize, $aPropertyItems[1][1], $aResult

    $aSize = _GDIPlus_ImageGetPropertySize($hImage)
    If @error Then Return SetError(@error, @extended, -1)

    $iBuffer = $aSize[0]
    $tBuffer = DllStructCreate("byte[" & $iBuffer & "]")
    $pBuffer = DllStructGetPtr($tBuffer)
    $iCount = $aSize[1]

    $aResult = DllCall($__g_hGDIPDll, "uint", "GdipGetAllPropertyItems", "hwnd", $hImage, "uint", $iBuffer, "uint", $iCount, "ptr", $pBuffer)
    If @error Then Return SetError(@error, @extended, -1)
    If $aResult[0] Then Return SetError(10, $aResult[0], False)

    ReDim $aPropertyItems[$iCount + 1][4]
    $aPropertyItems[0][0] = $iCount

    For $iI = 1 To $iCount
        $tPropertyItem = DllStructCreate($tagGDIPPROPERTYITEM, $pBuffer)
        $aPropertyItems[$iI][0] = DllStructGetData($tPropertyItem, "id")
        $aPropertyItems[$iI][1] = DllStructGetData($tPropertyItem, "length")
        $aPropertyItems[$iI][2] = DllStructGetData($tPropertyItem, "type")
        $aPropertyItems[$iI][3] = DllStructGetData($tPropertyItem, "pvalue")
        $pBuffer += DllStructGetSize($tPropertyItem)
    Next

    Return $aPropertyItems
EndFunc

Func _GDIPlus_ImageGetPropertyItemValue($iLength, $iType, $pValue)
    Static Local $tvalue
    Switch $iType
        Case 1,6    ; $GDIP_PROPERTYTAGTYPEUBYTE,$GDIP_PROPERTYTAGTYPESBYTE
            $tvalue = DllStructCreate('byte val',$pValue)
        Case 2      ; $GDIP_PROPERTYTAGTYPEASCII
            $tvalue = DllStructCreate('char val['&$iLength&']',$pValue)
        Case 3      ; $GDIP_PROPERTYTAGTYPEUSHORT
            $tvalue = DllStructCreate('ushort val',$pValue)
        Case 4      ; $GDIP_PROPERTYTAGTYPEULONG
            $tvalue = DllStructCreate('ulong val',$pValue)
        Case 5      ; $GDIP_PROPERTYTAGTYPEURATIONAL
            $tvalue = DllStructCreate('ulong val1;ulong val2',$pValue)
        Case 7      ; $GDIP_PROPERTYTAGTYPEUNDEFINED
            ; undefined, per specification, but may be a long but is sometimes a string
            $tvalue = DllStructCreate('byte val['&$ilength&']',$pValue) ; see _GDIPlus_ImageSetPropertyItemEx
;~          $tvalue = DllStructCreate('char val['&$ilength&']',$pValue)
        Case 8      ; $GDIP_PROPERTYTAGTYPESSHORT
            $tvalue = DllStructCreate('short val',$pValue)
        Case 9      ; $GDIP_PROPERTYTAGTYPEULONG
            $tvalue = DllStructCreate('ulong val',$pValue)
        Case 10     ; $GDIP_PROPERTYTAGTYPESRATIONAL
            $tvalue = DllStructCreate('ulong val1;ulong val2',$pValue)
        Case 11     ; $GDIP_PROPERTYTAGTYPESFLOAT
            $tvalue = DllStructCreate('float val',$pValue)
        Case 12     ; $GDIP_PROPERTYTAGTYPEDFLOAT
            $tvalue = DllStructCreate('double val',$pValue)
    EndSwitch
    If @error Then Return SetError(@error,0,-1)
    Switch $iType
            Case 5,10   ; $GDIP_PROPERTYTAGTYPEURATIONAL,$GDIP_PROPERTYTAGTYPESRATIONAL
            Local $aRet[2]
            $aRet[0] = DllStructGetData($tvalue,'val1')
            $aRet[1] = DllStructGetData($tvalue,'val2')
        Case Else
            Local $aRet[1]
            $aRet[0] = DllStructGetData($tvalue,'val')
    EndSwitch
    Return $aRet
EndFunc

Func _GDIPlus_ImageGetPropertySize($hImage)
    Local $aSize[2], $aResult

    $aResult = DllCall($__g_hGDIPDll, "uint", "GdipGetPropertySize", "hwnd", $hImage, "uint*", 0, "uint*", 0)
    If @error Then Return SetError(@error, @extended, -1)

    $aSize[0] = $aResult[2]
    $aSize[1] = $aResult[3]
    Return $aSize
EndFunc   ;==>_GDIPlus_ImageGetPropertySize

Func _GDIPlus_ImageSetPropertyItemEx($hImage,$id,$iLength,$iType,$value1,$value2=-1)
    Local $tProp = DllStructCreate($tagGDIPPROPERTYITEM)
    DllStructSetData($tProp,'id',$id)
    DllStructSetData($tProp,'type',$itype)
    DllStructSetData($tProp,'length',$ilength)
    Local $tag,$tvalue
    Switch $iType
        Case $GDIP_PROPERTYTAGTYPEUBYTE,$GDIP_PROPERTYTAGTYPESBYTE
            $tvalue = DllStructCreate('byte val;')
        Case $GDIP_PROPERTYTAGTYPEASCII
            $tvalue = DllStructCreate('char val['&$iLength&'];')
        Case $GDIP_PROPERTYTAGTYPEUSHORT
            $tvalue = DllStructCreate('ushort val;')
        Case $GDIP_PROPERTYTAGTYPEULONG
            $tvalue = DllStructCreate('ulong val;')
        Case $GDIP_PROPERTYTAGTYPEURATIONAL
            $tvalue = DllStructCreate('ulong val1;ulong val2;')
        Case $GDIP_PROPERTYTAGTYPEUNDEFINED
            ; undefined, per specification, but may be a long but is sometimes a string
;~          $tag = 'byte val['&$iLength&']' ; causes saving to jpeg to write junk
            $tvalue = DllStructCreate('char val['&$iLength&'];')
        Case $GDIP_PROPERTYTAGTYPESSHORT
            $tvalue = DllStructCreate('short val;')
        Case $GDIP_PROPERTYTAGTYPEULONG
            $tvalue = DllStructCreate('ulong val;')
        Case $GDIP_PROPERTYTAGTYPESRATIONAL
            $tvalue = DllStructCreate('long val1;long val2;')
        Case $GDIP_PROPERTYTAGTYPESFLOAT
            $tvalue = DllStructCreate('float val;')
        Case $GDIP_PROPERTYTAGTYPEDFLOAT
            $tvalue = DllStructCreate('double val;')
    EndSwitch
;~ If @error Then _Msgdebug(@ScriptLineNumber&' create','@error,$id,$ilength,$iType,$value1,$value2',@error,Hex($id,4),$ilength,$iType,$value1,$value2)
    Switch $iType
        Case $GDIP_PROPERTYTAGTYPEURATIONAL,$GDIP_PROPERTYTAGTYPESRATIONAL
            DllStructSetData($tvalue,1,$value1)
;~ If @error Then _Msgdebug(@ScriptLineNumber&' val1','@error,$id,$ilength,$iType,$value1,$value2',@error,Hex($id,4),$ilength,$iType,$value1,$value2)
            DllStructSetData($tvalue,2,$value2)
;~ If @error Then _Msgdebug(@ScriptLineNumber&' val2','@error,$id,$ilength,$iType,$value1,$value2',@error,Hex($id,4),$ilength,$iType,$value1,$value2)
        Case Else
            DllStructSetData($tvalue,1,$value1)
;~ If @error Then _Msgdebug(@ScriptLineNumber&' val','@error,$id,$ilength,$iType,$value1,$value2',@error,Hex($id,4),$ilength,$iType,$value1,$value2)
    EndSwitch
    DllStructSetData($tProp,'pvalue',DllStructGetPtr($tvalue))
;~ If @error Then _Msgdebug(@ScriptLineNumber&' pvalue','@error,$id,$ilength,$iType,$value1,$value2',@error,Hex($id,4),$ilength,$iType,$value1,$value2)

    Local $aResult = DllCall($__g_hGDIPDll, "int", "GdipSetPropertyItem", "hwnd", $hImage, "ptr", _
    DllStructGetPtr($tProp))
    If @error Then Return SetError(@error, @extended, -1)
    If $aResult[0] Then Return SetError(10, $aResult[0], -1)

    Return $aResult[0] = 0
EndFunc

Func FinishUp()
    _GDIPlus_Shutdown()
EndFunc

cDebug.au3 (which is commented out) is my variable-dump library, which can be found here .

The screenshot below shows the values of the first 27 properties as zeros (which is wrong). _GDIPlus_ImageSaveToFile() worked as expected.

Display 1st 27 0, 30 up OK File save 916K, GDIP status 0.png

The screenshot below shows the values of all properties correctly in _ArrayDisplay(). _GDIPlus_ImageSaveToFile() worked as expected.

Display OK File size 916K GDIP status 0.png

The screenshot below shows the values of the first 27 properties OK in _ArrayDisplay() and most of properties 30 to 63 as zeroes when they should be non-zero. The output file size as 36K (which is wrong) and GDIP Status as 7 (Win32 error).

Display first 27 OK 30 up 0 file save 36K GDIP status Win32 error.png

Edited by c.haslam

Spoiler

CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard

 

Share this post


Link to post
Share on other sites

I have found an error in my understanding of how EXIF data is stored: for example, type $GDIP_PROPERTYTAGTYPEUSHORT (3) indicates that pValue points to an array of unsigned shorts. So there may not be an error in memory allocation by DllStructCreate().


Spoiler

CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard

 

Share this post


Link to post
Share on other sites

I have modified the script, recognizing that most of the metadata is stored in a jpeg as arrays. This version abends at run-time with Variable used without being declared on $ouFilspc despite Au3Check not finding any errors, and $oufilspc being declared as Local a few lines before.

Suggestions are most welcome.

#include <GDIPlus.au3>
#include <Array.au3>
Opt('MustDeclareVars',1)
;~ #include "..\cDebug.au3"

; Property Item structure
Global Const $tagGDIPPROPERTYITEM = _
    "uint id;" & _          ; ID of this property
    "ulong length;" & _     ; Length of the property value, in bytes
    "word type;" & _        ; Type of the value, as one of TAG_TYPE_XXX constants
    "ptr pvalue;"           ; pointer to property value

; Image property types constants
; Ref: https://www.media.mit.edu/pia/Research/deepview/exif.html
Global Const $GDIP_PROPERTYTAGTYPEUBYTE = 1
Global Const $GDIP_PROPERTYTAGTYPEASCII = 2
Global Const $GDIP_PROPERTYTAGTYPEUSHORT = 3
Global Const $GDIP_PROPERTYTAGTYPEULONG = 4
Global Const $GDIP_PROPERTYTAGTYPEURATIONAL = 5
Global Const $GDIP_PROPERTYTAGTYPESBYTE = 6
Global Const $GDIP_PROPERTYTAGTYPEUNDEFINED = 7
Global Const $GDIP_PROPERTYTAGTYPESSHORT = 8
Global Const $GDIP_PROPERTYTAGTYPESLONG = 9
Global Const $GDIP_PROPERTYTAGTYPESRATIONAL = 10
Global Const $GDIP_PROPERTYTAGTYPESFLOAT = 11
Global Const $GDIP_PROPERTYTAGTYPEDFLOAT = 12

Global $gId

OnAutoItExitRegister(FinishUp)

main()

Func main()
    _GDIPlus_Startup()

;~  Local $hImage = _GDIPlus_ImageLoadFromFile('H:\b\1.jpg')
    Local $hImage = _GDIPlus_ImageLoadFromFile('H:\temp\AP test data\DSC00824 - Copy.jpg')
;~  Local $hImage = _GDIPlus_ImageLoadFromFile('H:\temp\AP test data\pergola photo - Copy.JPG')
    Local $propsAr = GetProperties($hImage)

Local $dAr = $propsAr
For $i = 0 To UBound($propsAr,1)-1
    $dAr[$i][0] = Hex($propsAr[$i][0],4)
    Switch True
        Case IsArray($propsAr[$i][3])
            Local $t='',$vec = $propsAr[$i][3]
            For $j = 0 To UBound($vec)-1
                $t &= '|'&$vec[$j]
            Next
            $t = StringMid($t,2)
            $dAr[$i][3] = $t
    EndSwitch
Next
_ArrayDisplay($dAr,'At line '&@ScriptLineNumber,'',0,Default,'id|length|type|value')

    For $i = 0 To UBound($propsAr,1)-1
        If Not _GDIPlus_ImageSetPropertyItemEx($hImage,$propsAr[$i][0],$propsAr[$i][1], _
            $propsAr[$i][2],$propsAr[$i][3]) Then
            ConsoleWrite('_GDIPlus_ImageSetPropertyItemEx failed'&@CRLF)
        EndIf
    Next
    Local $date = '2017:12:09 14:01:23'
    If Not _GDIPlus_ImageSetPropertyItemEx($hImage,0x9003,20,2,$date) Then

    Local $ouFilspc = 'H:\b\2.jpg'
    _GDIPlus_ImageSaveToFile($hImage,$ouFilspc)
    If @error Then MsgBox(0,'_GDIPlus_ImageSaveToFile','@error '&@error&' @extended '&@extended)
        ConsoleWrite('_GDIPlus_ImageSetPropertyItemEx failed'&@CRLF)
    EndIf

    _GDIPlus_ImageDispose($hImage)
    Local $vec = FileGetTime($ouFilspc) ; at run time:  $ouFilspc "Variable used without being declared"
    MsgBox(0,@ScriptLineNumber,'Output: file size '&FileGetSize($ouFilspc)& _
        ' bytes at '&StringFormat('%s-%02s-%02s %02s:%02s',$vec[0],$vec[1],$vec[2],$vec[3],$vec[4]))
EndFunc

Func GetProperties($hImage)
    Local $ar = _GDIPlus_ImageGetAllPropertyItemsEx($hImage)
    Local $j=-1,$id,$length,$type,$value
    For $i = 1 To $ar[0][0]
        $length = $ar[$i][1]
        $type = $ar[$i][2]
        $value = $ar[$i][3]
        If Not ($value=0 Or ($type=2 And $length=0)) Then
            $j += 1
            $ar[$j][0] = $ar[$i][0]
            $ar[$j][1] = $length
            $ar[$j][2] = $type
            $ar[$j][3] = $value
        EndIf
    Next
    ReDim $ar[$j+1][4]

    Local $propsAr[$j+1][4]
    For $i = 0 To UBound($ar,1)-1
        $propsAr[$i][0] = $ar[$i][0]    ; id
        $propsAr[$i][1] = $ar[$i][1]    ; length
        $propsAr[$i][2] = $ar[$i][2]    ; type
$gId = $propsAr[$i][0]
        $propsAr[$i][3] = _GDIPlus_ImageGetPropertyItemValue($ar[$i][1],$ar[$i][2],$ar[$i][3])
    Next
    Return $propsAr
EndFunc

Func _GDIPlus_ImageGetAllPropertyItemsEx($hImage)
    Local $iI, $iCount, $tBuffer, $pBuffer, $iBuffer, $tPropertyItem, $aSize, $aPropertyItems[1][1], $aResult

    $aSize = _GDIPlus_ImageGetPropertySize($hImage)
    If @error Then Return SetError(@error, @extended, -1)

    $iBuffer = $aSize[0]
    $tBuffer = DllStructCreate("byte[" & $iBuffer & "]")
    $pBuffer = DllStructGetPtr($tBuffer)
    $iCount = $aSize[1]

    $aResult = DllCall($__g_hGDIPDll, "uint", "GdipGetAllPropertyItems", "hwnd", $hImage, "uint", $iBuffer, "uint", $iCount, "ptr", $pBuffer)
    If @error Then Return SetError(@error, @extended, -1)
    If $aResult[0] Then Return SetError(10, $aResult[0], False)

    ReDim $aPropertyItems[$iCount + 1][4]
    $aPropertyItems[0][0] = $iCount

    For $iI = 1 To $iCount
        $tPropertyItem = DllStructCreate($tagGDIPPROPERTYITEM, $pBuffer)
        $aPropertyItems[$iI][0] = DllStructGetData($tPropertyItem, "id")
        $aPropertyItems[$iI][1] = DllStructGetData($tPropertyItem, "length")
        $aPropertyItems[$iI][2] = DllStructGetData($tPropertyItem, "type")
        $aPropertyItems[$iI][3] = DllStructGetData($tPropertyItem, "pvalue")
        $pBuffer += DllStructGetSize($tPropertyItem)
    Next

    Return $aPropertyItems
EndFunc

; Returns:
;   byte and undefined: binary
;   string              string
;   rational            vector: [n] numerator, [n=1] denominator
;   else                vector
; Vectors are ref 0
Func _GDIPlus_ImageGetPropertyItemValue($iLength, $iType, $pValue)
    Static Local $tvalue
    Local $qels

    Switch $iType
        Case 1,6,7  ; UBYTE,SBYTE,UNDEFINED
            $tvalue = DllStructCreate('byte binary['&$ilength&']',$pValue)
        Case 2      ; ASCII
            $tvalue = DllStructCreate('char str['&$iLength&']',$pValue)
        Case 3      ; USHORT
            $qels = $iLength/2
            $tvalue = DllStructCreate('ushort valVec['&$qels&']',$pValue)
        Case 4,5    ; ULONG,URATIONAL
            $qels = $iLength/4
            $tvalue = DllStructCreate('ulong valVec['&$qels&']',$pValue)
        Case 8      ; SSHORT
            $qels = $iLength/4
            $tvalue = DllStructCreate('short valVec['&$qels&']',$pValue)
        Case 9,10   ; SLONG,SRATIONAL
            $qels = $iLength/4
            $tvalue = DllStructCreate('long valVec['&$qels&']',$pValue)
        $tvalue = DllStructCreate('double val',$pValue)
    EndSwitch
Local $err = @error
If $err Then
    ConsoleWrite('@error '&$err&@CRLF)
    ConsoleWrite('id '&Hex($gId,4)&' ilength ' &$ilength&' type '&$itype&@CRLF)
    MsgBox(0,@ScriptLineNumber,'id '&Hex($gId,4)&' ilength ' &$ilength&' type '&$itype)
EndIf
    If $err Then Return SetError($err,0,-1)
    Local $ret
    Switch $itype
        Case 1,6,7  ; UBYTE,SBYTE,UNDEFINED
            Local $ret =  DllStructGetData($tvalue,'binary')
        Case 2 ; ASCII
            Local $ret = DllStructGetData($tvalue,'str')
        Case Else
            Local $ret[$qels]
            For $i = 0 To $qels-1
                $ret[$i] = DllStructGetData($tvalue,'valVec',$i+1)
            Next
    EndSwitch
If $err Then
    ConsoleWrite('@error '&$err&@CRLF)
    ConsoleWrite('GetData: id '&Hex($gId,4)&' ilength ' &$ilength&' type '&$itype&@CRLF)
    MsgBox(0,@ScriptLineNumber,'id '&Hex($gId,4)&' ilength ' &$ilength&' type '&$itype)
EndIf
    Return $ret
EndFunc

Func _GDIPlus_ImageGetPropertySize($hImage)
    Local $aSize[2], $aResult

    $aResult = DllCall($__g_hGDIPDll, "uint", "GdipGetPropertySize", "hwnd", $hImage, "uint*", 0, "uint*", 0)
    If @error Then Return SetError(@error, @extended, -1)

    $aSize[0] = $aResult[2]
    $aSize[1] = $aResult[3]
    Return $aSize
EndFunc   ;==>_GDIPlus_ImageGetPropertySize

Func _GDIPlus_ImageSetPropertyItemEx($hImage,$id,$iLength,$iType,$value)
    Local $tProp = DllStructCreate($tagGDIPPROPERTYITEM)
    DllStructSetData($tProp,'id',$id)
    DllStructSetData($tProp,'type',$itype)
    DllStructSetData($tProp,'length',$ilength)
    Local $tag,$tvalue,$qels
    Switch $iType
        Case 1,6,7  ; UBYTE,SBYTE,UNDEFINED
            $tvalue = DllStructCreate('byte binary['&$ilength&']')
        Case 2      ; ASCII
            $tvalue = DllStructCreate('char str['&$iLength&']')
        Case 3      ; USHORT
            $qels = $iLength/2
            $tvalue = DllStructCreate('ushort valVec['&$qels&']')
        Case 4,5    ; ULONG,URATIONAL
            $qels = $iLength/4
            $tvalue = DllStructCreate('ulong valVec['&$qels&']')
        Case 8      ; SSHORT
            $qels = $iLength/2
            $tvalue = DllStructCreate('short valVec['&$qels&']')
        Case 9,10   ; SLONG,SRATIONAL
            $qels = $iLength/4
            $tvalue = DllStructCreate('long valVec['&($iLength/4)&']')
    EndSwitch
Local $err = @error
If $err Then
    ConsoleWrite('@error '&$err&@CRLF)
    ConsoleWrite('SetData: id '&Hex($gId,4)&' ilength ' &$ilength&' type '&$itype&@CRLF)
    MsgBox(0,@ScriptLineNumber,'id '&Hex($gId,4)&' ilength ' &$ilength&' type '&$itype)
EndIf
    If $err Then Return SetError($err,0,-1)
    Switch $itype
        Case 1,6,7  ; UBYTE,SBYTE,UNDEFINED
            DllStructSetData($tvalue,'binary',$value)
        Case 2  ; ASCII
            DllStructSetData($tvalue,'str',$value)
        Case Else
            For $i = 0 To $qels-1
                DllStructSetData($tvalue,'valVec',$value[$i],$i+1)
            Next
    EndSwitch
    DllStructSetData($tProp,'pvalue',DllStructGetPtr($tvalue))
Local $err = @error
If $err Then
    ConsoleWrite('@error '&$err&@CRLF)
    ConsoleWrite('SetData: id '&Hex($gId,4)&' ilength ' &$ilength&' type '&$itype&@CRLF)
    MsgBox(0,@ScriptLineNumber,'id '&Hex($gId,4)&' ilength ' &$ilength&' type '&$itype)
EndIf

Local $ptr = DllStructGetPtr($tProp)
Local $err = @error
If $err Then
    ConsoleWrite('@error '&$err&@CRLF)
    ConsoleWrite('GetPtr: id '&Hex($gId,4)&' ilength ' &$ilength&' type '&$itype&@CRLF)
    MsgBox(0,@ScriptLineNumber,'id '&Hex($gId,4)&' ilength ' &$ilength&' type '&$itype)
EndIf
    Local $aResult = DllCall($__g_hGDIPDll, "int", "GdipSetPropertyItem", "hwnd", $hImage, "ptr", _
    $ptr)
    If @error Then Return SetError(@error, @extended, -1)
    If $aResult[0] Then Return SetError(10, $aResult[0], -1)
    Return $aResult[0] = 0
EndFunc
Func FinishUp()
    _GDIPlus_Shutdown()
EndFunc

 


Spoiler

CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard

 

Share this post


Link to post
Share on other sites

The problem is that $outFilSpc is only declared if this If statement evaluates to true. If it's undeclared, then the If statement failed.

If Not _GDIPlus_ImageSetPropertyItemEx($hImage, 0x9003, 20, 2, $date) Then

        Local $ouFilspc = 'H:\b\2.jpg'
        _GDIPlus_ImageSaveToFile($hImage, $ouFilspc)
        If @error Then MsgBox(0, '_GDIPlus_ImageSaveToFile', '@error ' & @error & ' @extended ' & @extended)
        ConsoleWrite('_GDIPlus_ImageSetPropertyItemEx failed' & @CRLF)
    EndIf

 


If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites

I use single-line Ifs very seldom, because I often get them wrong, as I did above!

There are many alligators in my coding swamp right now, so it is not too surprising that I didn't seem that baby one!


Spoiler

CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard

 

Share this post


Link to post
Share on other sites

I have found a curious situation. Snippet:

Func _GDIPlus_ImageGetAllPropertyItemsEx($hImage)
    Local $iI, $iCount, $tBuffer, $pBuffer, $iBuffer, $tPropertyItem, $aPropertyItems[1][1], $aResult
;~  Local $iI, $iCount, $tBuffer, $pBuffer, $iBuffer, $tPropertyItem, $aSize, $aPropertyItems[1][1], $aResult

    Local $ar = _GDIPlus_ImageGetPropertySize($hImage)
    If @error Then Return SetError(@error, @extended, -1)

    $iBuffer = $ar[0]
    $tBuffer = DllStructCreate("byte[" & $iBuffer & "]")
    $pBuffer = DllStructGetPtr($tBuffer)
    $iCount = $ar[1]
    $aResult = DllCall($__g_hGDIPDll, "uint", "GdipGetAllPropertyItems", "hwnd", $hImage, _
        "uint", $iBuffer, "uint", $iCount, "ptr", $pBuffer)
    If @error Then Return SetError(@error, @extended, -1)
    If $aResult[0] Then Return SetError(10, $aResult[0], False)
    ReDim $aPropertyItems[$iCount + 1][4]
    $aPropertyItems[0][0] = $iCount

    For $iI = 1 To $iCount
        $tPropertyItem = DllStructCreate($tagGDIPPROPERTYITEM, $pBuffer)
        $aPropertyItems[$iI][0] = DllStructGetData($tPropertyItem, "id")
        $aPropertyItems[$iI][1] = DllStructGetData($tPropertyItem, "length")
        $aPropertyItems[$iI][2] = DllStructGetData($tPropertyItem, "type")
        $aPropertyItems[$iI][3] = DllStructGetData($tPropertyItem, "pvalue")
        $pBuffer += DllStructGetSize($tPropertyItem)
    Next

    Return $aPropertyItems
EndFunc

Func _GDIPlus_ImageGetPropertySize($hImage)
    Local $aRet[2], $aResult

    $aResult = DllCall($__g_hGDIPDll, "uint", "GdipGetPropertySize", "hwnd", $hImage, "uint*", 0, "uint*", 0)
    If @error Then Return SetError(@error, @extended, -1)

    $aRet[0] = $aResult[2]  ; size in bytes
    $aRet[1] = $aResult[3]  ; number of property items
    Return $aRet
EndFunc   ;==>_GDIPlus_ImageGetPropertySize

When I run the script of which this is a part, $iBuffer is 43763 bytes long and $iCount is 66. The code above, which is from GDIP.7z, assumes that GdipGetAllProperty Items sets pBuffer to point to PropertyItem1, PropertyItem2, ... PropertyItemN. The property item struct is

$tagGDIPPROPERTYITEM = _
    "uint id;" & _          ; ID of this property
    "ulong length;" & _     ; Length of the property value, in bytes
    "word type;" & _        ; Type of the value, as one of TAG_TYPE_XXX constants
    "ptr pvalue;"           ; pointer to property value

Note the pointer. The length of this struct is 16 bytes. So if the data is arranged in this way, $iBuffer would be 66 x 16 = 1056 bytes! So the data cannot be arranged linearly, with one property item after another.

Scenario 2

What if the tag should be like

$tagGDIPPROPERTYITEM = _
    "uint id;" & _          ; ID of this property
    "ulong length;" & _     ; Length of the property value, in bytes
    "word type;" & _        ; Type of the value, as one of TAG_TYPE_XXX constants
    "byte valueVec["&$iLength&"];"

?

I know that one of the property items is about 37K long, and another 1.1K long. The lengths of id, length and type add up to 12 bytes. The lengths of the other values probably average 5.

37K + 1.1K + (12 + 5)*66 = 39222. This is fairly close to 43763 -- but not close enough to convince me that Scenario 2 is correct.

Also,it is strange that the buffer needs to be an odd number of bytes long, because the length of the struct in Scenario1 above (the one I am using) is an even number of bytes.

So what goes?

Early in my trials, I thought that the data is arranged as in Scenario 2. I don't remember where I got this idea.

If the data is arranged per Scenario 2, why does getting property items work as well as it does?

After a night's sleep, I realized that $iBuffer may be the total size occupied by property items. My script now adds up the lengths. They add up to 42707 bytes. 43763 - 42707 = 1056. 1056 / 16 = 66 which is the number of property items! So $iBuffer is the space occupied by values! It is time to do some more thinking.

This does mean that $tBuffer is larger than it needs to be. It also implies that $tagGDIPPROPERTYITEM is correct.

Edited by c.haslam

Spoiler

CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard

 

Share this post


Link to post
Share on other sites
5 hours ago, c.haslam said:

There are many alligators in my coding swamp

:lol: You're lucky your swamp is in your code; mine is between my ears!:D

Not sure whether you've considered this (if so, just ignore this), but be aware of potential member alignment issues within your structs; unless you explicitly align, AutoIt may adjust alignment (implicit align 8) and apply padding. Note in particular (from the Help for DllstructCreate):

Quote

The alignment of a member will be on a boundary that is either a multiple of n or a multiple of the size of the member, whichever is smaller.  (...)

If a change of alignment is needed "align" can be use[d] before the first element which that needs to be changed (...)

The alignment of the beginning of a structure is the maximum alignment of any individual member.
Each member within the structure is be placed at its proper alignment as defined in the previous table, which require implicit internal padding, depending on the previous member.

The interplay of these "rules" may yield some unexpected results (which is why I tend to align 1 explicitly). Just my two cents.

;)

Edited by RTFC

Share this post


Link to post
Share on other sites

RTFC,

I found a bug in GDIPlus_ImageGetPropertyItemValue(): for Case 9,10 I had accidentally left in

$tvalue = DllStructCreate('double val',$pValue)

I have removed it.

I tried adding align 1; at the start of all tags in GDIPlus_ImageGetPropertyItemValue() . This did not change the results in _ArrayDisplay().

I tried adding align 1; at the start of $tagGDIPPROPERTYITEM. This crashed with rc:-1073741819

I was had been hopeful that your suggestion would solve the problem.

GDIPlus_ImageGetPropertyItemValue() now looks like this:

; Returns:
;   byte array and undefined:   binary
;   byte scalar                 scalar
;   string                      string
;   rational                    vector: [n] numerator, [n=1] denominator
;   else                        vector
; Vectors are ref 0
Func _GDIPlus_ImageGetPropertyItemValue($iLength, $iType, $pValue)
    Static Local $tvalue
    Local $qels
If $pValue=0 Then
Return 0
EndIf
    Switch $iType
        Case 1,6,7  ; UBYTE,SBYTE,UNDEFINED
            $qels = $ilength
If $qels=1 Then
$tvalue = DllStructCreate('align 1;byte binary',$pValue)
Else
            $tvalue = DllStructCreate('align 1;byte binary['&$ilength&']',$pValue)
EndIf
        Case 2      ; ASCII
If $ilength=0 Then
Return ''
EndIf
            $qels = $ilength
            $tvalue = DllStructCreate('align 1;char str['&$iLength&']',$pValue)
        Case 3      ; USHORT
            $qels = $iLength/2
            $tvalue = DllStructCreate('align 1;ushort valVec['&$qels&']',$pValue)
        Case 4,5    ; ULONG,URATIONAL
            $qels = $iLength/4
            $tvalue = DllStructCreate('align 1;ulong valVec['&$qels&']',$pValue)
        Case 8      ; SSHORT
            $qels = $iLength/4
            $tvalue = DllStructCreate('align 1;short valVec['&$qels&']',$pValue)
        Case 9,10   ; SLONG,SRATIONAL
            $qels = $iLength/4
            $tvalue = DllStructCreate('align 1;long valVec['&$qels&']',$pValue)
        Case Else
            MsgBox(0,@ScriptLineNumber,'_GDIPlus_ImageGetPropertyItemValue(): type '&$itype& ' found')
    EndSwitch
Local $err = @error
If $err Then
    ConsoleWrite('@error '&$err&@CRLF)
    ConsoleWrite('id '&Hex($gId,4)&' ilength ' &$ilength&' type '&$itype&@CRLF)
    MsgBox(0,@ScriptLineNumber,'id '&Hex($gId,4)&' ilength ' &$ilength&' type '&$itype)
EndIf
    If $err Then Return SetError($err,0,-1)
    Local $ret
    Switch $itype
        Case 1,6,7  ; UBYTE,SBYTE,UNDEFINED
            Local $ret =  DllStructGetData($tvalue,'binary')
        Case 2 ; ASCII
            Local $ret = DllStructGetData($tvalue,'str')
        Case Else
            Local $ret[$qels]
            For $i = 0 To $qels-1
                $ret[$i] = DllStructGetData($tvalue,'valVec',$i+1)
            Next
    EndSwitch
If $err Then
    ConsoleWrite('@error '&$err&@CRLF)
    ConsoleWrite('GetData: id '&Hex($gId,4)&' ilength ' &$ilength&' type '&$itype&@CRLF)
    MsgBox(0,@ScriptLineNumber,'id '&Hex($gId,4)&' ilength ' &$ilength&' type '&$itype)
EndIf
    Return $ret
EndFunc

Diagnostic code and most of the new code is outdented, for now.

I had been excluding property items for which the value is zero and ASCII property items for which the length is zero in the caller. These cases are now handled in this function.

For now, I am only working on the script through to the array display.

Edited by c.haslam

Spoiler

CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard

 

Share this post


Link to post
Share on other sites

There are 3 possibilities for bugs:

  • In my code
  • In a DLLStruct* function
  • In Microsoft's gdip* functions

I have been working on the third possibility.

I have run the script that follows several times. Desk-checking the output to the console has convinced me, at least for now, that Microsoft's GdipGetAllPropertyItems() works consistently. Its return is as advertised, i.e. it is my Scenario 1. This does not rule out the possibility of a memory leak.

That leaves the other two possibilities. A memory leak is possible in both.

It is beyond me as to how the second script below sometimes reports an ASCII string, and sometimes doesn't.

The script used to check GdipGetAllPropertyItems() is below. It reports in the odd format because I needed to be able to find Id's if the alignment was other than 2.

#include <GDIPlus.au3>
#include <Array.au3>
Opt('MustDeclareVars',1)
#include "..\cDebug.au3"

OnAutoItExitRegister(FinishUp)

main()

Func main()
    _GDIPlus_Startup()
    Local $hImage = _GDIPlus_ImageLoadFromFile('H:\temp\AP test data\DSC00824 - Copy.jpg')
    Local $ar = _GDIPlus_ImageGetAllPropertyItemsEx($hImage)
EndFunc

Func _GDIPlus_ImageGetAllPropertyItemsEx($hImage)
    Local $iI, $iCount, $tBuffer, $pBuffer, $iBuffer, $tPropertyItem, $aPropertyItems[1][1], $aResult

    Local $ar = _GDIPlus_ImageGetPropertySize($hImage)
    If @error Then Return SetError(@error, @extended, -1)

    $iBuffer = $ar[0]
    $tBuffer = DllStructCreate("byte[" & $iBuffer & "]")
    $pBuffer = DllStructGetPtr($tBuffer)
    $iCount = $ar[1]
    $aResult = DllCall($__g_hGDIPDll, "uint", "GdipGetAllPropertyItems", "hwnd", $hImage, _
        "uint", $iBuffer, "uint", $iCount, "ptr", $pBuffer)
    If @error Then Return SetError(@error, @extended, -1)
    If $aResult[0] Then Return SetError(10, $aResult[0], False)
    ReDim $aPropertyItems[$iCount + 1][4]
    $aPropertyItems[0][0] = $iCount

    Local $byAr[$iCount*16]
    For $j = 0 To ($iCount-1)*16
        Local $t = DllStructCreate('byte;',$pBuffer+$j)
        $byAr[$j] = DllStructGetData($t,1)
    Next
    For $j = 0 To ($iCount-1)*16
        _consdebug(@ScriptLineNumber,'j,val',($j+1)&'-'&$j,Hex($byAr[$j+1],2)&Hex($byAr[$j],2))
    Next
EndFunc

Func _GDIPlus_ImageGetPropertySize($hImage)
    Local $aRet[2], $aResult

    $aResult = DllCall($__g_hGDIPDll, "uint", "GdipGetPropertySize", "hwnd", $hImage, "uint*", 0, "uint*", 0)
    If @error Then Return SetError(@error, @extended, -1)

    $aRet[0] = $aResult[2]  ; size in bytes
    $aRet[1] = $aResult[3]  ; number of property items
    Return $aRet
EndFunc   ;==>_GDIPlus_ImageGetPropertySize

Func FinishUp()
    _GDIPlus_Shutdown()
EndFunc

There is one strange finding: as mentioned in an earlier post, $tBuffer only needs to be large enough for the 66 property items, so I tried a buffer of 66*16 bytes.  GdipGetAllPropertyItems() returned an error code!

 


Spoiler

CDebug Dumps values of variables including arrays and DLL structs, to a GUI, to the Console, and to the Clipboard

 

Share this post


Link to post
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

  • Similar Content

    • By ripdad
      I ran across a topic while researching the BASS UDF...
      https://www.autoitscript.com/forum/topic/155845-carpenter-needs-help-performing-serious-surgery-on-audiometer2/ and then remembered another topic...
      https://www.autoitscript.com/forum/topic/121624-sound-level-sampling/ which got me to thinking as to how I could get the first topic to go LIVE without the need of loading an mp3.
      This will accept any LIVE AUDIO INPUT.
      Be sure to read this post if you have trouble with it...
      https://www.autoitscript.com/forum/topic/121624-sound-level-sampling/?do=findComment&comment=1400178 Also, read the comments I made in the script, so you will know how it will react to LIVE INPUT streams.

      Live FFT Visual Spectrum.zip
       

      LIVE 128 Band FFT Visual Spectrum.au3
       
    • By UEZ
      Here a little script to load a TGA image file and create a GDI+ bitmap. Currently supported TGA formats are  1/8/15/16/24 and 32-bit.
      As v0.85 is written completely in AutoIt, it might take some time to convert larger 8/15/16/24/32-bit images. ☕
       
      _GDIPlus_TGAImageLoadFromFile.au3 UDF
      v0.85 without assembler acceleration code but with RLE support:
      ;Coded by UEZ #AutoIt3Wrapper_UseX64=n #include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <WinAPIFiles.au3> ; #FUNCTION# ==================================================================================================================== ; Name ..........: _GDIPlus_TGAImageLoadFromFile ; Description ...: Loads a TGA compressed (RLE) / uncompressed image file (1/8/15/16/24/32-bit) and converts it to a GDI+ bitmap format. ; Syntax ........: _GDIPlus_TGAImageLoadFromFile($sFile[, $bPrintInfo = False.]) ; Parameters ....: $sFile - TGA file name to load from disk. ; $bPrintInfo - [optional] Prints some information about the TGA image to console. Default is False. ; Return values .: Success: GDI+ bitmap handle ; Failure: error 1 - file cannot be opened ; error 2 - TGA image is not in one of these formats: 1/8/15/16/24/32-bit ; error 3 - unsupported TGA image type ; error 4 - unable to read file to struct ; error 5 - unknown TGA pixel depth ; error 6 - return bitmap cannot be created ; Version .......: v0.85 build 2019-11-08 beta ; Author ........: UEZ ; Remarks .......: 8/15/16/24/32-bit images might be slow on converting ^^ ; Related .......: _GDIPlus_BitmapCreateFromScan0, _GDIPlus_ImageRotateFlip, DllStructCreate, _WinAPI_CreateFile, _WinAPI_SetFilePointer ; Link ..........: https://www.loc.gov/preservation/digital/formats/fdd/fdd000180.shtml, http://www.fileformat.info/format/tga/egff.htm ; Example .......: Yes ; =============================================================================================================================== Func _GDIPlus_TGAImageLoadFromFile($sFile, $bPrintInfo = False) Local Const $hFile = _WinAPI_CreateFile($sFile, 2, 2) If Not $hFile Then Return SetError(1, 0, 0) Local Const $tagTGAHeader = "align 1;byte idLength;byte colormapType;byte imageType;word firstEntryIndex;word colormapLength;byte colormapEntrySize;word xOrigin;word yOrigin;word width;word height;byte pixelDepth;byte imageDescriptor" Local Const $tagTGAFooter = "dword extAreaOffset;dword devDirOffset;byte imageID[18]" Local Const $tagTGAExtention = "align 1;word extSize;byte authorName[41];byte authorComments[324];word timeM;word timeD;word timeY;word timeHr;word timeMin;word timeSec;byte jobName[41];word jobTimeHr;word jobTimeMin;word jobTimeSec;byte swID[41];word swVersionNr;byte swVersionLetter;long keyColor;word pxAspectRatioNum;word pxAspectRatioDom;word gammaNum;word gammaDom;dword colCorrOffset;dword postStampOffset;dword scanLineOffset;byte attribType" Local Const $tTGAHeader = DllStructCreate($tagTGAHeader) Local $tTGAFooter = DllStructCreate($tagTGAFooter) Local Const $tTGAExtention = DllStructCreate($tagTGAExtention) Local $dwBytesRead, $tTGAImageID, $tagTGAImageID, $iColorValuesStartPos = 0 _WinAPI_ReadFile($hFile, $tTGAHeader, DllStructGetSize($tTGAHeader), $dwBytesRead) $iColorValuesStartPos += $dwBytesRead If $tTGAHeader.idLength > 0 Then $tagTGAImageID = "byte imageID[" & $tTGAHeader.idLength & "]" $tTGAImageID = DllStructCreate($tagTGAImageID) _WinAPI_ReadFile($hFile, $tTGAImageID, $tTGAHeader.idLength, $dwBytesRead) $iColorValuesStartPos += $dwBytesRead EndIf Local Const $iPxDepth = $tTGAHeader.pixelDepth If Not BitOR($iPxDepth = 32, $iPxDepth = 24, $iPxDepth = 16, $iPxDepth = 15, $iPxDepth = 8, $iPxDepth = 1) Then _WinAPI_CloseHandle($hFile) Return SetError(2, 0, 0) EndIf #cs ImageType Image Data Type Colormap Encoding 0 No image data included in file No No 1 Colormapped image data Yes No 2 Truecolor image data No No 3 Monochrome image data No No 9 Colormapped image data Yes Yes 10 Truecolor image data No Yes 11 Monochrome image data No Yes #ce If Not BitOR($tTGAHeader.imageType = 0x01, $tTGAHeader.imageType = 0x02, $tTGAHeader.imageType = 0x03, $tTGAHeader.imageType = 0x09, $tTGAHeader.imageType = 0x0A, $tTGAHeader.imageType = 0x0B) Then _WinAPI_CloseHandle($hFile) Return SetError(3, 0, 0) EndIf Local $iW = $tTGAHeader.width, $iH = $tTGAHeader.height, $colorwidth = $tTGAHeader.colormapEntrySize / 8, _ $colorTblSize = $tTGAHeader.colormapLength * $colorwidth Local $dwBufferSize = FileGetSize($sFile) Local $tSrcBmp = DllStructCreate("ubyte color[" & $dwBufferSize & "]") _WinAPI_ReadFile($hFile, $tSrcBmp, $dwBufferSize, $dwBytesRead) _WinAPI_SetFilePointer($hFile, -26, $FILE_END) _WinAPI_ReadFile($hFile, $tTGAFooter, 26, $dwBytesRead) Local $sFooter = StringTrimRight(BinaryToString($tTGAFooter.imageID), 1), $iOffset = 0, $iOffset2, $iOffset3 If Not StringCompare($sFooter, "TRUEVISION-XFILE.") Then ;read extension information to struct if available $iOffset = $tTGAFooter.extAreaOffset _WinAPI_SetFilePointer($hFile, $iOffset, $FILE_BEGIN) _WinAPI_ReadFile($hFile, $tTGAExtention, 0x01EF, $dwBytesRead) Else $tTGAFooter.extAreaOffset = 0 EndIf _WinAPI_CloseHandle($hFile) If $dwBytesRead = 0 Then Return SetError(4, _WinAPI_GetLastError(), 0) Local $bRLE = BitOR($tTGAHeader.imageType = 0x09, $tTGAHeader.imageType = 0x0A, $tTGAHeader.imageType = 0x0B) If $bPrintInfo Then ConsoleWrite("idLength: " & $tTGAHeader.idLength & @CRLF) ConsoleWrite("colormapType: " & $tTGAHeader.colormapType & @CRLF) ConsoleWrite("imageType: " & $tTGAHeader.imageType & @CRLF) ConsoleWrite("firstEntryIndex: " & $tTGAHeader.firstEntryIndex & @CRLF) ConsoleWrite("colormapLength: " & $tTGAHeader.colormapLength & @CRLF) ConsoleWrite("colormapEntrySize: " & $tTGAHeader.colormapEntrySize & @CRLF) ConsoleWrite("xOrigin: " & $tTGAHeader.xOrigin & @CRLF) ConsoleWrite("yOrigin: " & $tTGAHeader.yOrigin & @CRLF) ConsoleWrite("width: " & $tTGAHeader.width & @CRLF) ConsoleWrite("height: " & $tTGAHeader.height & @CRLF) ConsoleWrite("pixelDepth: " & $iPxDepth & @CRLF) ConsoleWrite("imageDescriptor: " & $tTGAHeader.imageDescriptor & @CRLF) If $tTGAHeader.idLength > 0 Then ConsoleWrite("ImageID: " & RemoveNullChars($tTGAImageID.imageID) & @CRLF) If $iOffset Then ConsoleWrite("authorName: " & RemoveNullChars($tTGAExtention.authorName) & @CRLF) ConsoleWrite("authorComments: " & RemoveNullChars($tTGAExtention.authorComments) & @CRLF) ConsoleWrite("jobName: " & RemoveNullChars($tTGAExtention.jobName) & @CRLF) ConsoleWrite("swID: " & RemoveNullChars($tTGAExtention.swID) & @CRLF) EndIf ConsoleWrite("RLE packed: " & $bRLE & @CRLF) EndIf Local Static $tDestBmp ;must be static otherwise bitmap data might get corrupted or in worst case script will crash Local $stride, $iPixelFormat Switch $iPxDepth Case 1 ;1-bit $iPixelFormat = $GDIP_PXF01INDEXED $stride = BitAND(($iW * 1) + 1, BitNOT(1)) $tDestBmp = DllStructCreate("uint color[" & $stride * $iH & "];") Case 8, 24 $iPixelFormat = $GDIP_PXF24RGB $stride = BitAND(($iW * 3) + 3, BitNOT(3)) $tDestBmp = DllStructCreate("ubyte color[" & $stride * $iH & "];") Case 15, 16 $iPixelFormat = $GDIP_PXF16RGB555 $stride = BitAND(($iW * 2) + 2, BitNOT(2)) $tDestBmp = DllStructCreate("ubyte color[" & $stride * $iH & "];") Case 32 $iPixelFormat = $GDIP_PXF32ARGB $stride = $iW * 4 $tDestBmp = DllStructCreate("ubyte color[" & $stride * $iH & "];") Case Else Return SetError(5, 0, 0) EndSwitch If Mod($stride, 4) <> 0 Then $stride += 4 - Mod($stride, 4) Local Const $hBitmap = _GDIPlus_BitmapCreateFromScan0($iW, $iH, $iPixelFormat, $stride, $tDestBmp) If @error Or Not $hBitmap Then Return SetError(6, @error, 0) Local $c, $q, $x, $y, $t1, $t2, $t3, $t4, $col, $red, $green, $blue, $alpha, $iLen, $iStart, $iEnd, $iLength, $iWW Local Const $hDLL = DllOpen("msvcrt.dll") Switch $iPxDepth Case 1 ;1-bit For $y = 0 To $iH - 1 $t1 = $y * $stride DllCall($hDLL, "ptr:cdecl", "memcpy", "ptr", DllStructGetPtr($tDestBmp) + $t1, "ptr", DllStructGetPtr($tSrcBmp) + BitShift($t1, 3), "uint", $stride) Next Case 8 ;8-bit ;if a color table is available, just use it If $tTGAHeader.colormapType = 1 Then Local $tMapColorTbl = DllStructCreate("ubyte bgr[" & $colorTblSize & "]", DllStructGetPtr($tSrcBmp, "color") + $tTGAHeader.firstEntryIndex) Switch $bRLE Case 0 For $y = 0 To ($iH - 1) $iOffset = $y * $iW + $colorTblSize $iOffset2 = $y * $stride For $x = 0 To ($iW - 1) $t1 = $iOffset2 + $x * 3 $t2 = $tSrcBmp.color($iOffset + $x + 1) * $colorwidth Switch $colorwidth Case 3, 4 $tDestBmp.color($t1 + 1) = $tMapColorTbl.bgr($t2 + 1) $tDestBmp.color($t1 + 2) = $tMapColorTbl.bgr($t2 + 2) $tDestBmp.color($t1 + 3) = $tMapColorTbl.bgr($t2 + 3) Case 2 ;convert from RGB555 to RGB $col = BitOR(BitShift($tMapColorTbl.bgr($t2 + 2), -8), $tMapColorTbl.bgr($t2 + 1)) ;RGB555 $tDestBmp.color($t1 + 1) = BitShift(BitAND($col, 0x001F), -3) ;B $tDestBmp.color($t1 + 2) = BitShift(BitShift(BitAND($col, 0x03E0), 5), -3) ;G $tDestBmp.color($t1 + 3) = BitShift(BitShift(BitAND($col, 0x7C00), 10), -3) ;R EndSwitch Next Next Case Else ;RLE encoded TGA images $c = 0 $x = 0 $y = 0 $iOffset = $colorTblSize + 1 $iStart = Int($iColorValuesStartPos + $colorTblSize) $iEnd = $tTGAFooter.extAreaOffset > 0 ? $tTGAFooter.extAreaOffset : $dwBufferSize $iLength = $iEnd - $iStart - 1 $iWW = $iW - 1 $t3 = $colorwidth = 2 ? 2 : 3 While $c <= $iLength $iOffset2 = Int($tSrcBmp.color($iOffset + $c)) $iLen = BitAND($iOffset2, 0x7F) + 1 If BitAND($iOffset2, 0x80) Then ; check for packet format ;run length packet format $c += 1 $iOffset3 = Int($tSrcBmp.color($iOffset + $c)) * $t3 $t2 = $y * $stride For $q = 1 To $iLen $t1 = $t2 + $x * 3 Switch $colorwidth Case 3, 4 $tDestBmp.color($t1 + 1) = $tMapColorTbl.bgr($iOffset3 + 1) $tDestBmp.color($t1 + 2) = $tMapColorTbl.bgr($iOffset3 + 2) $tDestBmp.color($t1 + 3) = $tMapColorTbl.bgr($iOffset3 + 3) Case 2 ;convert from RGB555 to RGB $col = BitOR(BitShift($tMapColorTbl.bgr($iOffset3 + 2), -8), $tMapColorTbl.bgr($iOffset3 + 1)) ;RGB555 $tDestBmp.color($t1 + 1) = BitShift(BitAND($col, 0x001F), -3) ;B $tDestBmp.color($t1 + 2) = BitShift(BitShift(BitAND($col, 0x03E0), 5), -3) ;G $tDestBmp.color($t1 + 3) = BitShift(BitShift(BitAND($col, 0x7C00), 10), -3) ;R EndSwitch $x += 1 If $x > $iWW Then $x = 0 $y += 1 $t2 = $y * $stride EndIf Next $c += 1 Else ;raw packet format $c += 1 $t2 = $y * $stride For $q = 1 To $iLen $iOffset3 = Int($tSrcBmp.color($iOffset + $c)) * $t3 $t1 = $t2 + $x * 3 Switch $colorwidth Case 3, 4 $tDestBmp.color($t1 + 1) = $tMapColorTbl.bgr($iOffset3 + 1) $tDestBmp.color($t1 + 2) = $tMapColorTbl.bgr($iOffset3 + 2) $tDestBmp.color($t1 + 3) = $tMapColorTbl.bgr($iOffset3 + 3) Case 2 ;convert from RGB555 to RGB $col = BitOR(BitShift($tMapColorTbl.bgr($iOffset3 + 2), -8), $tMapColorTbl.bgr($iOffset3 + 1)) ;RGB555 $tDestBmp.color($t1 + 1) = BitShift(BitAND($col, 0x001F), -3) ;B $tDestBmp.color($t1 + 2) = BitShift(BitShift(BitAND($col, 0x03E0), 5), -3) ;G $tDestBmp.color($t1 + 3) = BitShift(BitShift(BitAND($col, 0x7C00), 10), -3) ;R EndSwitch $x += 1 If $x > $iWW Then $x = 0 $y += 1 $t2 = $y * $stride EndIf $c += 1 Next EndIf WEnd EndSwitch Else ;convert it to grayscale Switch $bRLE Case 0 For $y = 0 To $iH - 1 $iOffset = $y * $iW + $colorTblSize $iOffset2 = $y * $stride For $x = 0 To $iW - 1 $t1 = $iOffset + $x - 2 $t2 = $iOffset2 + $x * 3 $blue = $tSrcBmp.color($t1 + 1) $green = $tSrcBmp.color($t1 + 2) $red = $tSrcBmp.color($t1 + 3) $col = $red $col = $col < 0 ? 0 : $col > 255 ? 255 : $col $tDestBmp.color($t2 + 1) = $col $tDestBmp.color($t2 + 2) = $col $tDestBmp.color($t2 + 3) = $col Next Next Case Else $c = 0 $x = 0 $y = 0 $iOffset = $colorTblSize + 1 $iStart = Int($iColorValuesStartPos + $colorTblSize) $iEnd = $tTGAFooter.extAreaOffset > 0 ? $tTGAFooter.extAreaOffset : $dwBufferSize $iLength = $iEnd - $iStart - 1 $iWW = $iW - 1 While $c <= $iLength $iOffset2 = Int($tSrcBmp.color($iOffset + $c)) $iLen = BitAND($iOffset2, 0x7F) + 1 If BitAND($iOffset2, 0x80) Then ; check for packet format ;run length packet format $c += 1 $iOffset3 = Int($tSrcBmp.color($iOffset + $c)) * 3 $blue = $iOffset3 $green = $iOffset3 + 1 $red = $iOffset3 + 2 $col = ($red + $green + $blue) / 9 $col = $col < 0 ? 0 : $col > 255 ? 255 : $col $t2 = $y * $stride For $q = 1 To $iLen $t1 = $t2 + $x * 3 $tDestBmp.color($t1 + 1) = $col $tDestBmp.color($t1 + 2) = $col $tDestBmp.color($t1 + 3) = $col $x += 1 If $x > $iWW Then $x = 0 $y += 1 $t2 = $y * $stride EndIf Next $c += 1 Else ;raw packet format $c += 1 $t2 = $y * $stride For $q = 1 To $iLen $iOffset3 = Int($tSrcBmp.color($iOffset + $c)) * 3 $blue = $iOffset3 $green = $iOffset3 + 1 $red = $iOffset3 + 2 $col = ($red + $green + $blue) / 9 $col = $col < 0 ? 0 : $col > 255 ? 255 : $col $t1 = $t2 + $x * 3 $tDestBmp.color($t1 + 1) = $col $tDestBmp.color($t1 + 2) = $col $tDestBmp.color($t1 + 3) = $col $x += 1 If $x > $iWW Then $x = 0 $y += 1 $t2 = $y * $stride EndIf $c += 1 Next EndIf WEnd EndSwitch EndIf Case 15, 16, 24, 32 ;15/16/24/32-bit, as the bitmap format is the same we can use memcpy to copy the pixel data directly to the memory. ;Exeptions are 15/16/24-bit images whose width is not a divider of 4! If BitOR($iPxDepth = 15, $iPxDepth = 16, $iPxDepth = 24) Then If BitOR(Mod($iW, 4), $bRLE) Then Switch $iPxDepth Case 15, 16 Switch $bRLE Case 0 $t4 = $iW * 2 For $y = 0 To ($iH - 1) $iOffset = $y * $t4 $iOffset2 = $y * $stride For $x = 0 To ($iW - 1) $t3 = $x * 2 $t1 = $iOffset + $t3 $t2 = $iOffset2 + $t3 ;RGB555 $tDestBmp.color($t2 + 1) = $tSrcBmp.color($t1 + $colorTblSize + 1) $tDestBmp.color($t2 + 2) = $tSrcBmp.color($t1 + $colorTblSize + 2) Next Next Case Else $c = 0 $x = 0 $y = 0 $iStart = Int($iColorValuesStartPos + $colorTblSize) $iEnd = $tTGAFooter.extAreaOffset > 0 ? $tTGAFooter.extAreaOffset : $dwBufferSize $iLength = $iEnd - $iStart - 1 $iWW = $iW - 1 While $c <= $iLength $iOffset2 = Int($tSrcBmp.color($colorTblSize + $c + 1)) $iLen = BitAND($iOffset2, 0x7F) + 1 If BitAND($iOffset2, 0x80) Then ; check for packet format ;run length packet format $c += 1 $t3 = $y * $stride For $q = 1 To $iLen $t1 = $t3 + $x * 2 $t2 = $colorTblSize + $c $tDestBmp.color($t1 + 1) = $tSrcBmp.color($t2 + 1) $tDestBmp.color($t1 + 2) = $tSrcBmp.color($t2 + 2) $x += 1 If $x > $iWW Then $x = 0 $y += 1 $t3 = $y * $stride EndIf Next $c += 2 Else ;raw packet format $c += 1 $t3 = $y * $stride For $q = 1 To $iLen $t1 = $t3 + $x * 2 $t2 = $colorTblSize + $c $tDestBmp.color($t1 + 1) = $tSrcBmp.color($t2 + 1) $tDestBmp.color($t1 + 2) = $tSrcBmp.color($t2 + 2) $x += 1 If $x > $iWW Then $x = 0 $y += 1 $t3 = $y * $stride EndIf $c += 2 Next EndIf WEnd EndSwitch Case 24 Switch $bRLE Case 0 $t4 = $iW * 3 For $y = 0 To $iH - 1 $iOffset = $y * $t4 $iOffset2 = $y * $stride For $x = 0 To ($iW - 1) $t3 = $x * 3 $t1 = $iOffset + $t3 $blue = $tSrcBmp.color($t1 + 1) $green = $tSrcBmp.color($t1 + 2) $red = $tSrcBmp.color($t1 + 3) $t2 = $iOffset2 + $t3 $tDestBmp.color($t2 + 1) = $blue $tDestBmp.color($t2 + 2) = $green $tDestBmp.color($t2 + 3) = $red Next Next Case Else $c = 0 $x = 0 $y = 0 $iStart = Int($iColorValuesStartPos + $colorTblSize) $iEnd = $tTGAFooter.extAreaOffset > 0 ? $tTGAFooter.extAreaOffset : $dwBufferSize $iLength = $iEnd - $iStart - 1 $iWW = $iW - 1 While $c <= $iLength $iOffset2 = Int($tSrcBmp.color($c + 1)) $iLen = BitAND($iOffset2, 0x7F) + 1 If BitAND($iOffset2, 0x80) Then ; check for packet format ;run length packet format $c += 1 $blue = $tSrcBmp.color($c + 1) $green = $tSrcBmp.color($c + 2) $red = $tSrcBmp.color($c + 3) $t2 = $y * $stride For $q = 1 To $iLen $t1 = $t2 + $x * 3 $tDestBmp.color($t1 + 1) = $blue $tDestBmp.color($t1 + 2) = $green $tDestBmp.color($t1 + 3) = $red $x += 1 If $x > $iWW Then $x = 0 $y += 1 $t2 = $y * $stride EndIf Next $c += 3 Else ;raw packet format $c += 1 $t2 = $y * $stride For $q = 1 To $iLen $blue = $tSrcBmp.color($c + 1) $green = $tSrcBmp.color($c + 2) $red = $tSrcBmp.color($c + 3) $t1 = $t2 + $x * 3 $tDestBmp.color($t1 + 1) = $blue $tDestBmp.color($t1 + 2) = $green $tDestBmp.color($t1 + 3) = $red $x += 1 If $x > $iWW Then $x = 0 $y += 1 $t2 = $y * $stride EndIf $c += 3 Next EndIf WEnd EndSwitch EndSwitch Else For $y = 0 To $iH - 1 $t1 = $y * $stride DllCall($hDLL, "ptr:cdecl", "memcpy", "ptr", DllStructGetPtr($tDestBmp) + $t1, "ptr", DllStructGetPtr($tSrcBmp) + $t1, "uint", $stride) Next EndIf Else Switch $bRLE Case 0 For $y = 0 To $iH - 1 $t1 = $y * $stride DllCall($hDLL, "ptr:cdecl", "memcpy", "ptr", DllStructGetPtr($tDestBmp) + $t1, "ptr", DllStructGetPtr($tSrcBmp) + $t1, "uint", $stride) Next Case Else $c = 0 $x = 0 $y = 0 $iStart = Int($iColorValuesStartPos + $colorTblSize) $iEnd = $tTGAFooter.extAreaOffset > 0 ? $tTGAFooter.extAreaOffset : $dwBufferSize $iLength = $iEnd - $iStart - 1 $iWW = $iW - 1 While $c <= $iLength $iOffset2 = Int($tSrcBmp.color($c + 1)) $iLen = BitAND($iOffset2, 0x7F) + 1 If BitAND($iOffset2, 0x80) Then ; check for packet format ;run length packet format $c += 1 $blue = $tSrcBmp.color($c + 1) $green = $tSrcBmp.color($c + 2) $red = $tSrcBmp.color($c + 3) $alpha = $tSrcBmp.color($c + 4) $t2 = $y * $stride For $q = 1 To $iLen $t1 = $t2 + $x * 4 $tDestBmp.color($t1 + 1) = $blue $tDestBmp.color($t1 + 2) = $green $tDestBmp.color($t1 + 3) = $red $tDestBmp.color($t1 + 4) = $alpha $x += 1 If $x > $iWW Then $x = 0 $y += 1 $t2 = $y * $stride EndIf Next $c += 4 Else ;raw packet format $c += 1 $t2 = $y * $stride For $q = 1 To $iLen $blue = $tSrcBmp.color($c + 1) $green = $tSrcBmp.color($c + 2) $red = $tSrcBmp.color($c + 3) $alpha = $tSrcBmp.color($c + 4) $t1 = $t2 + $x * 4 $tDestBmp.color($t1 + 1) = $blue $tDestBmp.color($t1 + 2) = $green $tDestBmp.color($t1 + 3) = $red $tDestBmp.color($t1 + 4) = $alpha $x += 1 If $x > $iWW Then $x = 0 $y += 1 $t2 = $y * $stride EndIf $c += 4 Next EndIf WEnd EndSwitch EndIf EndSwitch DllClose($hDLL) ;TGA image is stored bottom up in file. Need to flip it. If BitAND($tTGAHeader.imageDescriptor, 0x30) <> 0x20 Then _GDIPlus_ImageRotateFlip($hBitmap, $GDIP_Rotate180FlipX) $tSrcBmp = 0 Return $hBitmap EndFunc ;==>_GDIPlus_TGAImageLoadFromFile ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name ..........: RemoveNullChars ; Description ...: Converts a null terminated binary string to a string ; Author ........: UEZ ; =============================================================================================================================== Func RemoveNullChars($bin) Local $a = StringRegExp($bin, "[[:xdigit:]+]{2}", 3), $s, $i If @error Then Return $s For $i = 0 To UBound($a) - 1 If $a[$i] = "00" Then ExitLoop $s &= Chr(Dec($a[$i])) Next Return $s EndFunc ;==>RemoveNullChars ;------------- Example ------------- Global $sFile = FileOpenDialog("Select a TGA file", "", "TGA image(*.tga)") If @error Then Exit _GDIPlus_Startup() Global $endtime, $timer = TimerInit() Global $hImage = _GDIPlus_TGAImageLoadFromFile($sFile, True) If @error Then ConsoleWrite(@error & " / " & @extended & @CRLF) _GDIPlus_Shutdown() Exit EndIf $endtime = TimerDiff($timer) ;~ _GDIPlus_ImageSaveToFile($hImage, @ScriptDir & "\Converted.png") ;~ ShellExecute(@ScriptDir & "\Converted.png") Global $iW = _GDIPlus_ImageGetWidth($hImage), $iH = _GDIPlus_ImageGetHeight($hImage) Global $hGui = GUICreate("TGA Image Loader by UEZ", $iW, $iH) GUISetState() Global $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGui) _GDIPlus_GraphicsDrawImageRect($hGraphics, $hImage, 0, 0, $iW, $iH) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE _GDIPlus_BitmapDispose($hImage) _GDIPlus_GraphicsDispose($hGraphics) _GDIPlus_Shutdown() Exit Case $GUI_EVENT_RESTORE _GDIPlus_GraphicsDrawImageRect($hGraphics, $hImage, 0, 0, $iW, $iH) EndSwitch WEnd  
      v0.80 with assembler acceleration (thanks to AndyG for Assembleit2) but without RLE support yet:
      ;Coded by UEZ #AutoIt3Wrapper_Compile_Both=y #AutoIt3Wrapper_UseX64=n #include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <Memory.au3> #include <WinAPIFiles.au3> ; #FUNCTION# ==================================================================================================================== ; Name ..........: _GDIPlus_TGAImageLoadFromFile ; Description ...: Loads an uncompressed TGA image file (1/8/15/16/24/32-bit) and converts it to a GDI+ bitmap format. ; Syntax ........: _GDIPlus_TGAImageLoadFromFile($sFile[, $bPrintInfo = False.]) ; Parameters ....: $sFile - TGA file name to load from disk. ; $bPrintInfo - [optional] Prints some information about the TGA image to console. Default is False. ; Return values .: Success: GDI+ bitmap handle ; Failure: error 1 - file cannot be opened ; error 2 - TGA image is not in one of these formats: 1/8/15/16/24/32-bit ; error 3 - unsupported TGA image type ; error 4 - unable to read file to struct ; error 5 - unknown TGA pixel depth ; error 6 - return bitmap cannot be created ; Version .......: v0.80 build 2019-10-23 beta ; Author ........: UEZ - thanks to AndyG for Assembleit2 ; Remarks .......: No RLE compressed TGA image support yet! ; Related .......: _GDIPlus_BitmapCreateFromScan0, _GDIPlus_ImageRotateFlip, DllStructCreate, _WinAPI_CreateFile, _WinAPI_SetFilePointer ; Link ..........: https://www.loc.gov/preservation/digital/formats/fdd/fdd000180.shtml, http://www.fileformat.info/format/tga/egff.htm ; Example .......: Yes ; =============================================================================================================================== Func _GDIPlus_TGAImageLoadFromFile($sFile, $bPrintInfo = False) Local Const $hFile = _WinAPI_CreateFile($sFile, 2, 2) If Not $hFile Then Return SetError(1, 0, 0) Local Const $tagTGAHeader = "align 1;byte idLength;byte colormapType;byte imageType;word firstEntryIndex;word colormapLength;byte colormapEntrySize;word xOrigin;word yOrigin;word width;word height;byte pixelDepth;byte imageDescriptor" Local Const $tagTGAFooter = "dword extAreaOffset;dword devDirOffset;byte imageID[18]" Local Const $tagTGAExtention = "align 1;word extSize;byte authorName[41];byte authorComments[324];word timeM;word timeD;word timeY;word timeHr;word timeMin;word timeSec;byte jobName[41];word jobTimeHr;word jobTimeMin;word jobTimeSec;byte swID[41];word swVersionNr;byte swVersionLetter;long keyColor;word pxAspectRatioNum;word pxAspectRatioDom;word gammaNum;word gammaDom;dword colCorrOffset;dword postStampOffset;dword scanLineOffset;byte attribType" Local Const $tTGAHeader = DllStructCreate($tagTGAHeader) Local Const $tTGAFooter = DllStructCreate($tagTGAFooter) Local Const $tTGAExtention = DllStructCreate($tagTGAExtention) Local $dwBytesRead, $tTGAImageID, $tagTGAImageID _WinAPI_ReadFile($hFile, $tTGAHeader, DllStructGetSize($tTGAHeader), $dwBytesRead) If $tTGAHeader.idLength > 0 Then $tagTGAImageID = "byte imageID[" & $tTGAHeader.idLength & "]" $tTGAImageID = DllStructCreate($tagTGAImageID) _WinAPI_ReadFile($hFile, $tTGAImageID, $tTGAHeader.idLength, $dwBytesRead) EndIf Local Const $iPxDepth = $tTGAHeader.pixelDepth If Not BitOR($iPxDepth = 32, $iPxDepth = 24, $iPxDepth = 16, $iPxDepth = 15, $iPxDepth = 8, $iPxDepth = 1) Then _WinAPI_CloseHandle($hFile) Return SetError(2, 0, 0) EndIf #cs ImageType Image Data Type Colormap Encoding 0 No image data included in file No No 1 Colormapped image data Yes No 2 Truecolor image data No No 3 Monochrome image data No No 9 Colormapped image data Yes Yes 10 Truecolor image data No Yes 11 Monochrome image data No Yes #ce If Not BitOR($tTGAHeader.imageType = 0x01, $tTGAHeader.imageType = 0x02, $tTGAHeader.imageType = 0x03) Then _WinAPI_CloseHandle($hFile) Return SetError(3, 0, 0) EndIf Local $iW = $tTGAHeader.width, $iH = $tTGAHeader.height, $bytesPerPixel = $iPxDepth / 8, $colorwidth = $tTGAHeader.colormapEntrySize / 8, _ $colorTblSize = $tTGAHeader.colormapLength * $colorwidth If $tTGAHeader.colormapEntrySize < 24 Then $bytesPerPixel = 4 Local Const $dwBufferSize = FileGetSize($sFile) Local $tSrcBmp = DllStructCreate("ubyte color[" & $dwBufferSize + $colorTblSize & "]") _WinAPI_ReadFile($hFile, $tSrcBmp, $dwBufferSize + $colorTblSize, $dwBytesRead) _WinAPI_SetFilePointer($hFile, -26, $FILE_END) _WinAPI_ReadFile($hFile, $tTGAFooter, 26, $dwBytesRead) Local $sFooter = StringTrimRight(BinaryToString($tTGAFooter.imageID), 1), $iOffset = 0, $iOffset2 If Not StringCompare($sFooter, "TRUEVISION-XFILE.") Then ;read extension information to struct if available $iOffset = $tTGAFooter.extAreaOffset _WinAPI_SetFilePointer($hFile, $iOffset, $FILE_BEGIN) _WinAPI_ReadFile($hFile, $tTGAExtention, 0x01EF, $dwBytesRead) EndIf _WinAPI_CloseHandle($hFile) If $dwBytesRead = 0 Then Return SetError(4, _WinAPI_GetLastError(), 0) If $bPrintInfo Then ConsoleWrite("idLength: " & $tTGAHeader.idLength & @CRLF) ConsoleWrite("colormapType: " & $tTGAHeader.colormapType & @CRLF) ConsoleWrite("imageType: " & $tTGAHeader.imageType & @CRLF) ConsoleWrite("firstEntryIndex: " & $tTGAHeader.firstEntryIndex & @CRLF) ConsoleWrite("colormapLength: " & $tTGAHeader.colormapLength & @CRLF) ConsoleWrite("colormapEntrySize: " & $tTGAHeader.colormapEntrySize & @CRLF) ConsoleWrite("xOrigin: " & $tTGAHeader.xOrigin & @CRLF) ConsoleWrite("yOrigin: " & $tTGAHeader.yOrigin & @CRLF) ConsoleWrite("width: " & $tTGAHeader.width & @CRLF) ConsoleWrite("height: " & $tTGAHeader.height & @CRLF) ConsoleWrite("pixelDepth: " & $iPxDepth & @CRLF) ConsoleWrite("imageDescriptor: " & $tTGAHeader.imageDescriptor & @CRLF) If $tTGAHeader.idLength > 0 Then ConsoleWrite("ImageID: " & RemoveNullChars($tTGAImageID.imageID) & @CRLF) If $iOffset Then ConsoleWrite("authorName: " & RemoveNullChars($tTGAExtention.authorName) & @CRLF) ConsoleWrite("authorComments: " & RemoveNullChars($tTGAExtention.authorComments) & @CRLF) ConsoleWrite("jobName: " & RemoveNullChars($tTGAExtention.jobName) & @CRLF) ConsoleWrite("swID: " & RemoveNullChars($tTGAExtention.swID) & @CRLF) EndIf EndIf Local Static $tDestBmp ;must be static otherwise bitmap data might get corrupted or in worst case script will crash Local $stride, $iPixelFormat Switch $iPxDepth Case 1 ;1-bit $iPixelFormat = $GDIP_PXF01INDEXED $stride = BitAND(($iW * 1) + 1, BitNOT(1)) $tDestBmp = DllStructCreate("uint color[" & $stride * $iH + 1 & "];") Case 8, 24 $iPixelFormat = $GDIP_PXF24RGB $stride = BitAND(($iW * 3) + 3, BitNOT(3)) $tDestBmp = DllStructCreate("uint color[" & $stride * $iH + 1 & "];") Case 15, 16 $iPixelFormat = $GDIP_PXF16RGB555 $stride = BitAND(($iW * 2) + 2, BitNOT(2)) $tDestBmp = DllStructCreate("uint color[" & $stride * $iH + 1 & "];") Case 32 $iPixelFormat = $GDIP_PXF32ARGB $stride = $iW * 4 $tDestBmp = DllStructCreate("uint color[" & $stride * $iH + 1 & "];") Case Else Return SetError(5, 0, 0) EndSwitch If Mod($stride, 4) <> 0 Then $stride += 4 - Mod($stride, 4) Local Const $hBitmap = _GDIPlus_BitmapCreateFromScan0($iW, $iH, $iPixelFormat, $stride, $tDestBmp) If @error Or Not $hBitmap Then Return SetError(6, @error, 0) Local $fTimer = TimerInit() Local $x, $x1, $y, $t1 Local Const $hDLL = DllOpen("msvcrt.dll") Local Const $tagParam = "ptr tSrcBmp;ptr tDestBmp;dword strideSrc;dword strideDest;dword w;dword h;dword colorTblSize;dword t1;dword t2" Local $tParam If @AutoItX64 Then $tParam = _DLLStructCreate64($tagParam) Else $tParam = DLLStructCreate($tagParam) EndIf $tParam.tSrcBmp = DllStructGetPtr($tSrcBmp) $tParam.tDestBmp = DllStructGetPtr($tDestBmp) $tParam.strideDest = $stride $tParam.w = ($iW - 1) $tParam.h = ($iH - 1) $tParam.colorTblSize = $colorTblSize Switch $iPxDepth Case 1 ;1-bit For $y = 0 To $iH - 1 $t1 = $y * $stride DllCall($hDLL, "ptr:cdecl", "memcpy", "ptr", DllStructGetPtr($tDestBmp) + $t1, "ptr", DllStructGetPtr($tSrcBmp) + BitShift($t1, 3), "uint", $stride) Next Case 8 ;8-bit ConsoleWrite("Using Assembler code to speed-up..." & @CRLF) ;if a color table is available, just use it If $tTGAHeader.colormapType = 1 Then Local $tMapColorTbl = DllStructCreate("ubyte bgr[" & $colorTblSize & "]", DllStructGetPtr($tSrcBmp, "color") + $tTGAHeader.firstEntryIndex) Local $tParam2, $tagParam2 = "align 1;ptr tSrcBmp;ptr tDestBmp;ptr colormap;dword strideSrc;dword strideDest;dword w;dword h;dword colorTblSize;dword colorwidth;dword t1;dword t2;byte r5;byte g5;byte b5;" If @AutoItX64 Then $tParam2 = _DLLStructCreate64($tagParam2) Else $tParam2 = DllStructCreate($tagParam2) EndIf $tParam2.tSrcBmp = DllStructGetPtr($tSrcBmp) $tParam2.tDestBmp = DllStructGetPtr($tDestBmp) $tParam2.colormap = DllStructGetPtr($tMapColorTbl) $tParam2.strideSrc = $iW $tParam2.strideDest = $stride $tParam2.colorwidth = $colorwidth $tParam2.w = ($iW - 1) $tParam2.h = ($iH - 1) $tParam2.colorTblSize = $colorTblSize Switch @AutoItX64 Case False Local Const $bBinASM8cm_x86 = Binary("0x608B7C242431C990909090909090909089C8F7670C03471C89472489C8F7671089472831DB8B472401D8030789C231C08A02F767208B570801C28B32B803000000F7E303472803470489C5837F200275476689F26683E21F66C1E20388572E6689F26681E2E00366C1EA0566C1E20388572D6689F26681E2007C66C1EA0A66C1E20388572C31C00A472CC1E0080A472DC1E0080A472E89C6897500433B5F147684413B4F180F8665FFFFFF61C20400") Local $tBinASM8cm_x86 = DllStructCreate("ubyte asm[" & BinaryLen($bBinASM8cm_x86) & "]") $tBinASM8cm_x86.asm = $bBinASM8cm_x86 DllCallAddress("none", DllStructGetPtr($tBinASM8cm_x86), "ptr", DllStructGetPtr($tParam2)) Case Else Local Const $bBinASM8cm_x64 = Binary("0x575653554989CF41BE000000009090904489F041F7671841034728418947304489F041F7671C418947344531ED418B47304401E84903074889C24831C08A0241F7672C498B57104801C2448B0A4831C048C7C00300000041F7E541034734490347084989C041837F2C02755A4831D2664489CA6683E21F66C1E2034188573A4831D2664489CA6681E2E00366C1EA0566C1E203418857394831D2664489CA6681E2007C66C1EA0A66C1E2034188573831C0410A4738C1E008410A4739C1E008410A473A4189C145890841FFC5453B6F200F8657FFFFFF41FFC6453B77240F862DFFFFFF5D5B5E5FC20800") Local $tBinASM8cm_x64 = _DLLStructCreate64("ubyte asm[" & BinaryLen($bBinASM8cm_x64) & "]") $tBinASM8cm_x64.asm = $bBinASM8cm_x64 DllCallAddress("none", DllStructGetPtr($tBinASM8cm_x64), "ptr", DllStructGetPtr($tParam2)) EndSwitch Else ;convert it 1:1 directly Switch @AutoItX64 Case False $tParam.strideSrc = $iW $tParam.colorTblSize -= 2 Local Const $bBinASM8_x86 = Binary("0x8B7C2404BB00000000B900000000909089C8F7670889471C89C8F7670C8947208B471C01D8034718030789C252B803000000F7E30347200347045A8B328930433B5F1076DB31DB413B4F1476C3C20400") Local $tBinASM8_x86 = DllStructCreate("ubyte asm[" & BinaryLen($bBinASM8_x86) & "]") $tBinASM8_x86.asm = $bBinASM8_x86 DllCallAddress("none", DllStructGetPtr($tBinASM8_x86), "ptr", DllStructGetPtr($tParam)) Case Else $tParam.strideSrc = $iW Local Const $bBinASM8_x64 = Binary("0x575653554989CF49836F2002BB00000000B9000000009090909090909090909089C841F767104989C289C841F767144989C34D89D04901D84D0347204D030748C7C00300000048F7E34C01D8490347084D8B08448908FFC3413B5F1876D44831DBFFC1413B4F1C76B75D5B5E5FC20800") Local $tBinASM8_x64 = _DLLStructCreate64("ubyte asm[" & BinaryLen($bBinASM8_x64) & "]") $tBinASM8_x64.asm = $bBinASM8_x64 DllCallAddress("none", DllStructGetPtr($tBinASM8_x64), "ptr", DllStructGetPtr($tParam)) EndSwitch EndIf Case 15, 16, 24, 32 ;15/16/24/32-bit, as the bitmap format is the same we can use memcpy to copy the pixel data directly to the memory. ;Exeptions are 15/16/24-bit images whose width is not a divider of 4! If BitOR($iPxDepth = 15, $iPxDepth = 16, $iPxDepth = 24) And Mod($iW, 4) Then ConsoleWrite("Using Assembler code to speed-up..." & @CRLF) Switch $iPxDepth Case 15, 16 $tParam.strideSrc = $iW * 2 Switch @AutoItX64 Case False Local Const $bBinASM1516_x86 = Binary("0x8B7C2404BB00000000B900000000909089C8F7670889471C89C8F7670C894720B802000000F7E35003471C034718030789C2580347200347048B32668930433B5F1076DC31DB413B4F1476C4C20400") Local $tBinASM1516_x86 = DllStructCreate("ubyte asm[" & BinaryLen($bBinASM1516_x86) & "]") $tBinASM1516_x86.asm = $bBinASM1516_x86 DllCallAddress("none", DllStructGetPtr($tBinASM1516_x86), "ptr", DllStructGetPtr($tParam)) Case Else Local Const $bBinASM1516_x64 = Binary("0x575653554989CFBB00000000B90000000090909090909090909090909090909089C841F767104989C189C841F767144989C25389D8D1E04C89D24801C2490357084D89C84901C04D0347204D0307498B00488902FFC3FFC3413B5F1876D55BFFC1413B4F1C76B95D5B5E5FC20800") Local $tBinASM1516_x64 = _DLLStructCreate64("ubyte asm[" & BinaryLen($bBinASM1516_x64) & "]") $tBinASM1516_x64.asm = $bBinASM1516_x64 DllCallAddress("none", DllStructGetPtr($tBinASM1516_x64), "ptr", DllStructGetPtr($tParam)) EndSwitch Case 24 $tParam.strideSrc = $iW * 3 Switch @AutoItX64 Case False Local Const $bBinASM24_x86 = Binary("0x8B7C2404BB00000000B900000000909089C8F7670889471C89C8F7670C894720B803000000F7E35003471C034718030789C2580347200347048B328930433B5F1076DD31DB413B4F1476C5C20400") Local $tBinASM24_x86 = DllStructCreate("ubyte asm[" & BinaryLen($bBinASM24_x86) & "]") $tBinASM24_x86.asm = $bBinASM24_x86 DllCallAddress("none", DllStructGetPtr($tBinASM24_x86), "ptr", DllStructGetPtr($tParam)) Case Else Local Const $bBinASM24_x64 = Binary("0x575653554989CF4831C990909090909089C841F767104989C189C841F767144989C24831DB48C7C00300000048F7E34C89D24801C2490357084D89C84901C04D0347204D0307498B00488902FFC3FFC3413B5F1876CFFFC1413B4F1C76B25D5B5E5FC20800") Local $tBinASM24_x64 = _DLLStructCreate64("ubyte asm[" & BinaryLen($bBinASM24_x64) & "]") $tBinASM24_x64.asm = $bBinASM24_x64 DllCallAddress("none", DllStructGetPtr($tBinASM24_x64), "ptr", DllStructGetPtr($tParam)) EndSwitch EndSwitch Else For $y = 0 To $iH - 1 $t1 = $y * $stride DllCall($hDLL, "ptr:cdecl", "memcpy", "ptr", DllStructGetPtr($tDestBmp) + $t1, "ptr", DllStructGetPtr($tSrcBmp) + $t1, "uint", $stride) Next EndIf EndSwitch ConsoleWrite(TimerDiff($fTimer) & " ms" & @CRLF) DllClose($hDLL) ;TGA image is stored bottom up in file. Need to flip it. If BitAND($tTGAHeader.imageDescriptor, 0x30) <> 0x20 Then _GDIPlus_ImageRotateFlip($hBitmap, $GDIP_Rotate180FlipX) $tSrcBmp = 0 Return $hBitmap EndFunc ;==>_GDIPlus_TGAImageLoadFromFile ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name ..........: RemoveNullChars ; Description ...: Converts a null terminated binary string to a string ; Author ........: UEZ ; =============================================================================================================================== Func RemoveNullChars($bin) Local $a = StringRegExp($bin, "[[:xdigit:]+]{2}", 3), $s, $i If @error Then Return $s For $i = 0 To UBound($a) - 1 If $a[$i] = "00" Then ExitLoop $s &= Chr(Dec($a[$i])) Next Return $s EndFunc ;==>RemoveNullChars ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name ..........: _DLLStructCreate64 ; Description ...: Creates a struct for x64 assembler code execution ; Author ........: AndyG ; =============================================================================================================================== Func _DLLStructCreate64($struct) ;align auf 16-byte Adresse Local $temp = DllStructCreate($struct) Local $tempsize = DllStructGetSize($temp) + 64 Local $ptr = DllStructGetPtr($struct) Local $a1 = Mod(Number($ptr), 64) Local $temp = 0 Local $mem = _MemVirtualAlloc($ptr + $a1, $tempsize, $MEM_COMMIT, $PAGE_EXECUTE_READWRITE) Local $mem_dllstructcreate64_internal = $mem Local $a2 = Mod(Number($mem), 64) ;rest div 16 adresse = offset Local $sstruct = DllStructCreate($struct, (Number($mem) - $a2 + 64)) Return $sstruct ;auf 16 alingned pointer EndFunc ;==>_DLLStructCreate64 Global $sFile = FileOpenDialog("Select a TGA file", "", "TGA image(*.tga)") If @error Then Exit _GDIPlus_Startup() Global $hImage = _GDIPlus_TGAImageLoadFromFile($sFile, True) If @error Then ConsoleWrite(@error & " / " & @extended & @CRLF) _GDIPlus_Shutdown() Exit EndIf ;save result ;~ _GDIPlus_ImageSaveToFile($hImage, @ScriptDir & "\Converted.png") ;~ ShellExecute(@ScriptDir & "\Converted.png") Global $iW = _GDIPlus_ImageGetWidth($hImage), $iH = _GDIPlus_ImageGetHeight($hImage) Global $hGui = GUICreate("TGA Image Loader by UEZ", $iW, $iH) GUISetState() Global $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGui) _GDIPlus_GraphicsDrawImageRect($hGraphics, $hImage, 0, 0, $iW, $iH) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE _GDIPlus_BitmapDispose($hImage) _GDIPlus_GraphicsDispose($hGraphics) _GDIPlus_Shutdown() Exit Case $GUI_EVENT_RESTORE _GDIPlus_GraphicsDrawImageRect($hGraphics, $hImage, 0, 0, $iW, $iH) EndSwitch WEnd  
      Here my rookie assembler code ^^:
      #cs _ASM8cm_x86 use32 define tSrcBmp dword[edi] define tDestBmp dword[edi + 04] define colortable dword[edi + 08] define strideSrc dword[edi + 12] define strideDest dword[edi + 16] define w dword[edi + 20] define h dword[edi + 24] define colorTblSize dword[edi + 28] define colorwidth dword[edi + 32] define iOffset dword[edi + 36] define iOffset2 dword[edi + 40] define r5 byte[edi + 44] define g5 byte[edi + 45] define b5 byte[edi + 46] pushad ;~ _ASMDBG_() mov edi, dword[esp + 36] ;pointer to the struct xor ecx, ecx; y = 0 align 16 _y: mov eax, ecx mul strideSrc add eax, colorTblSize mov iOffset, eax ;iOffset = y * $strideSrc + $colorTblSize mov eax, ecx mul strideDest mov iOffset2, eax ;iOffset2 = y * $strideDest xor ebx, ebx ;x = 0 _x: mov eax, iOffset add eax, ebx ;iOffset + x add eax, tSrcBmp mov edx, eax ;edx = iOffset + x + tSrcBmp xor eax, eax mov al, byte[edx] ;get index from color table mul colorwidth ;multiply it with colorwidth -> eax = index of the color table mov edx, colortable add edx, eax mov esi, dword[edx] ;get the color from the color table mov eax, 3 mul ebx ; add eax, iOffset2 ; add eax, tDestBmp ;$x * 3 + iOffset2 + tDestBmp = t1 mov ebp, eax cmp colorwidth, 2 jne _col_rgb mov dx, si ;BitShift(BitAND($col, 0x001F), -3) ;B and dx, 0x001F shl dx, 3 mov b5, dl mov dx, si ;BitShift(BitShift(BitAND($col, 0x03E0), 5), -3) ;G and dx, 0x03E0 shr dx, 5 shl dx, 3 mov g5, dl mov dx, si ;BitShift(BitShift(BitAND($col, 0x7C00), 10), -3) ;R and dx, 0x7C00 shr dx, 10 shl dx, 3 mov r5, dl xor eax, eax ;eax = 0 or al, r5 ;generate rgb value from rgb555 shl eax, 8 or al, g5 shl eax, 8 or al, b5 mov esi, eax _col_rgb: mov dword[ebp], esi ;write to destination inc ebx cmp ebx, w jbe _x inc ecx cmp ecx, h jbe _y ;~ _ASMDBG_() popad ret ;4 #ce _ASM8cm_x86 #cs _ASM8cm_x64 use64 define tSrcBmp qword[r15] define tDestBmp qword[r15 + 08] define colortable qword[r15 + 16] define strideSrc dword[r15 + 24] define strideDest dword[r15 + 28] define w dword[r15 + 32] define h dword[r15 + 36] define colorTblSize dword[r15 + 40] define colorwidth dword[r15 + 44] define iOffset dword[r15 + 48] define iOffset2 dword[r15 + 52] define r5 byte[r15 + 56] define g5 byte[r15 + 57] define b5 byte[r15 + 58] define x r13d define y r14d push rdi push rsi push rbx push rbp mov qword r15, rcx mov y, 0 align 16 _y: mov eax, y mul strideSrc add eax, colorTblSize mov iOffset, eax ;iOffset = y * $strideSrc + $colorTblSize mov eax, y mul strideDest mov iOffset2, eax ;iOffset2 = y * $strideDest xor x, x ;x = 0 _x: mov eax, iOffset add eax, x ;iOffset + x add rax, tSrcBmp mov rdx, rax ;edx = iOffset + x + tSrcBmp xor rax, rax mov al, byte[rdx] ;get index from color table mul colorwidth ;multiply it with colorwidth -> eax = index of the color table mov rdx, colortable add rdx, rax mov r9d, dword[rdx] ;get the color from the color table xor rax, rax mov rax, 3 mul x ; add eax, iOffset2 ; add rax, tDestBmp ;$x * 3 + iOffset2 + tDestBmp = t1 mov r8, rax cmp colorwidth, 2 jne _col_rgb xor rdx, rdx mov dx, r9w ;BitShift(BitAND($col, 0x001F), -3) ;B and dx, 0x001F shl dx, 3 mov b5, dl xor rdx, rdx mov dx, r9w ;BitShift(BitShift(BitAND($col, 0x03E0), 5), -3) ;G and dx, 0x03E0 shr dx, 5 shl dx, 3 mov g5, dl xor rdx, rdx mov dx, r9w ;BitShift(BitShift(BitAND($col, 0x7C00), 10), -3) ;R and dx, 0x7C00 shr dx, 10 shl dx, 3 mov r5, dl xor eax, eax ;eax = 0 or al, r5 ;generate rgb value from rgb555 shl eax, 8 or al, g5 shl eax, 8 or al, b5 mov r9d, eax _col_rgb: mov dword[r8], r9d ;write to destination inc x cmp x, w jbe _x inc y cmp y, h jbe _y pop rbp pop rbx pop rsi pop rdi ret 8 #ce #cs _ASM8_x86 use32 pushad mov edi, dword[esp + 36] ;pointer to the struct define tSrcBmp dword[edi] define tDestBmp dword[edi + 04] define strideSrc dword[edi + 08] define strideDest dword[edi + 12] define w dword[edi + 16] define h dword[edi + 20] define colorTblSize dword[edi + 24] define iOffset dword[edi + 28] define iOffset2 dword[edi + 32] mov ecx, 0 ; y align 16 _y: mov eax, ecx mul strideSrc add eax, colorTblSize mov iOffset, eax ;iOffset = y * $strideSrc + $colorTblSize mov eax, ecx mul strideDest mov iOffset2, eax ;iOffset2 = y * $strideDest xor ebx, ebx ;x = 0 _x: mov ebp, iOffset sub ebp, 2 add ebp, ebx add ebp, tSrcBmp ;ebp = t1 mov eax, 3 mul ebx add eax, iOffset2 add eax, tDestBmp ;eax = t2 mov esi, dword[ebp] ;get the color from source bitmap mov dword[eax], esi ;write to destination inc ebx cmp ebx, w jbe _x inc ecx cmp ecx, h jbe _y popad ret ;4 #ce _ASM8_x86 #cs _ASM8_x64 use64 push rdi push rsi push rbx push rbp define tSrcBmp qword[r15] define tDestBmp qword[r15 + 08] define strideSrc [r15 + 16] define strideDest [r15 + 20] define w [r15 + 24] define h [r15 + 28] define colorTblSize [r15 + 32] define iOffset [r15 + 36] define iOffset2 [r15 + 40] mov qword r15, rcx sub qword colorTblSize, 2 mov ebx, 0 ;w - 1 mov ecx, 0 ;h - 1 align 16 _y: mov eax, ecx mul dword strideSrc mov r10, rax ;r10 = y * $strideSrc mov eax, ecx mul dword strideDest mov r11, rax ;r11 = y * $strideDest _x: mov r8, r10 add r8, rbx add r8, colorTblSize add r8, tSrcBmp ;r8 = t1 mov rax, 3 mul rbx add rax, r11 add rax, tDestBmp ;eax = t2 mov r9, [r8] ;get the color from source bitmap mov dword[rax], r9d ;write to destination inc ebx cmp ebx, w jbe _x xor rbx, rbx inc ecx cmp ecx, h jbe _y pop rbp pop rbx pop rsi pop rdi ret 8 #ce _ASM8_x64 #cs _ASM1516_x86 use32 mov edi, dword[esp + 4] ;pointer to the struct define tSrcBmp ptr[edi] define tDestBmp ptr[edi + 04] define strideSrc dword[edi + 08] define strideDest dword[edi + 12] define w dword[edi + 16] define h dword[edi + 20] define colorTblSize dword[edi + 24] define iOffset dword[edi + 28] define iOffset2 dword[edi + 32] mov ebx, 0 ; x mov ecx, 0 ; y align 16 _y: mov eax, ecx mul strideSrc mov iOffset, eax ;iOffset = y * $strideSrc mov eax, ecx mul strideDest mov iOffset2, eax ;iOffset2 = y * $strideDest _x: mov eax, 2 mul ebx ;x * 2 push eax add eax, iOffset add eax, colorTblSize add eax, tSrcBmp mov edx, eax ;edx = t1 pop eax ;restore x * 2 add eax, iOffset2 add eax, tDestBmp ;eax = t2 mov esi, dword[edx] ;get the color from source bitmap mov word[eax], si ;write to destination inc ebx cmp ebx, w jbe _x xor ebx, ebx inc ecx cmp ecx, h jbe _y ret ;4 #ce _ASM1516_x86 #cs _ASM1516_x64 use64 ;~ define tSrcBmp dword[r15 + 0] ;~ define tDestBmp dword[r15 + 8] ;~ define strideS dword[r15 + 16] ;~ define strideD dword[r15 + 20] ;~ define width dword[r15 + 24] ;~ define height dword[r15 + 28] ;~ define colorTblSize dword[r15 + 32] ;~ define t1 dword[r15 + 36] ;not needed ;~ define t2 dword[r15 + 40] ;not needed push rdi push rsi push rbx push rbp mov qword r15, rcx mov ebx, 0 ;dword[r15 + 24] ;ebx = w - 1 mov ecx, 0 ;dword[r15 + 28] ;ecx = h - 1 align 16 _y: mov eax, ecx mul dword[r15 + 16] mov r9, rax mov eax, ecx mul dword[r15 + 20] mov r10, rax push rbx _x: mov eax, ebx shl eax, 1 mov rdx, r10 add rdx, rax add rdx, [r15 + 8] mov r8, r9 add r8, rax add r8, [r15 + 32] add r8, [r15] mov rax, [r8] mov [rdx], rax inc ebx inc ebx cmp ebx, dword[r15 + 24] jbe _x pop rbx inc ecx cmp ecx, dword[r15 + 28] jbe _y pop rbp pop rbx pop rsi pop rdi ret 8 #ce _ASM1516_x64 #cs _ASM24_x86 use32 mov edi, dword[esp + 4] ;pointer to the struct define tSrcBmp dword[edi] define tDestBmp dword[edi + 04] define strideSrc dword[edi + 08] define strideDest dword[edi + 12] define w dword[edi + 16] define h dword[edi + 20] define colorTblSize dword[edi + 24] define iOffset dword[edi + 28] define iOffset2 dword[edi + 32] mov ebx, 0 ; x mov ecx, 0 ; y align 16 _y: mov eax, ecx mul strideSrc mov iOffset, eax ;iOffset = y * $strideSrc mov eax, ecx mul strideDest mov iOffset2, eax ;iOffset2 = y * $strideDest _x: mov eax, 3 mul ebx ;x * 3 push eax add eax, iOffset add eax, colorTblSize add eax, tSrcBmp mov edx, eax ;edx = t1 pop eax ;restore x * 3 add eax, iOffset2 add eax, tDestBmp ;eax = t2 mov esi, dword[edx] ;get the color from source bitmap mov dword[eax], esi ;write to destination inc ebx cmp ebx, w jbe _x xor ebx, ebx inc ecx cmp ecx, h jbe _y ret ;4 #ce _ASM24_x86 #cs _ASM24_x64 use64 ;~ define tSrcBmp dword[r15 + 0] ;~ define tDestBmp dword[r15 + 8] ;~ define strideS dword[r15 + 16] ;~ define strideD dword[r15 + 20] ;~ define width dword[r15 + 24] ;~ define height dword[r15 + 28] ;~ define colorTblSize dword[r15 + 32] ;~ define t1 dword[r15 + 36] ;not needed ;~ define t2 dword[r15 + 40] ;not needed push rdi push rsi push rbx push rbp mov qword r15, rcx xor rcx, rcx align 16 _y: mov eax, ecx mul dword[r15 + 16] mov r9, rax mov eax, ecx mul dword[r15 + 20] mov r10, rax xor rbx, rbx _x: mov rax, 3 mul rbx mov rdx, r10 add rdx, rax add rdx, [r15 + 8] mov r8, r9 add r8, rax add r8, [r15 + 32] add r8, [r15] mov rax, [r8] mov [rdx], rax ;copy 64 bits inc ebx inc ebx cmp ebx, dword[r15 + 24] jbe _x inc ecx cmp ecx, dword[r15 + 28] jbe _y pop rbp pop rbx pop rsi pop rdi ret 8 #ce _ASM24_x64  
      If you find a TGA image which is in scope of this script but doesn't convert it properly, please report it here.
      Thanks.
    • By Luigi
      A simple function to print a DllStruct on AutoIt.

       
      #include <StringConstants.au3> #include <Array.au3> Func DllStructPrint($str, $tag) Local $ret = "" If IsDllStruct($str) Then $tag = StringLower($tag) Local $arr1, $arr2 $arr1 = StringSplit($tag, ";", $STR_NOCOUNT) Local $aLabel[1] For $ii = 0 To UBound($arr1, 1) - 1 If Not ($arr1[$ii] = "struct") And Not ($arr1[$ii] = "endstruct") Then $arr2 = StringSplit($arr1[$ii], " ", $STR_NOCOUNT) If IsArray($arr2) Then _ArrayAdd($aLabel, $arr2[1]) EndIf Next For $ii = 1 To UBound($aLabel, 1) - 1 $ret &= $aLabel[$ii] & "=" & DllStructGetData($str, $aLabel[$ii]) Next ElseIf IsArray($str) Then $ret &= "[" & @LF Local $iSize = UBound($str, 1) - 1 For $ii = 0 To $iSize $ret &= " " & DllStructPrint($str[$ii], $tag) & ($ii = $iSize ? "" : ",") & @LF Next $ret &= "]" & @LF EndIf Return $ret EndFunc ;==>DllStructPrint Local $tag = "Struct;byte key;EndStruct" Local $str1 = DllStructCreate($tag) $str1.key = Random(100, 999) Local $str2 = DllStructCreate($tag) $str2.key = Random(100, 999) Local $str3 = DllStructCreate($tag) $str3.key = Random(100, 999) Local $arr[2] $arr[0] = $str2 $arr[1] = $str3 Local $var1 = DllStructPrint($str1, $tag) ConsoleWrite($var1 & @LF) Local $var2 = DllStructPrint($arr, $tag) ConsoleWrite($var2 & @LF)  
      OUTPUT: key=189 [ key=155, key=62 ]  
    • By UEZ
      Since monoceres has released 
      I searched for a way to map the 2D image of the earth to a 3D sphere with rotation.
       
      Here the result (after 9 years of research ^^) as a non realistic physical animation:
       ==> 
       
      Due to the fact that AutoIt / GDI+ are not that fast I couldn't add a moon animation additionally.
       
      Thanks to one of Eukalyptus' code to pointing me to the right direction. U rock man. 
       
      Source code extract only - not working because of missing binary data (images):
      ;coded by UEZ build 2017-03-18 #pragma compile(x64, false) #pragma compile(Icon, "c:\Program Files (x86)\AutoIt3\Icons\au3.ico") #AutoIt3Wrapper_Run_Au3Stripper=y #Au3Stripper_Parameters=/so /pe /rm #AutoIt3Wrapper_Run_After=del /f /q "%scriptdir%\%scriptfile%_stripped.au3" #include <GDIPlus.au3> #include <GuiConstantsEx.au3> #include <WindowsConstants.au3> _GDIPlus_Startup() Global $hGUI, $iFPS = 0, $iShowFPS = 0, $bExit Global Const $iW = 800, $iW2 = ($iW - 100) / 2, $iH = 500, $fRad = ACos(-1) / 180, $sTitle = "GDI+ Rotating Earth v1.7 coded by UEZ 2017" AutoItSetOption("GUIOnEventMode", 1) GDIPlus_RotatingEarth() AutoItSetOption("GUIOnEventMode", 0) _GDIPlus_Shutdown() Func GDIPlus_RotatingEarth() $bExit = False $hGUI = GUICreate($sTitle, $iW, $iH) GUISetState(@SW_SHOW, $hGUI) ;create canvas elements Local Const $hDC = _WinAPI_GetDC($hGUI) Local Const $hHBitmap = _WinAPI_CreateCompatibleBitmap($hDC, $iW, $iH) Local Const $hDC_backbuffer = _WinAPI_CreateCompatibleDC($hDC) Local Const $DC_obj = _WinAPI_SelectObject($hDC_backbuffer, $hHBitmap) Local Const $hCanvas = _GDIPlus_GraphicsCreateFromHDC($hDC_backbuffer) _GDIPlus_GraphicsSetInterpolationMode($hCanvas, $GDIP_INTERPOLATIONMODE_NEARESTNEIGHBOR) _GDIPlus_GraphicsSetPixelOffsetMode($hCanvas, $GDIP_PIXELOFFSETMODE_HALF) Local Const $hBrush_Clr = _GDIPlus_BrushCreateSolid(0xFF000000), _ $hBrush_FPS = _GDIPlus_BrushCreateSolid(0xFFF0F0F0), _ $hFormat_FPS = _GDIPlus_StringFormatCreate(), _ $hFamily_FPS = _GDIPlus_FontFamilyCreate("Arial"), _ $hFont_FPS = _GDIPlus_FontCreate($hFamily_FPS, 8), _ $tLayout_FPS = _GDIPlus_RectFCreate(0, 0, 60, 16), _ $hImage_Earth = _GDIPlus_BitmapCreateFromMemory(_Earth()), _ $hImage_Galaxy = _GDIPlus_BitmapCreateFromMemory(_Galaxy()), _ $hImage_Clouds = _GDIPlus_BitmapCreateFromMemory(_Clouds()), _ $hImage_Moon = _GDIPlus_BitmapCreateFromMemory(_Moon()), _ $hImage_USSE = _GDIPlus_BitmapCreateFromMemory(_USSE()), _ $hMatrix = _GDIPlus_MatrixCreate(), $hMatrix2 = _GDIPlus_MatrixCreate(), _ $hPath = _GDIPlus_PathCreate(), $hPath2 = _GDIPlus_PathCreate(), _ $hPen = _GDIPlus_PenCreate(0xC0FFFFFF, 1) _GDIPlus_ImageRotateFlip($hImage_USSE, 4) Local $aDim = _GDIPlus_ImageGetDimension($hImage_Earth) Local $hGfx = _GDIPlus_ImageGetGraphicsContext($hImage_Earth) _GDIPlus_GraphicsDrawStringEx($hGfx, "Coded by UEZ 2017 ^^", $hFont_FPS, _GDIPlus_RectFCreate(0, $aDim[1] / 2 - 4, 120, 12), $hFormat_FPS, $hBrush_FPS) _GDIPlus_ImageDispose($hGfx) Local Const $hTexture_Earth = _GDIPlus_TextureCreate($hImage_Earth), $hTexture_Clouds = _GDIPlus_TextureCreate($hImage_Clouds) DllCall($__g_hGDIPDll, "int", "GdipTranslateTextureTransform", "ptr", $hTexture_Earth, "float", -200, "float", 0, "long", 0) DllCall($__g_hGDIPDll, "int", "GdipTranslateTextureTransform", "ptr", $hTexture_Clouds, "float", -100, "float", 0, "long", 0) Local $iDiameter = $aDim[0] < $aDim[1] ? $aDim[0] : $aDim[1], _ $fDiameter2 = $iDiameter / 2, _ $fDX = ($iW - $iDiameter) / 2, $fDY = ($iH - $iDiameter) / 2 _GDIPlus_PathAddEllipse($hPath, $fDX - 1, $fDY - 1, $iDiameter + 2, $iDiameter + 2) Local Const $hBrush = _GDIPlus_PathBrushCreateFromPath($hPath) _GDIPlus_PathBrushSetCenterColor($hBrush, 0x02000008) _GDIPlus_PathBrushSetCenterPoint($hBrush, $fDX + $fDiameter2 + 1, $fDY + $fDiameter2 + 1) _GDIPlus_PathBrushSetSurroundColor($hBrush, 0xF8000000) _GDIPlus_PathBrushSetGammaCorrection($hBrush, 1) _GDIPlus_PathBrushSetFocusScales($hBrush, 0.50, 0.50) _GDIPlus_PathAddEllipse($hPath2, -1, -1, 201, 201) Local Const $hBrush2 = _GDIPlus_PathBrushCreateFromPath($hPath2) _GDIPlus_PathBrushSetCenterColor($hBrush2, 0x0800000) _GDIPlus_PathBrushSetCenterPoint($hBrush2, 100, 100) _GDIPlus_PathBrushSetSurroundColor($hBrush2, 0xFF000000) _GDIPlus_PathBrushSetGammaCorrection($hBrush2, 1) _GDIPlus_PathBrushSetFocusScales($hBrush2, 0.50, 0.50) $hGfx = _GDIPlus_ImageGetGraphicsContext($hImage_Moon) _GDIPlus_GraphicsFillEllipse($hGfx, -1, -1, 201, 201, $hBrush2) _GDIPlus_ImageDispose($hGfx) $iFPS = 0 GUISetOnEvent($GUI_EVENT_CLOSE, "_Exit_About") AdlibRegister("CalcFPS", 1000) Local $fTimer1, $fTimer2, $fScale, $fTmp, $fX, $fSin, $fZ, $fS, $zz, $z = 90, $iStep = 4 ;the higher $iStep is the faster the animation but lower the quality. Local $fPosX, $fPosY, $fSize, $fSpeed, $aMeteor[4] = [0, 10 + Random() * ($iH - 20), 5 + Random() * 10, 5 + Random() * 10] $fPosX = $iW + 60 $fPosY = Random() * ($iH - 100) + 50 $fSize = 0.5 + Random() * 2 $fSpeed = Random() * 3 + 1 $fTimer1 = TimerInit() $fTimer2 = TimerInit() Do DllCall($__g_hGDIPDll, "int", "GdipDrawImageRect", "handle", $hCanvas, "handle", $hImage_Galaxy, "float", 0, "float", 0, _ "float", $iW, "float", $iH) DllCall($__g_hGDIPDll, "int", "GdipSetSmoothingMode", "handle", $hCanvas, "int", 4) If TimerDiff($fTimer1) > 10000 Then DllCall($__g_hGDIPDll, "int", "GdipDrawLine", "handle", $hCanvas, "handle", $hPen, "float", $aMeteor[0], "float", $aMeteor[1], _ "float", $aMeteor[0] + $aMeteor[2] * 3, "float", $aMeteor[1] + $aMeteor[3] * 3) $aMeteor[0] += $aMeteor[2] $aMeteor[1] += $aMeteor[3] If BitOR($aMeteor[0] > $iW, $aMeteor[1] > $iH, $aMeteor[0] < 0, $aMeteor[1] < 0) Then $aMeteor[0] = 0 $aMeteor[1] = Random() * ($iH * 0.75) $aMeteor[2] = 8 + Random() * 12 $aMeteor[3] = 7 + Random() * 10 $fTimer1 = TimerInit() EndIf EndIf If TimerDiff($fTimer2) > 30000 Then DllCall($__g_hGDIPDll, "int", "GdipDrawImageRect", "handle", $hCanvas, "handle", $hImage_USSE, "float", $fPosX, "float", $fPosY, _ "float", 50 * $fSize, "float", 12 * $fSize) $fPosX -= $fSpeed If $fPosX < -100 Then $fPosX = $iW + 30 $fPosY = Random() * ($iH - 100) + 50 $fSize = Random() * 2 $fSpeed = Random() * 3 + 1 $fTimer2 = TimerInit() EndIf EndIf $zz = $z * $fRad $fX = $iW2 - Cos($zz) * 345 $z -= 0.5 $fZ = Sin($zz) $fS = 100 - $fZ * 50 DllCall($__g_hGDIPDll, "int", "GdipSetSmoothingMode", "handle", $hCanvas, "int", 1) DllCall($__g_hGDIPDll, "int", "GdipTranslateTextureTransform", "ptr", $hTexture_Earth, "float", 0.75, "float", 0, "long", 0) DllCall($__g_hGDIPDll, "int", "GdipTranslateTextureTransform", "ptr", $hTexture_Clouds, "float", 1.25, "float", 0, "long", 0) If $fZ > 0 Then _GDIPlus_GraphicsDrawImageRect($hCanvas, $hImage_Moon, $fX, 110, $fS, $fS) For $i = 1 To $fDiameter2 Step $iStep $fScale = 1 + $i / $fDiameter2 DllCall($__g_hGDIPDll, "int", "GdipSetMatrixElements", "handle", $hMatrix, "float", 1.0, "float", 0.0, "float", 0.0, "float", 1.0, "float", 0.0, "float", 0.0) DllCall($__g_hGDIPDll, "int", "GdipTranslateMatrix", "handle", $hMatrix, "float", $fDX + $fDiameter2, "float", $fDY + $fDiameter2, "int", 0) DllCall($__g_hGDIPDll, "int", "GdipScaleMatrix", "handle", $hMatrix, "float", $fScale, "float", $fScale, "int", 0) DllCall($__g_hGDIPDll, "int", "GdipTranslateMatrix", "handle", $hMatrix, "float", -$fDiameter2, "float", -$fDiameter2, "int", 0) DllCall($__g_hGDIPDll, "int", "GdipSetWorldTransform", "handle", $hCanvas, "handle", $hMatrix) DllCall($__g_hGDIPDll, "int", "GdipFillEllipse", "handle", $hCanvas, "handle", $hTexture_Earth, _ "float", $i, "float", $i, "float", $iDiameter -2 * $i, "float", $iDiameter - 2 * $i) DllCall($__g_hGDIPDll, "int", "GdipFillEllipse", "handle", $hCanvas, "handle", $hTexture_Clouds, _ "float", $i, "float", $i, "float", $iDiameter -2 * $i, "float", $iDiameter - 2 * $i) Next _GDIPlus_MatrixSetElements($hMatrix) _GDIPlus_GraphicsSetTransform($hCanvas, $hMatrix) DllCall($__g_hGDIPDll, "int", "GdipFillRectangle", "handle", $hCanvas, "handle", $hBrush, "float", $fDX, "float", $fDY, "float", $iDiameter, "float", $iDiameter) Else For $i = 1 To $fDiameter2 Step $iStep $fScale = 1 + $i / $fDiameter2 DllCall($__g_hGDIPDll, "int", "GdipSetMatrixElements", "handle", $hMatrix, "float", 1.0, "float", 0.0, "float", 0.0, "float", 1.0, "float", 0.0, "float", 0.0) DllCall($__g_hGDIPDll, "int", "GdipTranslateMatrix", "handle", $hMatrix, "float", $fDX + $fDiameter2, "float", $fDY + $fDiameter2, "int", 0) DllCall($__g_hGDIPDll, "int", "GdipScaleMatrix", "handle", $hMatrix, "float", $fScale, "float", $fScale, "int", 0) DllCall($__g_hGDIPDll, "int", "GdipTranslateMatrix", "handle", $hMatrix, "float", -$fDiameter2, "float", -$fDiameter2, "int", 0) DllCall($__g_hGDIPDll, "int", "GdipSetWorldTransform", "handle", $hCanvas, "handle", $hMatrix) DllCall($__g_hGDIPDll, "int", "GdipFillEllipse", "handle", $hCanvas, "handle", $hTexture_Earth, _ "float", $i, "float", $i, "float", $iDiameter - 2 * $i, "float", $iDiameter - 2 * $i) DllCall($__g_hGDIPDll, "int", "GdipFillEllipse", "handle", $hCanvas, "handle", $hTexture_Clouds, _ "float", $i, "float", $i, "float", $iDiameter - 2 * $i, "float", $iDiameter - 2 * $i) Next _GDIPlus_MatrixSetElements($hMatrix) _GDIPlus_GraphicsSetTransform($hCanvas, $hMatrix) DllCall($__g_hGDIPDll, "int", "GdipFillRectangle", "handle", $hCanvas, "handle", $hBrush, "float", $fDX, "float", $fDY, "float", $iDiameter, "float", $iDiameter) _GDIPlus_GraphicsDrawImageRect($hCanvas, $hImage_Moon, $fX, 110, $fS, $fS) EndIf _GDIPlus_GraphicsDrawStringEx($hCanvas, "FPS: " & $iShowFPS, $hFont_FPS, $tLayout_FPS, $hFormat_FPS, $hBrush_FPS) ;draw background message text _WinAPI_BitBlt($hDC, 0, 0, $iW, $iH, $hDC_backbuffer, 0, 0, $SRCCOPY) ;blit drawn bitmap to GUI $iFPS += 1 If $bExit Then ExitLoop Until False ;Not Sleep(10) AdlibUnRegister("CalcFPS") ;release resources _GDIPlus_PenDispose($hPen) _GDIPlus_BrushDispose($hBrush) _GDIPlus_BrushDispose($hBrush2) _GDIPlus_PathDispose($hPath) _GDIPlus_PathDispose($hPath2) _GDIPlus_MatrixDispose($hMatrix) _GDIPlus_MatrixDispose($hMatrix2) _GDIPlus_ImageDispose($hImage_Earth) _GDIPlus_ImageDispose($hImage_Galaxy) _GDIPlus_ImageDispose($hImage_Clouds) _GDIPlus_ImageDispose($hImage_Moon) _GDIPlus_ImageDispose($hImage_USSE) _GDIPlus_BrushDispose($hTexture_Earth) _GDIPlus_BrushDispose($hTexture_Clouds) _GDIPlus_FontDispose($hFont_FPS) _GDIPlus_FontFamilyDispose($hFamily_FPS) _GDIPlus_StringFormatDispose($hFormat_FPS) _GDIPlus_BrushDispose($hBrush_Clr) _GDIPlus_BrushDispose($hBrush_FPS) _GDIPlus_GraphicsDispose($hCanvas) _WinAPI_SelectObject($hDC_backbuffer, $DC_obj) _WinAPI_DeleteDC($hDC_backbuffer) _WinAPI_DeleteObject($hHBitmap) _WinAPI_ReleaseDC($hGUI, $hDC) GUIDelete($hGUI) EndFunc ;==>GDIPlus_RotatingEarth Func _Exit_About() $bExit = True EndFunc ;==>_Exit_About Func CalcFPS() ;display FPS $iShowFPS = $iFPS $iFPS = 0 EndFunc ;==>CalcFPS ;Code below was generated by: 'File to Base64 String' Code Generator v1.20 Build 2016-12-01 ...  
      Download: Rotating Earth v1.7.au3
      In line 92 you can modify the $iStep variable -> the higher $iStep is the faster the animation & lower the quality.
       
      So long...
    • By UEZ
      AutoIt Windows Screenshooter
      Key Features:
      takes easily a screenshot from any visible window capture any region of the desktop incl. freehand capturing capture GUI controls and GUI menus separately capture a marked area every x seconds for a duration of y seconds create a GIF animation from saved frames (Vista or higher os required) capture to AVI file (without audio!) takes a screenshot from web sites (available only on Win7+ os and when Aero is enabled) put images to clipboard to paste to other applications easily color picker save image in different formats and also to PDF! add timestamp to saved images simple image editing options: greyscale, b&w, invert, rotate +-90° send image to printer and default email client preview of captured screens incl. zoom option multi monitor support display pixel color under mouse ruler basic image editor (paint, highlight, ellipse, rectangle, text and some graphic FX) watermark captured image no 3rd party tools or DLLs used - pure AutoIt! fully portable - no installation is needed multi language feature (Eng, Ger, Tur, Fra and Rus only) drag'n'drop an image to the app for editing To do:
      capture content of scrollable window/control capture cascaded menus Due to DllCall("User32.dll", "int", "PrintWindow", "hwnd", $hWnd, "handle", $hMemDC, "int", 0) limitation some windows cannot be captured properly (GDI+, ProgDVB, etc.) but can take screenshots of hidden windows. One workaround is to use full screen capturing (F11/F12) or "Grab Screen" function! Or try double click with rmb on listview items (beta).
      Download source code (9460 downloads previously): AutoIt Windows Screenshooter v1.84 Build 2019-08-18.7z (version 3.3.12.0+ needed!)
      You are not allowed to sell this code or just parts of it in a commercial project or modify it and distribute it with a different name!
      Download compiled Exe only: 4shared / Media Fire  / Softpedia (1.58mb)
      Distributing copies of the program in compiled format (exe) must be free of any fee!
      -----> click here to Donate!  
      (Current donators: 1. Cuong N.) 
       
       
      It is designed for Win7+ operating systems with AERO enabled! E.g. on WinXP machines some functions are not working properly and might crash the application!
      AV scanners may have a negative impact the execution of compiled exe and might report any malware. I guarantee that there is no malicious code in the source code / exe!!! 
      Main GUI:

       
       
      About Intro:

       
       
      Basic Image Editor:

       
       
      Watermark:

       
       
      Click link for an enhanced version of Watermark Image.
      Credits:
      main code by UEZ additional code (alphabetical order) by Authenticity, AutoItObject Team, Eemuli, Eukalyptus, funkey, _Kurt, martin, monoceres, ProgAndy, taietel, trancexx, Ward, wolf9228 and Yashied! mesale0077 for turkish translation wakillon for french translation AZJIO for russian translation Keys:
      Main GUI:
      User your mouse to scroll preview window or
      Numpad 8: Scroll preview window up
      Numpad 2: Scroll preview window down
      Numpad 4: Scroll preview window left
      Numpad 6: Scroll preview window right
      Numpad +: zoom in preview window or mouse wheel down
      Numpad -: zoom out preview window or mouse wheel up
      F1: capture again on last position
      F5: refresh Windows Name list
      PRINTSCREEN: take screenshot from whole screen
      ALT+PRINTSCR: take a screenshot from active window
      F10: Undo made changes with Image Editing function
      F11: take screenshot from whole screen incl mouse cursor
      F12: take screenshot from whole screen
      Ctrl+Alt+F9 start "Grab Screen" mode
      Ctrl+Alt+F12: take a screenshot from active window using alternative screenshot functionality (beta)!
      Ctrl+r: call ruler
      Ctrl+s: save current displayed image
      Ctrl+x: exit program
      ctrl+w: call web grab input field (available only when Aero is enabled)
      Ctrl+i: call image editor
      Ctrl+m: call watermark editor
      Ctrl+z: undo
      Only available on Vista+ os: double click with rmb on list items to use alternative screenshot functionality (beta)!
      When 'Grab Screen' is clicked you can hold down the ctrl key to switch to 'grab controls' mode. Control under mouse will be framed red.
      ctrl + shift will take the screenshot of appropriate control. To capture GUI menus you can press rmb which simulates the lmb. When a menu is opened press shift additionally to capture it.
      Press and hold only the shift key to capture any region on the desktop using freehand capturing - release it so capture marked regions!
      Or just mark resize able area which you want to grab. Press CTRL key to grab marked area or right mouse button to capture the marked area every x seconds for a duration of y seconds.
      When saving the image just enter the extension you wish to use (*.jpg;*.png;*.bmp;*.gif;*.tif;*.pdf). Big thanks to taietel for his PDF UDF!
      Image Editor:
      s: save
      c: copy
      n: send
      h: highlighter
      p: pen
      r: rectangle
      e: ellipse
      a: arrow
      o: color
      t: text
      g: text config
      Ctrl+z: undo
      Watermark editor:
      Ctrl+z: undo
       
      To start the app minimized just call it "Windows Screenshooter.exe /min"
      Maybe it is useful for someone...
      Any kind of comment is welcome.
      Br,
      UEZ
      Change log:
       


×
×
  • Create New...