Jump to content
Bilgus

Scrolling Single Line Graph UDF

Recommended Posts

Posted (edited)

Waveform.thumb.png.b1d0a6168268c476c4eb32fc98c2cf7c.png

This is an update or derivative work of Beege 's Scrolling Line Graph UDF

https://www.autoitscript.com/forum/topic/109599-scrolling-line-graph-udf

 

I noticed a few issues for my use case with the UDF one being that adding a sample required updating the waveform

High CPU usage went hand in hand with that requirement

Another issue was just how long updating took to complete

I've hopefully rectified that with this version

 

There are a few changes (only 1 line per graph for instance)

  • The addition of a function AddSample (uses graphics paths to speed up drawing samples on update)
  • Gridlines are only generated once
  • A sample finished line can be added
  • UpdateGraph allows you to compress the discarded portion of the graph (it looks kinda cool but uses more CPU)
  • Lower Cpu usage
  • Uses real Control Ids - it is a label control underneath so you get click events and can display text when control is disabled

Example (Waveform.au3)

Spoiler

waveform.au3 

#include <GUIConstantsEx.au3> ; $GUI_DISABLE
#include "SSLG.au3"
#include <Array.au3>
;Just some timing variables
Global $iAvg = 0, $iAvg_Add = 0
Global $iCt = 0, $iCt_Add = 0
Global $iMax = 0, $iMin = 60000

;Setup
Global Const $Increments = 100
Global $UpdateIntervalMs = 100
Global $iSleep = 25
Global $bGenSamples = True

Opt('GuiOnEventMode', 1)
$GUI = GUICreate("GDI+ Scrolling Single Line Graph", 800, 500, -1, -1, BitOR($WS_SIZEBOX, $WS_SYSMENU, $WS_MINIMIZEBOX))
OnAutoItExitRegister(_Exit)
GUISetOnEvent(-3, _Exit)
GUISetState()

;_SSLG_CreateGraph($iLeft, $iTop, $iWidth, $iHeight, $iY_Min, $iY_Max, $iIncrements, $iBackGround = Default)
Global $Graph1 = _SSLG_CreateGraph(10, 10, -20, 300, 0, 100, $Increments)
GUICtrlSetData(-1, "Click me to enable" & @CRLF & "Resize the window to your liking" & @CRLF & "Click Again for a randomized experience")
GUICtrlSetOnEvent(-1, graph_)
GUICtrlSetState(-1, BitOR(GUICtrlGetState(-1), $GUI_DISABLE))
_SSLG_ClearGraph($Graph1) ;Create already cleared the graph

;Only needed for the example ==================================================
Global $Slider1 = GUICtrlCreateSlider(35, 350, 800 - 45, 40)
GUICtrlSetLimit(-1, 100, 1)
GUICtrlSetData(-1, $iSleep)
GUICtrlSetOnEvent(-1, slider_)
GUICtrlSetTip(-1, $iSleep)
UpdateSpeed($iSleep)

Global $Checkbox1 = GUICtrlCreateCheckbox("", 10, 350, 25, 25)
GUICtrlSetState(-1, $GUI_CHECKED)
GUICtrlSetOnEvent(-1, checkbox_)
;==============================================================================


GUIRegisterMsg($WM_EXITSIZEMOVE, WM_EXITSIZEMOVE)

;Wait for first activation
While BitAND(GUICtrlGetState($Graph1), $GUI_DISABLE) = $GUI_DISABLE
    Sleep(1000)
WEnd

AdlibRegister(Update, $UpdateIntervalMs)

Local $i = 0, $t
Local $y
While 1
    $t = TimerInit()

    If $bGenSamples Then
        ;_SSLG_AddSample($Graph1, $i)

        $y = Int(Sin($i / 30) * 40) + 45
        _SSLG_AddSample($Graph1, $y)

        _SSLG_AddSample($Graph1, Random($y / 2, $y * 2))

        For $j = 0 To Random(1, 10, 1)
            _SSLG_AddSample($Graph1, Random(0, 100))
        Next
    Else
        For $j = 0 To 5
            _SSLG_AddSample($Graph1)
        Next
    EndIf

    $iAvg_Add += TimerDiff($t)
    $iCt_Add += 1

    Sleep($iSleep)

    $i += Random(1, 15, 1)
    If $i > 179 Then $i = 0
WEnd


Func Update()
    Local $iErr, $iSamples
    Local $bCompress, $bFill

    Local $t = TimerInit()
    Static $i = 0
    $i = $i + 1

    If $i > 0 Then
        $bCompress = True
        $bFill = False
    Else
        $bCompress = False
        $bFill = True
    EndIf

    ;_SSLG_UpdateGraph($idSSLG, $bCompress = False, $bFill = False)
    If _SSLG_UpdateGraph($Graph1, $bCompress, $bFill) Then
        $iSamples = @extended
        Local $iT = TimerDiff($t)
        If $iT > $iMax Then $iMax = $iT
        If $iT < $iMin Then $iMin = $iT
        $iAvg += $iT
        $iCt += 1
        If $iCt >= 1000 Then Exit
    EndIf
    If $i > 100 Then $i = -100
EndFunc   ;==>Update

Func UpdateSpeed($iSleepMs)
    ;Try to keep update interval in sync with sample generation
    $UpdateIntervalMs = $iSleepMs * 10
    AdlibRegister(Update, $UpdateIntervalMs)
EndFunc   ;==>UpdateSpeed

;Callbacks ====================================================================
Func WM_EXITSIZEMOVE($hWnd, $Msg, $wParam, $lParam)
    _SSLG_SetResizeGraph($Graph1)
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_EXITSIZEMOVE

Func slider_()
    $iSleep = GUICtrlRead($Slider1)
    GUICtrlSetTip($Slider1, $iSleep)
    UpdateSpeed($iSleep)
EndFunc   ;==>slider_

Func checkbox_()
    $bGenSamples = (GUICtrlRead($Checkbox1) = $GUI_CHECKED)
EndFunc   ;==>checkbox_

Func graph_()
    ConsoleWrite("*Click*" & @CRLF)
    Local $iState = GUICtrlGetState($Graph1)
    If Not BitAND($iState, $GUI_DISABLE) Then
        Sleep(1000)
        GUICtrlSetData($Graph1, "Click me to enable")
        GUICtrlSetState($Graph1, BitOR($iState, $GUI_DISABLE))
        Return
    Else
        Local $iY_Min = Random(0, 1, 1)
        Local $iY_Max = ($iY_Min - 1) * -100
        $iY_Min *= 100
        _SSLG_SetYRange($Graph1, $iY_Min, $iY_Max)
        GUICtrlSetData($Graph1, "")
    EndIf
    Local $iGrid = Random(-5, 50, 1)
    If $iGrid < 0 Then $iGrid = 0
    GUICtrlSetState($Graph1, BitXOR($iState, $GUI_DISABLE))

    ;_SSLG_SetSetSampleIndicator($idSSLG, $iLineColor = False, $iPenSize = Default)
    If Random(0, 1, 1) = 0 Then
        _SSLG_SetSetSampleIndicator($Graph1, 0xffFF0000, 2)
    Else
        _SSLG_SetSetSampleIndicator($Graph1, False)
    EndIf

    ;_SSLG_SetGrid($idSSLG, $iX_c, $iY_c, $iGridColor = Default, $iPenSize = Default)
    _SSLG_SetGrid($Graph1, $iGrid, $iGrid / 2)

    Local $iColor = Random(0x0, 0xFF, 1) + Random(0x0, 0xFF, 1) * 256 + Random(0x0, 0xFF, 1) * 65536

    ;_SSLG_SetLine($idSSLG, $iLineColor, $iPenSize = Default, $iFillColor = Default)
    _SSLG_SetLine($Graph1, 0xFF00FF00, Random(1, 5, 1), $iColor)


    GUICtrlSetBkColor($Graph1, $iColor)
EndFunc   ;==>graph_

Func _Exit()
    AdlibUnRegister(Update)
    Local $sRes = StringFormat("Update: %dx Avg %0.2fMs\r\nMin %0.2fMs, Max %0.2fMs\r\n\r\nAdd: %dx Avg %0.2fMs\r\n", $iCt, ($iAvg / $iCt), $iMin, $iMax, $iCt_Add, ($iAvg_Add / $iCt_Add))
    ConsoleWrite($sRes)
    MsgBox(0, @ScriptName, $sRes)
    OnAutoItExitUnRegister(_Exit)
    Exit
EndFunc   ;==>_Exit

 

 

Example 2 (peak.au3)

Spoiler
#include <GuiConstants.au3>
#include "SSLG.au3"

Global $oAudioMeterInformation = _AudioVolObject()
If Not IsObj($oAudioMeterInformation) Then Exit -1 ; Will happen on non-supported systems

Opt('GuiOnEventMode', 1)
Global $GUI = GUICreate("GDI+ Scrolling Single Line Graph", 800, 500, -1, -1, BitOR($WS_SIZEBOX, $WS_SYSMENU, $WS_MINIMIZEBOX))
OnAutoItExitRegister(_Exit)
GUISetOnEvent(-3, _Exit)

;_SSLG_CreateGraph($iLeft, $iTop, $iWidth, $iHeight, $iY_Min, $iY_Max, $iIncrements, $iBackGround = Default)
Global $Graph1 = _SSLG_CreateGraph(10, 10, -20, 300, 0, 100, 600)
GUICtrlSetOnEvent(-1, graph_)

;_SSLG_SetGrid($idSSLG, $iX_c, $iY_c, $iGridColor = Default, $iPenSize = Default)
_SSLG_SetGrid($Graph1, 100, 10)
_SSLG_ClearGraph($Graph1) ;Create already cleared the graph but we want a grid

GUISetState()

AdlibRegister(_SamplePeak, 25)
AdlibRegister(_UpdateGraph, 300)
GUIRegisterMsg($WM_EXITSIZEMOVE, WM_EXITSIZEMOVE)

While 1
    Sleep(1000)
WEnd

Func _SamplePeak()
    Local Const $S_OK = 0
    Local $iPeak
    If $oAudioMeterInformation.GetPeakValue($iPeak) = $S_OK Then
        _SSLG_AddSample($Graph1, 100 * $iPeak)
    EndIf
EndFunc   ;==>_SamplePeak

Func _UpdateGraph()
    ;_SSLG_UpdateGraph($idSSLG, $bCompress = False, $bFill = False)
    _SSLG_UpdateGraph($Graph1, True, False)
EndFunc   ;==>_UpdateGraph

Func WM_EXITSIZEMOVE($hWnd, $Msg, $wParam, $lParam)
    _SSLG_SetResizeGraph($Graph1)
    Return $GUI_RUNDEFMSG
EndFunc   ;==>WM_EXITSIZEMOVE

Func graph_()
    ConsoleWrite("*Click*" & @CRLF)
EndFunc   ;==>graph_

Func _Exit()
    AdlibUnRegister(_SamplePeak)
    AdlibUnRegister(_UpdateGraph)
    OnAutoItExitUnRegister(_Exit)
    Exit
EndFunc   ;==>_Exit

;-------------------------------------------------------------------------------------------------------------------------------------
; https://www.autoitscript.com/forum/topic/142523-master-loudnessvolume-via-peak-meter-windows-7-64-bit/?tab=comments#comment-1003940
;-------------------------------------------------------------------------------------------------------------------------------------
Func _AudioVolObject()
    Local Const $sCLSID_MMDeviceEnumerator = "{BCDE0395-E52F-467C-8E3D-C4579291692E}"
    Local Const $sIID_IMMDeviceEnumerator = "{A95664D2-9614-4F35-A746-DE8DB63617E6}"
    Local Const $tagIMMDeviceEnumerator = "EnumAudioEndpoints hresult(dword;dword;ptr*);" & _
            "GetDefaultAudioEndpoint hresult(dword;dword;ptr*);" & _
            "GetDevice hresult(wstr;ptr*);" & _
            "RegisterEndpointNotificationCallback hresult(ptr);" & _
            "UnregisterEndpointNotificationCallback hresult(ptr);"
    ; Sequences of code below are taken from the source of plugin written for AutoIt for setting master volume on Vista and above systems.
    ; Code was written by wraithdu in C++.
    ; MMDeviceEnumerator
    Local $oMMDeviceEnumerator = ObjCreateInterface($sCLSID_MMDeviceEnumerator, $sIID_IMMDeviceEnumerator, $tagIMMDeviceEnumerator)
    If @error Then Return SetError(1, 0, 0)
    Local Const $eRender = 0
    Local Const $eConsole = 0
    ; DefaultAudioEndpoint
    Local $pDefaultDevice
    $oMMDeviceEnumerator.GetDefaultAudioEndpoint($eRender, $eConsole, $pDefaultDevice)
    If Not $pDefaultDevice Then Return SetError(2, 0, 0)
    ; Turn that pointer into object
    Local $oIMMDefaultDevice = ObjCreateInterface($pDefaultDevice, "{D666063F-1587-4E43-81F1-B948E807363F}", _
            "Activate hresult(clsid;dword;variant*;ptr*);")
    Local Const $CLSCTX_INPROC_SERVER = 0x1
    ; AudioMeterInformation
    Local $pAudioMeterInformation
    $oIMMDefaultDevice.Activate("{C02216F6-8C67-4B5B-9D00-D008E73E0064}", $CLSCTX_INPROC_SERVER, 0, $pAudioMeterInformation)
    If Not $pAudioMeterInformation Then Return SetError(3, 0, 0)
    Return ObjCreateInterface($pAudioMeterInformation, "{C02216F6-8C67-4B5B-9D00-D008E73E0064}", "GetPeakValue hresult(float*);")
EndFunc   ;==>_AudioVolObject
;-------------------------------------------------------------------------------------------------------------------------------------
; https://www.autoitscript.com/forum/topic/142523-master-loudnessvolume-via-peak-meter-windows-7-64-bit/?tab=comments#comment-1003940
;-------------------------------------------------------------------------------------------------------------------------------------

 

UDF

Spoiler

SSLG.au3

;
#Region Header
; #INDEX# =======================================================================================================================
; Title ............: SSLG
; AutoIt Version ...: 3.3.14.5
; Language .........: English
; Description ......: Functions to assist in creating and updating Scrolling Single Line Graphs
; Original Author(s): Beege ;http://www.autoitscript.com/forum/index.php?showtopic=109599
; Author(s) ........: Bilgus
; ===============================================================================================================================

; #CURRENT# =====================================================================================================================
;_SSLG_CreateGraph
;_SSLG_AddSample
;_SSLG_UpdateGraph
;_SSLG_SetSetSampleIndicator
;_SSLG_SetGrid
;_SSLG_SetLine
;_SSLG_SetSmoothingMode
;_SSLG_ClearGraph
;_SSLG_SetYRange
;_SSLG_SetBackGroundColor
; ===============================================================================================================================

#include-once
#include <GDIPlus.au3>
#include <WindowsConstants.au3>

_GDIPlus_Startup()
OnAutoItExitRegister(__SSLG_Exit)
#EndRegion Header

#Region Global Variables and Constants
Global Const $gSSLG_DICT = 1
Global Enum $gSSLG_idCtrl, $gSSLG_aRect, $gSSLG_hCtrl, $gSSLG_hPen, $gSSLG_hPenSamp, $gSSLG_hPenGrid, $gSSLG_hBrushLine, $gSSLG_hBrushBkgnd, _
        $gSSLG_hDCBuf, $gSSLG_hHBitmapGDI_, $gSSLG_hBitmap_1, $gSSLG_hGrBuf_1, $gSSLG_hBitmap_0, $gSSLG_hGrBuf_0, $gSSLG_hPathGridH, _
        $gSSLG_iY_Min, $gSSLG_iY_Max, $gSSLG_iY_Range, $gSSLG_iY_Last, $gSSLG_iX_Inc, $gSSLG_hPathLine, $gSSLG_hPathGridV, $gSSLG_hMatrixHT, _
        $gSSLG_bNeedResize, $gSSLG_iIncrements, $gSSLG_iIncrementSize, $gSSLG_iBackColor, $gSSLG_iSamples, $gSSLG_iSamplesTotal, $MAX

Global $g_SSLG[1][$MAX]

$g_SSLG[0][0] = 0
$g_SSLG[0][$gSSLG_DICT] = ObjCreate("Scripting.Dictionary")

#cs
    $g_SSLG[0][0]          = List Count
    [0][1]                  = Dictionary object (associative array)
    [0][2-27]               = Nothing

    [$i][$gSSLG_idCtrl]         = ControlID
    [$i][$gSSLG_aRect]          = Control position array [x, y, w, h]
    [$i][$gSSLG_hCtrl]          = Control Handle
    [$i][$gSSLG_hPen]           = Line Pen Handle
    [$i][$gSSLG_hPenSamp]       = Sample Finished Pen Handle
    [$i][$gSSLG_hPenGrid]       = Gridline Pen Handle
    [$i][$gSSLG_hBrushLine]     = Brush to fill under graph line
    [$i][$gSSLG_hBrushBkgnd]    = Brush for background ([$gSSLG_iBackColor])

    [$i][$gSSLG_hDCBuf]         = Device context Handle for buffer
    [$i][$gSSLG_hHBitmapGDI_]   = Standard GDI bitmap (selected into hDCBuf)
    [$i][$gSSLG_hBitmap_1]      = Buffer 1 Bitmap Object Handle
    [$i][$gSSLG_hGrBuf_1]       = Buffer 1 Graphic Object Handle
    [$i][$gSSLG_hBitmap_0]      = Buffer 0 Bitmap Object Handle
    [$i][$gSSLG_hGrBuf_0]       = Buffer 0 Graphic Object Handle

    [$i][$gSSLG_iY_Min]         = Y Min
    [$i][$gSSLG_iY_Max]         = Y Max
    [$i][$gSSLG_iY_Range]       = Y Range
    [$i][$gSSLG_iY_Last]        = Last Y Coordinate

    [$i][$gSSLG_iX_Inc]         = Vertical Gridline every #iX_Inc samples
    [$i][$gSSLG_hPathLine]      = Graphics Path Object Handle
    [$i][$gSSLG_hPathGridV]     = Graphics Path Object Handle Vertical Grid Lines
    [$i][$gSSLG_hPathGridH]     = Graphics Path Object Handle Horizontal Grid Lines
    [$i][$gSSLG_hMatrixHT]      = Graphics Path Horizontal Translation Matrice

    [$i][$gSSLG_bNeedResize]    = Resize graphics objects
    [$i][$gSSLG_iIncrements]    = Step Count
    [$i][$gSSLG_iIncrementSize] = Step Size
    [$i][$gSSLG_iBackColor]     = Background Color value
    [$i][$gSSLG_iSamples]       = Count of samples waiting to be drawn
    [$i][$gSSLG_iSamplesTotal]  = Count of total samples since ClearGraph()

#ce
#EndRegion Global Variables and Constants

#Region Public Functions
; #FUNCTION# ====================================================================================================================
; Name...........: _SSLG_CreateGraph
; Description ...: Creates a Scrolling Line Graph
; Syntax.........: _SSLG_CreateGraph($iLeft, $iTop, $iW, $iH, $iY_Min, $iY_Max, $iIncrements, $iBackGround = Default)

; Parameters ....:
;   $iLeft      - Left side of the graph
;   $iTop       - Top side of the graph
;   $iW             - Width of the graph
;   $iH             - Height of the graph
;   $iY_Min         - Minimum Y Value
;   $iY_Max         - Maximum Y Value
;   $iIncrements    - How many parts the Graph is divided up into.
;   $iBackGround    - BackGround Color. Alpha, Red, Green and Blue Hex Value. (0xAARRGGBB). Default = Black

; Return values .: Success  - ControlId
; Author ........: Beege, Bilgus
; Remarks .......: $iIncrements will be rounded if $iW is not evenly divisible
; ===============================================================================================================================
Func _SSLG_CreateGraph($iLeft, $iTop, $iW, $iH, $iY_Min, $iY_Max, $iIncrements, $iBackGround = Default)
    If $iBackGround = Default Then $iBackGround = 0xFF000000

    ReDim $g_SSLG[UBound($g_SSLG) + 1][UBound($g_SSLG, 2)]
    $g_SSLG[0][0] += 1
    Local $oDict = $g_SSLG[0][$gSSLG_DICT]
    Local $iIdx = $g_SSLG[0][0]
    Local $aResult, $aPos

    Local $iCtrlID = GUICtrlCreateLabel("", $iLeft, $iTop, $iW, $iH, $WS_CLIPSIBLINGS)
    Local $hCtrl = GUICtrlGetHandle($iCtrlID)

    If $iW < 0 Or $iH < 0 Then ;Allow -W/H
        $aResult = DllCall("user32.dll", "hwnd", "GetParent", "hwnd", $hCtrl)
        If Not @error Then
            $aPos = WinGetClientSize($aResult[0])
            If Not @error Then
                If $iW < 0 Then $iW = $aPos[0] + $iW
                If $iH < 0 Then $iH = $aPos[1] + $iH
                GUICtrlSetPos($iCtrlID, $iLeft, $iTop, $iW, $iH)
            EndIf
        EndIf
    EndIf

    $g_SSLG[$iIdx][$gSSLG_idCtrl] = $iCtrlID
    $g_SSLG[$iIdx][$gSSLG_hCtrl] = $hCtrl

    Local $hDC = _WinAPI_GetDC($hCtrl)
    $g_SSLG[$iIdx][$gSSLG_hDCBuf] = _WinAPI_CreateCompatibleDC($hDC)
    _WinAPI_ReleaseDC($hCtrl, $hDC)

    ;Store references
    $oDict.Add(Hex($iCtrlID), $iIdx)
    $oDict.Add(Hex($hCtrl), $iIdx)

    $g_SSLG[$iIdx][$gSSLG_iIncrements] = $iIncrements

    $g_SSLG[$iIdx][$gSSLG_hPathLine] = _GDIPlus_PathCreate() ;Create new path object
    $g_SSLG[$iIdx][$gSSLG_hPathGridV] = _GDIPlus_PathCreate() ;Create new path object
    $g_SSLG[$iIdx][$gSSLG_hPathGridH] = _GDIPlus_PathCreate() ;Create new path object
    $g_SSLG[$iIdx][$gSSLG_hMatrixHT] = _GDIPlus_MatrixCreate() ;Horizontal translation matrix

    ;Initially these are disabled; use _SetGrid & _SetSampleIndicator
    $g_SSLG[$iIdx][$gSSLG_hPenSamp] = False
    $g_SSLG[$iIdx][$gSSLG_hPenGrid] = False

    $g_SSLG[$iIdx][$gSSLG_iBackColor] = __SSLG_RGB_ARGB($iBackGround)
    $g_SSLG[$iIdx][$gSSLG_hBrushBkgnd] = _GDIPlus_BrushCreateSolid($g_SSLG[$iIdx][$gSSLG_iBackColor])
    GUICtrlSetBkColor(-1, BitAND(BitNOT(0xFF000000), $iBackGround))
    GUICtrlSetColor(-1, 0xFFFFFF)

    _SSLG_SetLine($iCtrlID, 0xFF00FF00, 2)

    $g_SSLG[$iIdx][$gSSLG_iY_Last] = False
    $g_SSLG[$iIdx][$gSSLG_iX_Inc] = 0

    $g_SSLG[$iIdx][$gSSLG_iSamples] = 0
    $g_SSLG[$iIdx][$gSSLG_iSamplesTotal] = 0

    _SSLG_SetYRange($iCtrlID, $iY_Min, $iY_Max)

    _SSLG_SetSmoothingMode($iCtrlID)

    $g_SSLG[$iIdx][$gSSLG_bNeedResize] = True
    _SSLG_ClearGraph($iCtrlID)

    Return $iCtrlID

EndFunc   ;==>_SSLG_CreateGraph

; #FUNCTION# ====================================================================================================================
; Name...........: _SSLG_AddSample
; Description ...: Adds a new value to Line Graph
; Syntax.........: _SSLG_AddSample($iIdx, $iValue)
; Parameters ....: $idSSLG - Control ID returned from _SSLG_CreateGraph()
;                  $iValue - Value to add to graph Default advances graph without a data point displayed
; Return values .: Success  - 1
;   Failure     - 0 and sets @ERROR:
;                               - 1 Invalid iIndex
;                               - 3 Too many samples ~truncated
;                               - 4 Busy in another SSLG function
; Author ........: Bilgus
; Remarks .......: Adding too many samples between calls to UpdateGraph will cause samples to be lost
; ===============================================================================================================================

Func _SSLG_AddSample($idSSLG, $iValue = Default)
    Local $iIdx = __SSLG_LookupHandle($idSSLG, True)
    If $iIdx > $g_SSLG[0][0] Then Return SetError(1, @extended, 0)

    Local $hPath = $g_SSLG[$iIdx][$gSSLG_hPathLine]
    Local $hPath_Grid = $g_SSLG[$iIdx][$gSSLG_hPathGridV]
    Local $aRect = $g_SSLG[$iIdx][$gSSLG_aRect]
    Local $iH = $aRect[3]
    
    Local $iY = $g_SSLG[$iIdx][$gSSLG_iY_Last]
    Local $iY_Last = $g_SSLG[$iIdx][$gSSLG_iY_Last]
    Local $iY_Min = $g_SSLG[$iIdx][$gSSLG_iY_Min]
    Local $iY_Max = $g_SSLG[$iIdx][$gSSLG_iY_Max]

    If $g_SSLG[$iIdx][$gSSLG_iY_Last] = Default And $iValue <> Default Then 
        Return SetError(4, @extended, 0)
    Else
        $g_SSLG[$iIdx][$gSSLG_iY_Last] = Default ;Used as Mutex
    EndIf

    If $g_SSLG[$iIdx][$gSSLG_iSamples] <= 0 Then ; First sample, reset paths
        _GDIPlus_PathReset($hPath)
        _GDIPlus_PathReset($g_SSLG[$iIdx][$gSSLG_hPathGridV])
    EndIf

    If $iValue <> Default Then
        If $iY_Min < $iY_Max Then
            $iY = $g_SSLG[$iIdx][$gSSLG_iY_Max] - $iValue ;Need to flip direction of Y
        Else
            $iY = $iValue
        EndIf
        If Not $iY_Last Then $iY_Last = $iY
        _GDIPlus_PathAddLine($hPath, $g_SSLG[$iIdx][$gSSLG_iSamples] - 1, $iY_Last, $g_SSLG[$iIdx][$gSSLG_iSamples], $iY)
        ;ConsoleWrite(StringFormat("AddLine (%d, %d) (%d, %d) \r\n", $g_SSLG[$iIdx][$gSSLG_iSamples] - 1, $iY_Last, $g_SSLG[$iIdx][$gSSLG_iSamples], $iY ))
    EndIf

    If $g_SSLG[$iIdx][$gSSLG_hPenGrid] And Mod($g_SSLG[$iIdx][$gSSLG_iSamplesTotal], $g_SSLG[$iIdx][$gSSLG_iX_Inc]) = 0 Then
        ;Make a new vertical grid line
        _GDIPlus_PathStartFigure($hPath_Grid)
        _GDIPlus_PathAddLine($hPath_Grid, $g_SSLG[$iIdx][$gSSLG_iSamples], $iY_Min, $g_SSLG[$iIdx][$gSSLG_iSamples], $iY_Max)
        _GDIPlus_PathCloseFigure($hPath_Grid)
    EndIf

    $g_SSLG[$iIdx][$gSSLG_iSamples] += 1
    $g_SSLG[$iIdx][$gSSLG_iSamplesTotal] += 1 ;Used to track gridline increment
    $g_SSLG[$iIdx][$gSSLG_iY_Last] = $iY ;Release Mutex

    If $g_SSLG[$iIdx][$gSSLG_iSamples] > $g_SSLG[$iIdx][$gSSLG_iIncrements] Then Return SetError(3, @extended, 0)

    Return 1

EndFunc   ;==>_SSLG_AddSample

; #FUNCTION# ====================================================================================================================
; Name...........: _SSLG_UpdateGraph
; Description ...: Updates Line Graph with new values
; Syntax.........: _SSLG_UpdateGraph($iIdx, $iValue)
; Parameters ....: $idSSLG - Control ID returned from _SSLG_CreateGraph()
;                  $bCompress - Compress end of graph rather than discard (slower)
;                  $bFill - Fill under the graph line with hBrushLine
;                  $bForce Update even though control is disabled
; Return values .: Success  - 1
;   @Extended   - Number of samples displayed
;   Failure     - 0 and sets @ERROR:
;                               - 1 Invalid iIndex
;                               - 2 No Samples
;                               - 3 Samples overflow graph
;                               - 4 Busy in another SSLG function
; Author ........: Bilgus
; Remarks .......: Flip Y_Min and Y_Max in the call to CreateGraph to change fill area from under to above
;                  $bCompress = True uses more CPU and increases memory churn due to GDI+ temp objects
; ===============================================================================================================================
Func _SSLG_UpdateGraph($idSSLG, $bCompress = False, $bFill = False, $bForce = False)
    Local $iIdx = __SSLG_LookupHandle($idSSLG, $bForce)
    If $iIdx > $g_SSLG[0][0] Then Return SetError(1, @extended, 0)
    Local $iErr = 0, $iY_Last

    If $g_SSLG[$iIdx][$gSSLG_bNeedResize] Then _SSLG_ClearGraph($idSSLG)

    Local $iSamples = $g_SSLG[$iIdx][$gSSLG_iSamples]

    If $iSamples < 1 Then
        Return SetError(2, @extended, 0)
    ElseIf $iSamples > $g_SSLG[$iIdx][$gSSLG_iIncrements] Then
        ;ConsoleWrite("!Full!" & @CRLF)
        $iSamples = $g_SSLG[$iIdx][$gSSLG_iIncrements]
        $iErr = 3
    EndIf

    If $g_SSLG[$iIdx][$gSSLG_iY_Last] = Default Then
        SetError(4, @extended, 0) ; Currently in the AddSample or GraphClear Function
    Else
        $iY_Last = $g_SSLG[$iIdx][$gSSLG_iY_Last]
        $g_SSLG[$iIdx][$gSSLG_iY_Last] = Default ;Used as Mutex
    EndIf

    $g_SSLG[$iIdx][$gSSLG_iSamples] = 0

    Local $hPath = $g_SSLG[$iIdx][$gSSLG_hPathLine]

    Local $hMatrixHT = $g_SSLG[$iIdx][$gSSLG_hMatrixHT]

    Local $aRect = $g_SSLG[$iIdx][$gSSLG_aRect]
    Local $iW = $aRect[2]
    Local $iH = $aRect[3]

    Local $iIncrement = $g_SSLG[$iIdx][$gSSLG_iIncrementSize]
    Local $iInc_Total = $iIncrement * $iSamples
    Local $iShiftDist = $iW - $iInc_Total
    ;ConsoleWrite(StringFormat("!Display (%d, %d; %d;) \r\n", $iSamples, $iInc_Total, $iShiftDist))

    Local $iHistX = $iInc_Total
    Local $iHistW = $iShiftDist
    If $bCompress Then
        $iHistX = 0
        $iHistW = $iW
    EndIf

    Local $aGraphic[2], $aBmp[2]
    Static Local $iLastBuf = 0
    ;Swap back buffer each call
    Local $iBuf0 = $iLastBuf, $iBuf1 = (1 - $iLastBuf) ;Toggles 0,1
    $aGraphic[$iBuf0] = $g_SSLG[$iIdx][$gSSLG_hGrBuf_0]
    $aGraphic[$iBuf1] = $g_SSLG[$iIdx][$gSSLG_hGrBuf_1]
    $aBmp[$iBuf0] = $g_SSLG[$iIdx][$gSSLG_hBitmap_0]
    $aBmp[$iBuf1] = $g_SSLG[$iIdx][$gSSLG_hBitmap_1]
    $iLastBuf = $iBuf1

    ;Shift/Copy/Compress the last data to the current bitmap
    _GDIPlus_GraphicsDrawImageRectRect($aGraphic[0], $aBmp[1], _
            $iHistX, 0, $iHistW, $iH, _ ;[Src XYWH]
            0, 0, $iShiftDist, $iH) ; [Dst XYWH]

    ;Here we scale the path(points) to the size of the graph X increment and Y range
    _GDIPlus_MatrixSetElements($hMatrixHT, $iIncrement, 0, 0, (($iH - 1) / $g_SSLG[$iIdx][$gSSLG_iY_Range]), $iShiftDist, 0)

    If $bFill And _GDIPlus_PathGetPointCount($hPath) > 0 Then
        ;Create 3 lines to enclose desired fill area -- If $iY_Min was used it'd fill top of graph instead
        Local $iY_F = $g_SSLG[$iIdx][$gSSLG_iY_Max]
        Static Local $tPoints = DllStructCreate("float[" & 3 * 2 & "]")
        DllStructSetData($tPoints, 1, $iSamples, 1)
        DllStructSetData($tPoints, 1, $iY_Last, 2)
        DllStructSetData($tPoints, 1, $iSamples, 3)
        DllStructSetData($tPoints, 1, $iY_F, 4)
        DllStructSetData($tPoints, 1, -1, 5)
        DllStructSetData($tPoints, 1, $iY_F, 6)
        DllCall($__g_hGDIPDll, "int", "GdipAddPathLine2", "handle", $hPath, "struct*", $tPoints, "int", 3)
        ;_GDIPlus_PathSetFillMode ($hPath, 0)

        _GDIPlus_MatrixSetElements($hMatrixHT, $iIncrement, 0, 0, (($iH - 1) / $g_SSLG[$iIdx][$gSSLG_iY_Range]), $iShiftDist, 0)
        _GDIPlus_PathTransform($hPath, $hMatrixHT)
        _GDIPlus_GraphicsFillPath($aGraphic[0], $hPath, $g_SSLG[$iIdx][$gSSLG_hBrushLine])
        _GDIPlus_GraphicsDrawPath($aGraphic[0], $hPath, $g_SSLG[$iIdx][$gSSLG_hPen])
    Else
        _GDIPlus_MatrixSetElements($hMatrixHT, $iIncrement, 0, 0, (($iH - 1) / $g_SSLG[$iIdx][$gSSLG_iY_Range]), $iShiftDist, 0)
        _GDIPlus_PathTransform($hPath, $hMatrixHT)
        _GDIPlus_GraphicsDrawPath($aGraphic[0], $hPath, $g_SSLG[$iIdx][$gSSLG_hPen])
    EndIf
    ;_GDIPlus_PathReset($hPath) (Now Handled in AddSample)

    If $g_SSLG[$iIdx][$gSSLG_hPenGrid] Then
        _GDIPlus_PathAddPath($g_SSLG[$iIdx][$gSSLG_hPathGridV], $g_SSLG[$iIdx][$gSSLG_hPathGridH], False)
        _GDIPlus_PathTransform($g_SSLG[$iIdx][$gSSLG_hPathGridV], $hMatrixHT)
        _GDIPlus_GraphicsDrawPath($aGraphic[0], $g_SSLG[$iIdx][$gSSLG_hPathGridV], $g_SSLG[$iIdx][$gSSLG_hPenGrid])
        ;_GDIPlus_PathReset($g_SSLG[$iIdx][$gSSLG_hPathGridV]) (Now Handled in AddSample)
    EndIf

    If $g_SSLG[$iIdx][$gSSLG_hPenSamp] Then ;Place a line at the end of each sample period
        _GDIPlus_GraphicsDrawLine($aGraphic[0], $iW - 1, 0, $iW - 1, $iH, $g_SSLG[$iIdx][$gSSLG_hPenSamp])
    EndIf

    __SSLG_GraphicsDraw($iIdx, $aBmp[0], $iW, $iH) ;Copy back to ctrl

    ;Clear Next Bitmap
    _GDIPlus_GraphicsFillRect($aGraphic[1], 0, 0, $iW, $iH, $g_SSLG[$iIdx][$gSSLG_hBrushBkgnd])

    $g_SSLG[$iIdx][$gSSLG_iY_Last] = $iY_Last ;Release mutex
    Return SetError($iErr, $iSamples, 1)

EndFunc   ;==>_SSLG_UpdateGraph

; #FUNCTION# ====================================================================================================================
; Name...........: _SSLG_SetSampleIndicator
; Description ...: Sets Line Color and line size of sample update line
; Syntax.........: _SSLG_SetSetSampleIndicator($iIdx, $iARGB, $iPenSize)
; Parameters ....: $idSSLG - Control ID returned from _SSLG_CreateGraph()
;                  $iLineColor - Alpha, Red, Green and Blue Hex Value. (0xAARRGGBB) [Default] = False Removes Indicator
;                  $iPenSize - Size of pen [Default] = 2
;                  $iPenStyle  - GDIP_DASHSTYLE [Default] = $GDIP_DASHSTYLESOLID
; Return values .: Success  - 1
;   Failure     - 0 and sets @ERROR:
;                               - 1 Invalid iIndex
;                               - 2 Error setting pen color
; Author ........: Bilgus
; Remarks .......: none
; ===============================================================================================================================
Func _SSLG_SetSetSampleIndicator($idSSLG, $iLineColor = False, $iPenSize = Default, $iPenStyle = Default)
    Local $iIdx = __SSLG_LookupHandle($idSSLG)
    If $iIdx > $g_SSLG[0][0] Then Return SetError(1, @extended, 0)

    If $iPenStyle = Default Then $iPenStyle = $GDIP_DASHSTYLESOLID

    If $iLineColor = False Then
        _GDIPlus_PenDispose($g_SSLG[$iIdx][$gSSLG_hPenSamp])
        $g_SSLG[$iIdx][$gSSLG_hPenSamp] = False
        Return 1
    EndIf

    If $iPenStyle = Default Then $iPenStyle = $GDIP_DASHSTYLEDOT

    $iLineColor = __SSLG_RGB_ARGB($iLineColor)
    If Not $g_SSLG[$iIdx][$gSSLG_hPenSamp] And $iPenSize = Default Then $iPenSize = 1

    If $iPenSize <> Default Then
        _GDIPlus_PenDispose($g_SSLG[$iIdx][$gSSLG_hPenSamp])
        $g_SSLG[$iIdx][$gSSLG_hPenSamp] = _GDIPlus_PenCreate($iLineColor, $iPenSize)
    Else
        _GDIPlus_PenSetColor($g_SSLG[$iIdx][$gSSLG_hPenSamp], $iLineColor)
        If @error Then Return SetError(2, @extended, 0)
    EndIf
    _GDIPlus_PenSetDashStyle($g_SSLG[$iIdx][$gSSLG_hPenSamp], $iPenStyle)

    Return 1

EndFunc   ;==>_SSLG_SetSetSampleIndicator

; #FUNCTION# ====================================================================================================================
; Name...........: _SSLG_SetGrid
; Description ...: Sets Grid color x/y interval and line size of Grid
; Syntax.........: _SSLG_SetGrid($iIdx, $iX_c, $iY_c, $iARGB, $iPenSize)
; Parameters ....: $idSSLG     - Control ID returned from _SSLG_CreateGraph()
;                  $iX_c = 0   - X axis grid lines (vertical) [Default] = 0 --  Removes Vertical
;                  $iY_c = 0   - Y axis grid lines (hoizontal) [Default] = 0 -- Removes Horizontal
;                  $iGridColor - Alpha, Red, Green and Blue Hex Value. (0xAARRGGBB)
;                  $iPenSize   - Size of pen [Default] = 2
;                  $iPenStyle  - GDIP_DASHSTYLE [Default] =
; Return values .: Success  - 1
;   Failure     - 0 and sets @ERROR:
;                               - 1 Invalid iIndex
;                               - 2 Error setting pen color
; Author ........: Bilgus
; Remarks .......: none
; ===============================================================================================================================
Func _SSLG_SetGrid($idSSLG, $iX_c, $iY_c, $iGridColor = Default, $iPenSize = Default, $iPenStyle = Default)
    Local $iIdx = __SSLG_LookupHandle($idSSLG)
    If $iIdx > $g_SSLG[0][0] Then Return SetError(1, @extended, 0)
    Local $aRect = $g_SSLG[$iIdx][$gSSLG_aRect]
    Local $iH = $aRect[3]

    If $iGridColor = Default Then $iGridColor = 0xFFA0A0A0
    If $iPenSize = Default Then $iPenSize = 1
    If $iPenStyle = Default Then $iPenStyle = $GDIP_DASHSTYLESOLID

    $iGridColor = __SSLG_RGB_ARGB($iGridColor)

    Local $hPath_Grid = $g_SSLG[$iIdx][$gSSLG_hPathGridH]

    _GDIPlus_PathReset($hPath_Grid)

    _GDIPlus_PenDispose($g_SSLG[$iIdx][$gSSLG_hPenGrid])
    $g_SSLG[$iIdx][$gSSLG_hPenGrid] = False

    ;NOTE: notice the negative (-) sign on the Step value -- without it Step = 0 hangs

    For $j = $iH - 1 To 0 Step -Int($iY_c)
        _GDIPlus_PathStartFigure($hPath_Grid)
        _GDIPlus_PathAddLine($hPath_Grid, -1, $j, $g_SSLG[$iIdx][$gSSLG_iIncrements] - 1, $j)
        _GDIPlus_PathCloseFigure($hPath_Grid)
    Next

    $g_SSLG[$iIdx][$gSSLG_iX_Inc] = Int($iX_c)
    If $iX_c <> 0 Or $iY_c <> 0 Then
        $g_SSLG[$iIdx][$gSSLG_hPenGrid] = _GDIPlus_PenCreate($iGridColor, $iPenSize)
        _GDIPlus_PenSetDashStyle($g_SSLG[$iIdx][$gSSLG_hPenGrid], $iPenStyle)
    EndIf

    _SSLG_ClearGraph($idSSLG)

    Return 1

EndFunc   ;==>_SSLG_SetGrid

; #FUNCTION# ====================================================================================================================
; Name...........: _SSLG_SetLine
; Description ...: Sets Line Color and line size of Graph
; Syntax.........: _SSLG_SetLineColor($iIdx, $iARGB)
; Parameters ....: $idSSLG - Control ID returned from _SSLG_CreateGraph()
;                  $iLineColor - Alpha, Red, Green and Blue Hex Value. (0xAARRGGBB)
;                  $iPenSize - Size of pen [Default] = 2
;                  $iFillColor - Alpha, Red, Green and Blue Hex Value. (0xAARRGGBB) [Default] = $iLineColor
;                  $hBrush - you may also supply your own brush to fill area under plotted line (deleted on exit by SSLG)
; Return values .: Success  - 1
;   Failure     - 0 and sets @ERROR:
;                               - 1 Invalid iIndex
;                               - 2 Error setting pen color
; Author ........: Bilgus
; Remarks .......: none
; ===============================================================================================================================
Func _SSLG_SetLine($idSSLG, $iLineColor, $iPenSize = Default, $iFillColor = Default, $hBrush = Default)
    Local $iIdx = __SSLG_LookupHandle($idSSLG)
    If $iIdx > $g_SSLG[0][0] Then Return SetError(1, @extended, 0)

    $iLineColor = __SSLG_RGB_ARGB($iLineColor)
    If $iFillColor = Default Then $iFillColor = $iLineColor
    $iFillColor = __SSLG_RGB_ARGB($iFillColor)

    _GDIPlus_BrushDispose($g_SSLG[$iIdx][$gSSLG_hBrushLine])
    If $hBrush = Default Then
        $g_SSLG[$iIdx][$gSSLG_hBrushLine] = _GDIPlus_BrushCreateSolid($iFillColor)
    Else
        $g_SSLG[$iIdx][$gSSLG_hBrushLine] = $hBrush
    EndIf

    If Not $g_SSLG[$iIdx][$gSSLG_hPen] And $iPenSize = Default Then $iPenSize = 2
    If $iPenSize <> Default Then
        _GDIPlus_PenDispose($g_SSLG[$iIdx][$gSSLG_hPen])
        $g_SSLG[$iIdx][$gSSLG_hPen] = _GDIPlus_PenCreate($iLineColor, $iPenSize)
    EndIf

    GUICtrlSetColor($idSSLG, BitAND(BitNOT(0xFF000000), $iLineColor))
    _GDIPlus_PenSetColor($g_SSLG[$iIdx][$gSSLG_hPen], $iLineColor)
    If @error Then Return SetError(2, @extended, 0)

    Return 1

EndFunc   ;==>_SSLG_SetLine

; #FUNCTION# ====================================================================================================================
; Name...........: _SSLG_SetSmoothingMode
; Description ...: Sets the graph object rendering quality

; Syntax.........: _SSLG_SetSmoothingMode($iIdx, $iSmooth = 2)
; Parameters ....: $idSSLG - Control ID returned from _SSLG_CreateGraph()
;                  $iSmooth - Smoothing mode
;                         0 - Smoothing is not applied
;                         1 - Smoothing is applied using an 8 X 4 box filter
;                         2 - Smoothing is applied using an 8 X 8 box filter [Default]
; Return values .: Success  - 1
;   Failure     - 0 and sets @ERROR:
;                               - 1 Invalid iIndex
; Author ........: Beege
; Remarks .......: none
; ===============================================================================================================================
Func _SSLG_SetSmoothingMode($idSSLG, $iSmooth = 0)
    Local $iIdx = __SSLG_LookupHandle($idSSLG)
    If $iIdx > $g_SSLG[0][0] Then Return SetError(1, @extended, 0)

    _GDIPlus_GraphicsSetSmoothingMode($g_SSLG[$iIdx][$gSSLG_hGrBuf_0], $iSmooth)
    _GDIPlus_GraphicsSetSmoothingMode($g_SSLG[$iIdx][$gSSLG_hGrBuf_1], $iSmooth)

    Return 1

EndFunc   ;==>_SSLG_SetSmoothingMode

; #FUNCTION# ====================================================================================================================
; Name...........: _SSLG_ClearGraph
; Description ...: Clears all data from Graph
; Syntax.........: _SSLG_ClearGraph($iIdx)
; Parameters ....: $idSSLG - Control ID returned from _SSLG_CreateGraph()
; Return values .: Success  - 1
;   Failure     - 0 and sets @ERROR:
;                               - 1 Invalid iIndex
; Author ........: Bilgus
; Remarks .......: none
; ===============================================================================================================================
Func _SSLG_ClearGraph($idSSLG)
    Local $iIdx = __SSLG_LookupHandle($idSSLG)
    If $iIdx > $g_SSLG[0][0] Then Return SetError(1, @extended, 0)

    If $g_SSLG[$iIdx][$gSSLG_bNeedResize] Then 
        if __SSLG_GraphicsSetup($iIdx) = 0 Then Return
    EndIf

    $g_SSLG[$iIdx][$gSSLG_iY_Last] = Default ;Used as Mutex

    ;Need to clear both buffers we dont keep track which is current
    _GDIPlus_GraphicsClear($g_SSLG[$iIdx][$gSSLG_hGrBuf_0], $g_SSLG[$iIdx][$gSSLG_iBackColor]) ;
    _GDIPlus_GraphicsClear($g_SSLG[$iIdx][$gSSLG_hGrBuf_1], $g_SSLG[$iIdx][$gSSLG_iBackColor]) ;

    _GDIPlus_PathReset($g_SSLG[$iIdx][$gSSLG_hPathGridV])
    _GDIPlus_PathReset($g_SSLG[$iIdx][$gSSLG_hPathLine])

    $g_SSLG[$iIdx][$gSSLG_iSamplesTotal] = 0
    $g_SSLG[$iIdx][$gSSLG_iSamples] = 0

    If $g_SSLG[$iIdx][$gSSLG_hPenGrid] Then
        ;Add blank samples to draw grid
        For $i = 0 To $g_SSLG[$iIdx][$gSSLG_iIncrements] - 1
            _SSLG_AddSample($idSSLG, Default)
        Next
        $g_SSLG[$iIdx][$gSSLG_iY_Last] = False
        _SSLG_UpdateGraph($idSSLG, False, False, True)
    EndIf

    $g_SSLG[$iIdx][$gSSLG_iY_Last] = False

    Return 1

EndFunc   ;==>_SSLG_ClearGraph

; #FUNCTION# ====================================================================================================================
; Name...........: _SSLG_SetResizeGraph
; Description ...: Resize Graph after call to GUICtrlSetPos
; Syntax.........: _SSLG_ResizeGraph($iIdx)
; Parameters ....: $idSSLG - Control ID returned from _SSLG_CreateGraph()
; Return values .: Success  - 1
;   Failure     - 0 and sets @ERROR:
;                               - 1 Invalid iIndex
; Author ........: Bilgus
; Remarks .......: Only sets flag -- resize will occur on next ClearGraph or UpdateGraph
; ===============================================================================================================================
Func _SSLG_SetResizeGraph($idSSLG)
    Local $iIdx = __SSLG_LookupHandle($idSSLG)
    If $iIdx > $g_SSLG[0][0] Then Return SetError(1, @extended, 0)
    $g_SSLG[$iIdx][$gSSLG_bNeedResize] = True

    Return 1

EndFunc   ;==>_SSLG_SetResizeGraph

; #FUNCTION# ====================================================================================================================
; Name...........: _SSLG_SetYRange
; Description ...: Sets the Minimum and Maximum Y Values
; Syntax.........: _SSLG_SetYRange($iIdx, $iY_Min, $iY_Max)
; Parameters ....: $idSSLG - Control ID returned from _SSLG_CreateGraph()
;   $iY_Min     - Minimum Y Value
;   $iY_Max     - Maximum Y Value
; Return values .: Success  - 1
;   Failure     - 0 and sets @ERROR:
;                               - 1 Invalid iIndex
; Author ........: Beege
; Remarks .......: User should most likly want to ClearGraph after changing Y Range
; ===============================================================================================================================
Func _SSLG_SetYRange($idSSLG, $iY_Min, $iY_Max)
    Local $iIdx = __SSLG_LookupHandle($idSSLG)
    If $iIdx > $g_SSLG[0][0] Then Return SetError(1, @extended, 0)
    $g_SSLG[$iIdx][$gSSLG_iY_Min] = $iY_Min
    $g_SSLG[$iIdx][$gSSLG_iY_Max] = $iY_Max
    $g_SSLG[$iIdx][$gSSLG_iY_Range] = Abs($iY_Max - $iY_Min)
    
    Return 1

EndFunc   ;==>_SSLG_SetYRange

; #FUNCTION# ====================================================================================================================
; Name...........: _SSLG_SetBackGroundColor
; Description ...: Sets Graph BackGround Color
; Syntax.........: _SSLG_SetBackGroundColor($iIdx, $iARGB = 0xFF000000)
; Parameters ....: $idSSLG - Control ID returned from _SSLG_CreateGraph()
;   $iARGB      - Alpha, Red, Green and Blue Hex Value. (0xAARRGGBB). Default = Black
; Return values .: Success  - 1
;   Failure     - 0 and sets @ERROR:
;                               - 1 Invalid iIndex
; Author ........: Beege
; Remarks .......: All previous data will be cleared
; ===============================================================================================================================
Func _SSLG_SetBackGroundColor($idSSLG, $iARGB = 0xFF000000)
    Local $iIdx = __SSLG_LookupHandle($idSSLG)
    If $iIdx > $g_SSLG[0][0] Then Return SetError(1, @extended, 0)

    $g_SSLG[$iIdx][$gSSLG_iBackColor] = __SSLG_RGB_ARGB($iARGB)
    _GDIPlus_BrushDispose($g_SSLG[$iIdx][$gSSLG_hBrushBkgnd])
    $g_SSLG[$iIdx][$gSSLG_hBrushBkgnd] = _GDIPlus_BrushCreateSolid($g_SSLG[$iIdx][$gSSLG_iBackColor])
    _SSLG_ClearGraph($iIdx)

    Return 1

EndFunc   ;==>_SSLG_SetBackGroundColor
#EndRegion Public Functions

#Region Internal Functions
; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........: __SSLG_RGB_ARGB
; Description ...: Convert RBG color to ARGB color
; Syntax.........:
; Parameters ....:
; Return values .:
; Author ........: Bilgus
; Remarks .......:
; ===============================================================================================================================
Func __SSLG_RGB_ARGB($iARGB)
    If BitAND($iARGB, 0xFF000000) = 0 Then
        $iARGB = BitOR($iARGB, 0xFF000000)
    EndIf

    Return $iARGB

EndFunc   ;==>__SSLG_RGB_ARGB

; #INTERNAL_USE_ONLY# ====================================================================================================================
; Name...........: __SSLG_GraphicsSetup
; Description ...: Internal function -- (Re)Creates all the graphics objects
; Syntax.........: __SSLG_GraphicsSetup($iIdx)
; Parameters ....: $iIdx - INTERNAL Graph ID
; Return values .: N/A
;   Failure     - 0 and sets @ERROR:
;                               - 2 No change
; Author ........: Bilgus
; Remarks .......: All previous data will be cleared, Graphics objects destroyed, Re-created if $bReInit = True
; ===============================================================================================================================
Func __SSLG_GraphicsSetup($iIdx)
    $g_SSLG[$iIdx][$gSSLG_bNeedResize] = False

    Local $aRectOld = $g_SSLG[$iIdx][$gSSLG_aRect]
    Local $aRect = WinGetPos($g_SSLG[$iIdx][$gSSLG_hCtrl])

    If $g_SSLG[$iIdx][$gSSLG_hBitmap_0] And $aRect[2] = $aRectOld[2] And $aRect[3] = $aRectOld[3] Then
        ;ConsoleWrite("Resize not needed")
        Return SetError(2, @extended, 0)
    EndIf
    $g_SSLG[$iIdx][$gSSLG_aRect] = $aRect
    Local $iW = $aRect[2]
    Local $iH = $aRect[3]

    ;ConsoleWrite("New SZ: (" & $aRect[0] & ", " & $aRect[1] & "), (" & $iW & ", " & $iH & ")" & @CRLF)
    Local $hHBMP, $hGrBuf0, $hGrBuf1, $hBitmap0, $hBitmap1
    If $g_SSLG[$iIdx][$gSSLG_hBitmap_0] Then
        $hHBMP = $g_SSLG[$iIdx][$gSSLG_hHBitmapGDI_]
        $hGrBuf0 = $g_SSLG[$iIdx][$gSSLG_hGrBuf_0]
        $hBitmap0 = $g_SSLG[$iIdx][$gSSLG_hBitmap_0]
        $hGrBuf1 = $g_SSLG[$iIdx][$gSSLG_hGrBuf_1]
        $hBitmap1 = $g_SSLG[$iIdx][$gSSLG_hBitmap_1]
        $g_SSLG[$iIdx][$gSSLG_iIncrementSize] = -1
    EndIf


    Local $hGraphic = _GDIPlus_GraphicsCreateFromHWND($g_SSLG[$iIdx][$gSSLG_hCtrl])
    Local $hBitmap = _GDIPlus_BitmapCreateFromGraphics($iW, $iH, $hGraphic)
    
    ;$GDIP_PXF32PARGB (Pre-multiplied) appears to be the most efficient format as far as GDI+ is concerned
    $g_SSLG[$iIdx][$gSSLG_hBitmap_0] = _GDIPlus_BitmapCloneArea($hBitmap, 0, 0, $iW, $iH, $GDIP_PXF32PARGB)
    $g_SSLG[$iIdx][$gSSLG_hGrBuf_0] = _GDIPlus_ImageGetGraphicsContext($g_SSLG[$iIdx][$gSSLG_hBitmap_0])

    $g_SSLG[$iIdx][$gSSLG_hBitmap_1] = _GDIPlus_BitmapCloneArea($hBitmap, 0, 0, $iW, $iH, $GDIP_PXF32PARGB)
    $g_SSLG[$iIdx][$gSSLG_hGrBuf_1] = _GDIPlus_ImageGetGraphicsContext($g_SSLG[$iIdx][$gSSLG_hBitmap_1])

    $g_SSLG[$iIdx][$gSSLG_hHBitmapGDI_] = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap)

    $g_SSLG[$iIdx][$gSSLG_iIncrementSize] = Ceiling($iW / ($g_SSLG[$iIdx][$gSSLG_iIncrements] + 1))
    $g_SSLG[$iIdx][$gSSLG_iIncrements] = Int($iW / $g_SSLG[$iIdx][$gSSLG_iIncrementSize])

    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_GraphicsDispose($hGraphic)

    Local $aResult = DllCall("user32.dll", "hwnd", "GetParent", "hwnd", $g_SSLG[$iIdx][$gSSLG_hCtrl])
    If Not @error Then _WinAPI_RedrawWindow($aResult[0])

    _WinAPI_DeleteObject($hHBMP)
    _GDIPlus_GraphicsDispose($hGrBuf0)
    _GDIPlus_BitmapDispose($hBitmap0)
    _GDIPlus_GraphicsDispose($hGrBuf1)
    _GDIPlus_BitmapDispose($hBitmap1)

    Return 1

EndFunc   ;==>__SSLG_GraphicsSetup

; #INTERNAL_USE_ONLY# ====================================================================================================================
; Name...........: __SSLG_GraphicsDraw
; Description ...: Internal function -- BitBlt back to hDC
; Syntax.........: __SSLG_GraphicsDraw($iIdx)
; Parameters ....: $iIdx - INTERNAL Graph ID
;                  $iW - Width
;                  $iH - Height
; Return values .: N/A
; Author ........: Bilgus
; Remarks .......: Copy the GDI+ bitmap to a HBITMAP blit to the screen
; ===============================================================================================================================
Func __SSLG_GraphicsDraw($iIdx, $hBitmap, $iW, $iH)
    Local $hObjOld, $hDC_Src, $hDC_Dst, $hHBitmap, $hGraphic

    ;$hBitmap = GDI+ Bitmap [SRC]
    $hHBitmap = $g_SSLG[$iIdx][$gSSLG_hHBitmapGDI_] ;Standard GDI Bitmap [DEST]

    ;DC where we can select the Standard GDI Bitmap
    $hDC_Src = $g_SSLG[$iIdx][$gSSLG_hDCBuf]
    $hObjOld = _WinAPI_SelectObject($hDC_Src, $hHBitmap)

    $hGraphic = _GDIPlus_GraphicsCreateFromHDC($hDC_Src)
    _GDIPlus_GraphicsSetSmoothingMode($hGraphic, 2)
    _GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap, 0, 0, $iW, $iH)
    _GDIPlus_GraphicsDispose($hGraphic)

    $hDC_Dst = _WinAPI_GetDC($g_SSLG[$iIdx][$gSSLG_hCtrl])
    _WinAPI_BitBlt($hDC_Dst, 0, 0, $iW, $iH, $hDC_Src, 0, 0, $SRCCOPY) ;Copy back to ctrl
    _WinAPI_ReleaseDC($g_SSLG[$iIdx][$gSSLG_hCtrl], $hDC_Dst)

    _WinAPI_SelectObject($hDC_Src, $hObjOld) ;Put old object back

EndFunc   ;==>__SSLG_GraphicsDraw

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........: __SSLG_LookupHandle
; Description ...: Converts controlID or Handles to internal graph index
; Syntax.........:
; Parameters ....:
; Return values .:
; Author ........: Bilgus
; Remarks .......:
; ===============================================================================================================================
Func __SSLG_LookupHandle($idSSLG, $bForce = True)
    Static Local $idSSLG_Last = -1
    Static Local $hSSLG_Last = 0
    Local Const $GUI_DISABLE = 128
    If $bForce Or Not BitAND(GUICtrlGetState($idSSLG), $GUI_DISABLE) Then
        If $idSSLG = $idSSLG_Last Then Return $hSSLG_Last ;Shortcut
        $idSSLG = Hex($idSSLG)
        Local $oDict = $g_SSLG[0][$gSSLG_DICT]

        If $oDict.Exists($idSSLG) Then
            $idSSLG_Last = $idSSLG
            $hSSLG_Last = $oDict.Item($idSSLG)
            Return $hSSLG_Last
        EndIf

        ConsoleWriteError("Graph ControlID: " & $idSSLG & " does not exist" & @CRLF)
        For $vKey In $oDict
            ConsoleWriteError("[" & $vKey & "] = " & $oDict.Item($vKey) & @CRLF)
        Next
    EndIf

    Return SetError(1, @extended, $g_SSLG[0][0] + 1)

EndFunc   ;==>__SSLG_LookupHandle

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........: __SSLG_Exit()
; Description ...: Cleans up stored objects
; Syntax.........:
; Parameters ....:
; Return values .:
; Author ........:
; Remarks .......:
; ===============================================================================================================================
Func __SSLG_Exit()
    If $g_SSLG[0][0] Then
        For $i = 1 To $g_SSLG[0][0]
            $g_SSLG[$i][$gSSLG_iY_Last] = Default ;Mutex

            _WinAPI_DeleteObject($g_SSLG[$i][$gSSLG_hHBitmapGDI_])

            _GDIPlus_GraphicsDispose($g_SSLG[$i][$gSSLG_hGrBuf_1])
            _GDIPlus_BitmapDispose($g_SSLG[$i][$gSSLG_hBitmap_1])

            _GDIPlus_GraphicsDispose($g_SSLG[$i][$gSSLG_hGrBuf_0])
            _GDIPlus_BitmapDispose($g_SSLG[$i][$gSSLG_hBitmap_0])

            _GDIPlus_MatrixDispose($g_SSLG[$i][$gSSLG_hMatrixHT])

            _GDIPlus_PathDispose($g_SSLG[$i][$gSSLG_hPathLine])
            _GDIPlus_PathDispose($g_SSLG[$i][$gSSLG_hPathGridV])
            _GDIPlus_PathDispose($g_SSLG[$i][$gSSLG_hPathGridH])

            _GDIPlus_PenDispose($g_SSLG[$i][$gSSLG_hPenGrid])
            _GDIPlus_PenDispose($g_SSLG[$i][$gSSLG_hPenSamp])
            _GDIPlus_PenDispose($g_SSLG[$i][$gSSLG_hPen])

            _GDIPlus_BrushDispose($g_SSLG[$i][$gSSLG_hBrushLine])
            _GDIPlus_BrushDispose($g_SSLG[$i][$gSSLG_hBrushBkgnd])
            _WinAPI_DeleteDC($g_SSLG[$i][$gSSLG_hDCBuf])
        Next
    EndIf

    _GDIPlus_Shutdown()

EndFunc   ;==>__SSLG_Exit
#EndRegion Internal Functions

 

Updated:

Previous Downloads [38 / 38/ 0]

SSLG.au3 waveform.au3 Peak.au3

Edited by Bilgus
Add screenshot, Update Code, Update Code, Update Code

Share this post


Link to post
Share on other sites
Posted (edited)

Since I have this extra post here I'll go into some of the details

As you recall (or maybe you have no idea) Begee's original code only updated one point on each graph redraw

This lead to some pretty high CPU usage if you wanted to add lots of points

My idea was to allow adding multiple points before redrawing the graph.......

Spoiler

First Try:

The first try I just encoded all the new points as 4byte chunks Concatenated in a binary string

Then on redraw decode these new points and display them, this worked decently but was still a little slow

 

Next Idea:

My next idea was to use a graphics path and just add points at every sample (X, Y) (and the grid lines too)

(X is the incremented sample position, Y the value position)

(0, Y) (1, Y) (2, Y) (3, Y) (4, Y)

This worked VERY well and also allowed me to get rid of the image shifting

Bummer:

 I couldnt find a way to QUICKLY & easily discard the portion of the path that had scrolled off screen

(except to walk the points and copy the ones I wanted to save to a new path)

as a result CPU usage started going UP and UP over time ( since more and more points needed translation)

 

Final Idea:

So clearly a graphics path is an excellent way to do this

Rather than continually adding to it instead I put the scrolling code back in but this time I only save the path till the redraw occurs

On GraphUpdate

  • The old graph is scrolled by (incrementSz * #Samples) and copied to the backbuffer
  • The now blank right portion gets the background copied into the empty space
    • (if enabled) the grid gets copied here too
  • The new points are translated in the X direction (scaled as a function of (IncrementSz * SamplePos) 
    • I wanted to do this with Y as well but I seem to get a rotation instead of scaling :(
  • The path gets reset back to empty and the Sample Count set to 0
    • Speaking of Sample Count GDI+ has a function to return number of points in a path (BUT it sometimes returns 0???)
  • After translation the path is written to the backbuffer
    • (if enabled) a vertical line is also placed at the right most portion of the graph to show distance between graph updates
  • Finally the new image is copied back to the graph

As I mentioned above I also return a real control Id from the create function

This is accomplished by creating a label control and drawing on that instead of the main hWnd

Having a label control underneath allows a few things

  • Click Events
  • Colored background
  • Control Disable
  • Real Control IDs
  • Message displayed on disable
  • Should also allow resizing the control though I didn't add this functionality as I have no need

The only problem is how do we associate the control ID with the graph instance

Here I used the Scripting.Dictionary object as a simple associative array the Key = Hex(controlID) Value = graph instance

Note: setting the backcolor of the control doesn't change the graph background only the disabled background

 

Oh hey if you look close at the code there is even a 'mutex' in there

I noticed if the graph updates while in the add sample code the points go to the wrong sample when it returns

 

 

 

Edited by Bilgus
updates

Share this post


Link to post
Share on other sites
Posted (edited)

Code In first post updated

  • Grids are now scaled to proper size 
  • Got rid of CloneBitmap on every graphics update (far less page faults now)
  • Allow use of ARGB for colors or RGB
  • Faster redraw (~10-20 ms) 
  • Y coords are now scaled using GDI+
  • Option to fill bottom portion of graph - Fixed scaling issue
Edited by Bilgus

Share this post


Link to post
Share on other sites

I noticed that my control flickers a lot more than his original 

I removed the BitBlt calls in favor of the GDI+ DrawImage so I could get rid of creating a new HBitmap each update

Looks to me like BitBlt does a better job

I'll upload a version fixing this issue and still without creating a new HBitmap in a day or two

Why am I trying to keep from creating a new bitmap each update you ask?

-- PageFaults --

While they are soft pagefaults it still means the program is churning memory so I want to try and decrease as much as possible

The other advantage is lower memory and processor usage

 

Oh I also have added the ability to resize the control now

It just deletes the old buffers and recreates them but it works :)

Share this post


Link to post
Share on other sites

SSLG code has been updated

Turns out BitBlt is faster than _GDIPlus_DrawImage even after you do an extra copy to a GDI HBitmap

Weird, Never would have guessed...

  • BitBlt used for final drawing to control
  • Added ability to resize the graph on window resize (try it in the example)
  • SSLG is much more well behaved after this update
  • There are now two buffers that get swapped every other graph update this gets us a free copy of the last image
  • Grid lines resize automatically on control resize
  • All sample scaling now handled with graphics path

GDI+ has a lot of heap allocated memory behind the scenes about the only thing that still has a lot of allocations in SSLG

is when you enable bCompress for the old samples otherwise you should see very few page faults

Share this post


Link to post
Share on other sites
Posted (edited)

Well I added another example peak.au3 it uses the Windows sound AudioMeterInfo.GetPeakValue code and displays it in a SSLG graph

See for Trancex's original code: https://www.autoitscript.com/forum/topic/142523-master-loudnessvolume-via-peak-meter-windows-7-64-bit/?tab=comments#comment-1003940

 

Unfortunately I found a few more bugs which are (fortunately) now fixed

  • AddSample did not check if UpdateGraph was currently running causing the graph to be cleared
  • If Grid was enabled SetResizeGraph did not draw new gridlines after the resize
  • Couple of error numbers were changed to match between AddSample and UpdateGraph
  • Increments are now recalculated after IncrementsSize is calculated

 

 

Edited by Bilgus

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

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By UEZ
      Here another example to mark the desktop to get the marked region for capturing. This example is not perfect and not very fast (room for improvements).
      ;Coded by UEZ build 2020-08-07 beta ;Code cleanup up mLipok ; ;Short instruction: mark area on your desktop and press return key to capture. #include <APISysConstants.au3> #include <Array.au3> ;#include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <ScreenCapture.au3> #include <WinAPIGdi.au3> #include <WinAPISysWin.au3> #include <WindowsConstants.au3> ; enum _PROCESS_DPI_AWARENESS -> https://msdn.microsoft.com/en-us/library/windows/desktop/dn280512(v=vs.85).aspx Global Enum $DPI_AWARENESS_INVALID = -1, $PROCESS_DPI_UNAWARE = 0, $PROCESS_SYSTEM_DPI_AWARE, $PROCESS_PER_MONITOR_DPI_AWARE ;https://docs.microsoft.com/en-us/windows/desktop/hidpi/dpi-awareness-context Global Enum $Context_UnawareGdiScaled = -5, $Context_PerMonitorAwareV2, $Context_PerMonitorAware, $Context_SystemAware, $Context_Unaware _WinAPI_SetProcessDpiAwarenessContext($Context_PerMonitorAware) Global $__g_hGUI_MarkArea, $__g_hGUI_Bg, $__g_iLabel_TL, $__g_iLabel_TM, $__g_iLabel_TR, $__g_iLabel_LM, $__g_iLabel_RM, $__g_iLabel_BL, $__g_iLabel_BM, _ $__g_iLabel_BR, $__g_iOldCursor, $__g_iW, $__g_iH, $__g_iColor_ResizeDots = 0xFFFFFF, $__g_iBorder = 4, $__g_bSelectionDone = False Global $aRect = _GDIPlus_MarkScreenRegionAnimated() Global $hImage_Capture = _ScreenCapture_Capture(@TempDir & "\Test.png", $aRect[0], $aRect[1], $aRect[0] + $aRect[2] - 1, $aRect[1] + $aRect[3] - 1, False) ShellExecute(@TempDir & "\Test.png") ;_ArrayDisplay($aRect, "Marked area coordinates") Func _GDIPlus_MarkScreenRegionAnimated($bAnim = True) _GDIPlus_Startup() Local Const $hFullScreen = WinGetHandle("[TITLE:Program Manager;CLASS:Progman]") Local Const $aFullScreen = WinGetPos($hFullScreen) $__g_hGUI_Bg = GUICreate("", $aFullScreen[2], $aFullScreen[3], $aFullScreen[0], $aFullScreen[1], BitOR($WS_CLIPCHILDREN, $WS_POPUP), $WS_EX_TOPMOST) ;to avoid cursor flickering and for proper control read WinSetTrans($__g_hGUI_Bg, "", 0x01) $__g_hGUI_MarkArea = GUICreate("", 1, 1, -1, -1, $bAnim ? $WS_POPUP : BitOR($WS_POPUP, $WS_BORDER), BitOR($WS_EX_TOPMOST, $WS_EX_LAYERED), $__g_hGUI_Bg) GUISetBkColor(0xABCDEF, $__g_hGUI_MarkArea) If Not $bAnim Then $__g_iColor_ResizeDots = 0xFF0000 $__g_iLabel_TL = GUICtrlCreateLabel("", 0, 0, $__g_iBorder, $__g_iBorder) ;top left GUICtrlSetResizing(-1, $GUI_DOCKSIZE) GUICtrlSetBkColor(-1, $__g_iColor_ResizeDots) $__g_iLabel_TM = GUICtrlCreateLabel("", 0, 0, $__g_iBorder, $__g_iBorder) ;top mid GUICtrlSetResizing(-1, $GUI_DOCKSIZE) GUICtrlSetBkColor(-1, $__g_iColor_ResizeDots) $__g_iLabel_TR = GUICtrlCreateLabel("", 0, 0, $__g_iBorder, $__g_iBorder) ;top right GUICtrlSetResizing(-1, $GUI_DOCKSIZE) GUICtrlSetBkColor(-1, $__g_iColor_ResizeDots) $__g_iLabel_LM = GUICtrlCreateLabel("", 0, 0, $__g_iBorder, $__g_iBorder) ;left mid GUICtrlSetResizing(-1, $GUI_DOCKSIZE) GUICtrlSetBkColor(-1, $__g_iColor_ResizeDots) $__g_iLabel_RM = GUICtrlCreateLabel("", 0, 0, $__g_iBorder, $__g_iBorder) ;right mid GUICtrlSetResizing(-1, $GUI_DOCKSIZE) GUICtrlSetBkColor(-1, $__g_iColor_ResizeDots) $__g_iLabel_BL = GUICtrlCreateLabel("", 0, 0, $__g_iBorder, $__g_iBorder) ;bottom left GUICtrlSetResizing(-1, $GUI_DOCKSIZE) GUICtrlSetBkColor(-1, $__g_iColor_ResizeDots) $__g_iLabel_BM = GUICtrlCreateLabel("", 0, 0, $__g_iBorder, $__g_iBorder) ;bottom mid GUICtrlSetResizing(-1, $GUI_DOCKSIZE) GUICtrlSetBkColor(-1, $__g_iColor_ResizeDots) $__g_iLabel_BR = GUICtrlCreateLabel("", 0, 0, $__g_iBorder, $__g_iBorder) ;bottom right GUICtrlSetResizing(-1, $GUI_DOCKSIZE) GUICtrlSetBkColor(-1, $__g_iColor_ResizeDots) GUISetState(@SW_SHOWNA, $__g_hGUI_Bg) GUISetState(@SW_SHOW, $__g_hGUI_MarkArea) $__g_iOldCursor = MouseGetCursor() GUISetCursor(3, 1, $__g_hGUI_Bg) GUISetCursor(3, 1, $__g_hGUI_MarkArea) _WinAPI_SetLayeredWindowAttributes($__g_hGUI_MarkArea, 0xABCDEF, 0xF0) Local $aMPos, $aPrevMPos[2] = [MouseGetPos(0) + 1, MouseGetPos(1) + 1], $iID, $aCI, $iX, $iY, $aOldWinPos, $aOldMPos, $bMoved Local $aGUIStartPos, $iKey_Exit = GUICtrlCreateButton("", $aFullScreen[0] - 10, $aFullScreen[1] - 10, 1, 1), $aAccelKeys[1][2] = [["{ENTER}", $iKey_Exit]] GUISetAccelerators($aAccelKeys, $__g_hGUI_Bg) GUISetAccelerators($aAccelKeys, $__g_hGUI_MarkArea) #forceref $bMoved Do Switch GUIGetMsg() Case $GUI_EVENT_CLOSE, $iKey_Exit If $bAnim Then GUIRegisterMsg($WM_TIMER, "") DllCall("user32.dll", "bool", "KillTimer", "hwnd", $__g_hGUI_MarkArea, "uint_ptr", $iID) GUIRegisterMsg($WM_ERASEBKGND, "") EndIf _GDIPlus_Shutdown() Local $aResult = WinGetPos($__g_hGUI_MarkArea) $aResult[2] = WinGetClientSize($__g_hGUI_MarkArea)[0] $aResult[3] = WinGetClientSize($__g_hGUI_MarkArea)[1] GUIDelete($__g_hGUI_MarkArea) GUIDelete($__g_hGUI_Bg) If Not $__g_bSelectionDone Then $aResult = 0 Return $aResult EndSwitch $aMPos = MouseGetPos() If ($aMPos[0] <> $aPrevMPos[0] Or $aMPos[1] <> $aPrevMPos[1]) And (Not $__g_bSelectionDone) Then WinMove($__g_hGUI_MarkArea, "", $aMPos[0], $aMPos[1]) $aPrevMPos = $aMPos EndIf $aCI = GUIGetCursorInfo($__g_hGUI_MarkArea) If $aCI[2] And (Not $__g_bSelectionDone) Then $aGUIStartPos = WinGetPos($__g_hGUI_MarkArea) If $bAnim Then GUIRegisterMsg($WM_ERASEBKGND, "WM_ERASEBKGND") GUIRegisterMsg($WM_TIMER, "PlayBorderAnim") $iID = DllCall("User32.dll", "uint_ptr", "SetTimer", "hwnd", $__g_hGUI_MarkArea, "uint_ptr", 1, "uint", 50, "ptr", 0)[0] EndIf While $aCI[2] * Sleep(10) $aCI = GUIGetCursorInfo($__g_hGUI_MarkArea) $aMPos = MouseGetPos() $__g_iW = Abs($aMPos[0] - $aGUIStartPos[0]) + 1 $__g_iH = Abs($aMPos[1] - $aGUIStartPos[1]) + 1 If $aMPos[0] < $aGUIStartPos[0] Then $iX = $aMPos[0] Else $iX = $aGUIStartPos[0] EndIf If $aMPos[1] < $aGUIStartPos[1] Then $iY = $aMPos[1] Else $iY = $aGUIStartPos[1] EndIf WinMove($__g_hGUI_MarkArea, "", $iX, $iY, $__g_iW, $__g_iH) UpdateCtrlPos($bAnim) WEnd $__g_bSelectionDone = True GUISetCursor(3, 1, $__g_hGUI_MarkArea) ElseIf $aCI[3] And $__g_bSelectionDone Then $aGUIStartPos = WinGetPos($__g_hGUI_MarkArea) If _WinAPI_PtInRectEx(MouseGetPos(0), MouseGetPos(1), $aGUIStartPos[0], $aGUIStartPos[1], $aGUIStartPos[0] + $aGUIStartPos[2], $aGUIStartPos[1] + $aGUIStartPos[3]) Then $aMPos = MouseGetPos() $aGUIStartPos = WinGetPos($__g_hGUI_MarkArea) While $aCI[3] * Sleep(10) $aCI = GUIGetCursorInfo($__g_hGUI_MarkArea) WinMove($__g_hGUI_MarkArea, "", $aGUIStartPos[0] - ($aMPos[0] - MouseGetPos(0)), $aGUIStartPos[1] - ($aMPos[1] - MouseGetPos(1)), $__g_iW, $__g_iH) GUISetCursor(0, 1, $__g_hGUI_Bg) GUISetCursor(0, 1, $__g_hGUI_MarkArea) WEnd GUISetCursor(3, 1, $__g_hGUI_Bg) GUISetCursor(3, 1, $__g_hGUI_MarkArea) EndIf EndIf If $__g_bSelectionDone Then $aCI = GUIGetCursorInfo($__g_hGUI_MarkArea) If @error Then ContinueLoop Switch $aCI[4] Case $__g_iLabel_TL GUISetCursor(12, 1, $__g_hGUI_MarkArea) If $aCI[2] Then $aOldWinPos = WinGetPos($__g_hGUI_MarkArea) $aOldMPos = MouseGetPos() While $aCI[2] * Sleep(10) $aCI = GUIGetCursorInfo($__g_hGUI_MarkArea) WinMove($__g_hGUI_MarkArea, "", MouseGetPos(0), MouseGetPos(1), $aOldWinPos[2] + ($aOldMPos[0] - MouseGetPos(0)), $aOldWinPos[3] + ($aOldMPos[1] - MouseGetPos(1))) WEnd UpdateCtrlPos($bAnim) EndIf Case $__g_iLabel_BR GUISetCursor(12, 1, $__g_hGUI_MarkArea) If $aCI[2] Then $aOldWinPos = WinGetPos($__g_hGUI_MarkArea) $aOldMPos = MouseGetPos() While $aCI[2] * Sleep(10) $aCI = GUIGetCursorInfo($__g_hGUI_MarkArea) WinMove($__g_hGUI_MarkArea, "", $aOldWinPos[0], $aOldWinPos[1], $aOldWinPos[2] - ($aOldMPos[0] - MouseGetPos(0)), $aOldWinPos[3] - ($aOldMPos[1] - MouseGetPos(1))) WEnd UpdateCtrlPos($bAnim) EndIf Case $__g_iLabel_TR GUISetCursor(10, 1, $__g_hGUI_MarkArea) If $aCI[2] Then $aOldWinPos = WinGetPos($__g_hGUI_MarkArea) $aOldMPos = MouseGetPos() While $aCI[2] * Sleep(10) $aCI = GUIGetCursorInfo($__g_hGUI_MarkArea) WinMove($__g_hGUI_MarkArea, "", $aOldWinPos[0], MouseGetPos(1), $aOldWinPos[2] - ($aOldMPos[0] - MouseGetPos(0)), $aOldWinPos[3] + ($aOldMPos[1] - MouseGetPos(1))) WEnd UpdateCtrlPos($bAnim) EndIf Case $__g_iLabel_BL GUISetCursor(10, 1, $__g_hGUI_MarkArea) If $aCI[2] Then $aOldWinPos = WinGetPos($__g_hGUI_MarkArea) $aOldMPos = MouseGetPos() While $aCI[2] * Sleep(10) $aCI = GUIGetCursorInfo($__g_hGUI_MarkArea) WinMove($__g_hGUI_MarkArea, "", MouseGetPos(0), $aOldWinPos[1], $aOldWinPos[2] + ($aOldMPos[0] - MouseGetPos(0)), $aOldWinPos[3] - ($aOldMPos[1] - MouseGetPos(1))) WEnd UpdateCtrlPos($bAnim) EndIf Case $__g_iLabel_LM GUISetCursor(13, 1, $__g_hGUI_MarkArea) If $aCI[2] Then $aOldWinPos = WinGetPos($__g_hGUI_MarkArea) $aOldMPos = MouseGetPos() While $aCI[2] * Sleep(10) $aCI = GUIGetCursorInfo($__g_hGUI_MarkArea) WinMove($__g_hGUI_MarkArea, "", MouseGetPos(0), $aOldWinPos[1], $aOldWinPos[2] + ($aOldMPos[0] - MouseGetPos(0)), $aOldWinPos[3]) WEnd UpdateCtrlPos($bAnim) EndIf Case $__g_iLabel_RM GUISetCursor(13, 1, $__g_hGUI_MarkArea) If $aCI[2] Then $aOldWinPos = WinGetPos($__g_hGUI_MarkArea) $aOldMPos = MouseGetPos() While $aCI[2] * Sleep(10) $aCI = GUIGetCursorInfo($__g_hGUI_MarkArea) WinMove($__g_hGUI_MarkArea, "", $aOldWinPos[0], $aOldWinPos[1], $aOldWinPos[2] - ($aOldMPos[0] - MouseGetPos(0)), $aOldWinPos[3]) WEnd UpdateCtrlPos($bAnim) EndIf Case $__g_iLabel_TM GUISetCursor(11, 1, $__g_hGUI_MarkArea) If $aCI[2] Then $aOldWinPos = WinGetPos($__g_hGUI_MarkArea) $aOldMPos = MouseGetPos() While $aCI[2] * Sleep(10) $aCI = GUIGetCursorInfo($__g_hGUI_MarkArea) WinMove($__g_hGUI_MarkArea, "", $aOldWinPos[0], MouseGetPos(1), $aOldWinPos[2], $aOldWinPos[3] + ($aOldMPos[1] - MouseGetPos(1))) WEnd UpdateCtrlPos($bAnim) EndIf Case $__g_iLabel_BM GUISetCursor(11, 1, $__g_hGUI_MarkArea) If $aCI[2] Then $aOldWinPos = WinGetPos($__g_hGUI_MarkArea) $aOldMPos = MouseGetPos() While $aCI[2] * Sleep(10) $aCI = GUIGetCursorInfo($__g_hGUI_MarkArea) WinMove($__g_hGUI_MarkArea, "", $aOldWinPos[0], $aOldWinPos[1], $aOldWinPos[2], $aOldWinPos[3] - ($aOldMPos[1] - MouseGetPos(1))) WEnd UpdateCtrlPos($bAnim) EndIf Case Else GUISetCursor(3, 1, $__g_hGUI_MarkArea) EndSwitch EndIf Until False EndFunc ;==>_GDIPlus_MarkScreenRegionAnimated Func UpdateCtrlPos($bAnim = True) Local Const $aGUIStartPos = WinGetPos($__g_hGUI_MarkArea) If $__g_bSelectionDone And $bAnim Then GUIRegisterMsg($WM_TIMER, "") $__g_iW = $aGUIStartPos[2] $__g_iH = $aGUIStartPos[3] ControlMove($__g_hGUI_MarkArea, "", $__g_iLabel_TL, 0, 0, $__g_iBorder, $__g_iBorder) ControlMove($__g_hGUI_MarkArea, "", $__g_iLabel_TM, ($__g_iW - $__g_iBorder) / 2, 0, $__g_iBorder, $__g_iBorder) ControlMove($__g_hGUI_MarkArea, "", $__g_iLabel_TR, ($__g_iW - $__g_iBorder - $__g_iBorder / 2), 0, $__g_iBorder, $__g_iBorder) ControlMove($__g_hGUI_MarkArea, "", $__g_iLabel_LM, 0, ($__g_iH - $__g_iBorder) / 2, $__g_iBorder, $__g_iBorder) ControlMove($__g_hGUI_MarkArea, "", $__g_iLabel_RM, ($__g_iW - $__g_iBorder - $__g_iBorder / 2), ($__g_iH - $__g_iBorder) / 2, $__g_iBorder, $__g_iBorder) ControlMove($__g_hGUI_MarkArea, "", $__g_iLabel_BL, 0, ($__g_iH - $__g_iBorder - $__g_iBorder / 2), $__g_iBorder, $__g_iBorder) ControlMove($__g_hGUI_MarkArea, "", $__g_iLabel_BM, ($__g_iW - $__g_iBorder) / 2, ($__g_iH - $__g_iBorder - $__g_iBorder / 2), $__g_iBorder, $__g_iBorder) ControlMove($__g_hGUI_MarkArea, "", $__g_iLabel_BR, ($__g_iW - $__g_iBorder - $__g_iBorder / 2), ($__g_iH - $__g_iBorder - $__g_iBorder / 2), $__g_iBorder, $__g_iBorder) If $__g_bSelectionDone And $bAnim Then GUIRegisterMsg($WM_TIMER, "PlayBorderAnim") EndFunc ;==>UpdateCtrlPos Func PlayBorderAnim() Local $aWinPos = WinGetClientSize($__g_hGUI_MarkArea), $iW = $aWinPos[0], $iH = $aWinPos[1] Local Static $fOffset = 0 Local Const $iSize = $__g_iBorder / 2 Local Const $hDC = _WinAPI_GetDC($__g_hGUI_MarkArea) 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) Local Const $hPen = _GDIPlus_PenCreate(0xFF0178D7, $iSize), $hPen2 = _GDIPlus_PenCreate(0xFFFFFFFF, $iSize), _ $hBrush = _GDIPlus_BrushCreateSolid(0xFF000000 + $__g_iColor_ResizeDots), $hPen3 = _GDIPlus_PenCreate(0xFF000000) _GDIPlus_PenSetDashStyle($hPen, $GDIP_DASHSTYLEDASHDOT) _GDIPlus_GraphicsClear($hCanvas, 0xFFABCDEF) ;for faster performance direct dll calls DllCall($__g_hGDIPDll, "int", "GdipDrawRectangle", "handle", $hCanvas, "handle", $hPen2, "float", 1 + $iSize, "float", 1 + $iSize, "float", $iW - 2 * $iSize - 2, "float", $iH - 2 * $iSize - 2) DllCall($__g_hGDIPDll, "int", "GdipSetPenDashOffset", "handle", $hPen, "float", $fOffset) DllCall($__g_hGDIPDll, "int", "GdipDrawRectangle", "handle", $hCanvas, "handle", $hPen, "float", 1 + $iSize, "float", 1 + $iSize, "float", $iW - 2 * $iSize - 2, "float", $iH - 2 * $iSize - 2) DllCall($__g_hGDIPDll, "int", "GdipFillRectangle", "handle", $hCanvas, "handle", $hBrush, "float", 0, "float", 0, "float", $__g_iBorder + 1, "float", $__g_iBorder + 1) DllCall($__g_hGDIPDll, "int", "GdipDrawRectangle", "handle", $hCanvas, "handle", $hPen3, "float", 0, "float", 0, "float", $__g_iBorder + 1, "float", $__g_iBorder + 1) DllCall($__g_hGDIPDll, "int", "GdipFillRectangle", "handle", $hCanvas, "handle", $hBrush, "float", ($iW - $__g_iBorder) / 2, "float", 0, "float", $__g_iBorder + 1, "float", $__g_iBorder + 1) DllCall($__g_hGDIPDll, "int", "GdipDrawRectangle", "handle", $hCanvas, "handle", $hPen3, "float", ($iW - $__g_iBorder) / 2, "float", 0, "float", $__g_iBorder + 1, "float", $__g_iBorder + 1) DllCall($__g_hGDIPDll, "int", "GdipFillRectangle", "handle", $hCanvas, "handle", $hBrush, "float", ($iW - $__g_iBorder) - 2, "float", 0, "float", $__g_iBorder + 1, "float", $__g_iBorder + 1) DllCall($__g_hGDIPDll, "int", "GdipDrawRectangle", "handle", $hCanvas, "handle", $hPen3, "float", ($iW - $__g_iBorder) - 2, "float", 0, "float", $__g_iBorder + 1, "float", $__g_iBorder + 1) DllCall($__g_hGDIPDll, "int", "GdipFillRectangle", "handle", $hCanvas, "handle", $hBrush, "float", 0, "float", ($iH - $__g_iBorder) / 2, "float", $__g_iBorder + 1, "float", $__g_iBorder + 1) DllCall($__g_hGDIPDll, "int", "GdipDrawRectangle", "handle", $hCanvas, "handle", $hPen3, "float", 0, "float", ($iH - $__g_iBorder) / 2, "float", $__g_iBorder + 1, "float", $__g_iBorder + 1) DllCall($__g_hGDIPDll, "int", "GdipFillRectangle", "handle", $hCanvas, "handle", $hBrush, "float", ($iW - $__g_iBorder) - 2, "float", ($iH - $__g_iBorder) / 2, "float", $__g_iBorder + 1, "float", $__g_iBorder + 1) DllCall($__g_hGDIPDll, "int", "GdipDrawRectangle", "handle", $hCanvas, "handle", $hPen3, "float", ($iW - $__g_iBorder) - 2, "float", ($iH - $__g_iBorder) / 2, "float", $__g_iBorder + 1, "float", $__g_iBorder + 1) DllCall($__g_hGDIPDll, "int", "GdipFillRectangle", "handle", $hCanvas, "handle", $hBrush, "float", 0, "float", ($iH - $__g_iBorder) - 2, "float", $__g_iBorder + 1, "float", $__g_iBorder + 1) DllCall($__g_hGDIPDll, "int", "GdipDrawRectangle", "handle", $hCanvas, "handle", $hPen3, "float", 0, "float", ($iH - $__g_iBorder) - 2, "float", $__g_iBorder + 1, "float", $__g_iBorder + 1) DllCall($__g_hGDIPDll, "int", "GdipFillRectangle", "handle", $hCanvas, "handle", $hBrush, "float", ($iW - $__g_iBorder) / 2, "float", ($iH - $__g_iBorder) - 2, "float", $__g_iBorder + 1, "float", $__g_iBorder + 1) DllCall($__g_hGDIPDll, "int", "GdipDrawRectangle", "handle", $hCanvas, "handle", $hPen3, "float", ($iW - $__g_iBorder) / 2, "float", ($iH - $__g_iBorder) - 2, "float", $__g_iBorder + 1, "float", $__g_iBorder + 1) DllCall($__g_hGDIPDll, "int", "GdipFillRectangle", "handle", $hCanvas, "handle", $hBrush, "float", ($iW - $__g_iBorder) - 2, "float", ($iH - $__g_iBorder) - 2, "float", $__g_iBorder + 1, "float", $__g_iBorder + 1) DllCall($__g_hGDIPDll, "int", "GdipDrawRectangle", "handle", $hCanvas, "handle", $hPen3, "float", ($iW - $__g_iBorder) - 2, "float", ($iH - $__g_iBorder) - 2, "float", $__g_iBorder + 1, "float", $__g_iBorder + 1) _WinAPI_BitBlt($hDC, 0, 0, $iW, $iH, $hDC_backbuffer, 0, 0, $SRCCOPY) $fOffset += 0.5 _GDIPlus_GraphicsDispose($hCanvas) _WinAPI_SelectObject($hDC_backbuffer, $DC_obj) _WinAPI_DeleteDC($hDC_backbuffer) _WinAPI_DeleteObject($hHBitmap) _WinAPI_ReleaseDC($__g_hGUI_MarkArea, $hDC) _GDIPlus_PenDispose($hPen) _GDIPlus_PenDispose($hPen2) _GDIPlus_PenDispose($hPen3) _GDIPlus_BrushDispose($hBrush) EndFunc ;==>PlayBorderAnim Func WM_ERASEBKGND($hWnd, $iMsgm, $wParam, $lParam) ;suppress repainting to avoid flickering but causes some other side effects #forceref $iMsgm, $wParam, $lParam, $hWnd Local Const $hBrush = _WinAPI_CreateSolidBrush(0xEFCDAB) ;BGR format ;~ _WinAPI_RedrawWindow($__g_hGUI_MarkArea, 0, 0, BitOR($RDW_NOERASE, $RDW_NOCHILDREN, $RDW_NOFRAME, $RDW_VALIDATE)) _WinAPI_SetClassLongEx($__g_hGUI_MarkArea, $GCL_HBRBACKGROUND, $hBrush) _WinAPI_DeleteObject($hBrush) Return 0 EndFunc ;==>WM_ERASEBKGND ;https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-setprocessdpiawarenesscontext Func _WinAPI_SetProcessDpiAwarenessContext($DPIAwareContext = $Context_PerMonitorAware, $hGUI = 0, $iMode = 3) ;https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-setprocessdpiawarenesscontext $DPIAwareContext = ($DPIAwareContext < -5) ? -5 : ($DPIAwareContext > -1) ? -1 : $DPIAwareContext $iMode = ($iMode < 1) ? 1 : ($iMode > 3) ? 3 : $iMode Switch $iMode Case 1 Local $hDC = _WinAPI_GetDC($hGUI) Local $aResult1 = DllCall("user32.dll", "ptr", "GetDpiFromDpiAwarenessContext", "ptr", $hDC) If @error Or Not IsArray($aResult1) Then Return SetError(11, 0, 0) _WinAPI_ReleaseDC(0, $hDC) Local $aResult = DllCall("user32.dll", "Bool", "SetProcessDpiAwarenessContext", "int", $aResult1[0] + $DPIAwareContext) If @error Or Not IsArray($aResult) Then Return SetError(12, 0, 0) Case 2 ;~ If Not $hGUI Then $hGUI = WinGetHandle(AutoItWinGetTitle()) Local $aResult2 = DllCall("user32.dll", "int", "GetWindowDpiAwarenessContext", "ptr", $hGUI) If @error Or Not IsArray($aResult2) Then Return SetError(21, 0, 0) Local $aResult = DllCall("user32.dll", "Bool", "SetProcessDpiAwarenessContext", "int", $aResult2[0] + $DPIAwareContext) If @error Or Not IsArray($aResult) Then Return SetError(22, 0, 0) Case 3 Local $aResult31 = DllCall("user32.dll", "ptr", "GetThreadDpiAwarenessContext") If @error Or Not IsArray($aResult31) Then Return SetError(31, 0, 0) Local $aResult32 = DllCall("user32.dll", "ptr", "GetAwarenessFromDpiAwarenessContext", "ptr", $aResult31[0]) If @error Or Not IsArray($aResult32) Then Return SetError(32, 0, 0) Local $aResult = DllCall("user32.dll", "Bool", "SetThreadDpiAwarenessContext", "int", $aResult32[0] + $DPIAwareContext) If @error Or Not IsArray($aResult) Then Return SetError(33, 0, 0) EndSwitch Return 1 EndFunc ;==>_WinAPI_SetProcessDpiAwarenessContext  
      Just press the lmb and move your mouse. When lmb is released you can adjust the size of the window by dragging the white rectangle to any direction. Rmb will move the marked area.
      Press ESC to get the coordinates of the marked region.
      If you have any improvements, please post it here.
       
      Tested on Win10 x64 only.
       
    • By UEZ
      This project has been discontinued!
       
      Here a small tool I wrote to update my Sysinternal tools collection without the need to download always the whole package or visiting the site to check for updates. I know that there are several tools available (also some tools written in AutoIt) but here another one for the collection. It was good exercise for me to code it.
       
       
        
       
       
      Some files from cannot be downloaded although they are visible on the web site!
       
      Here the download link of the source code only: AutoIt Sysinternal Tools Synchronizer v0.99.5 build 2020-07-04 beta.7z  (1509 downloads previously)
      -=> Requires AutoIt version 3.3.13.20 or higher / tested on Win8.1 real machine and some VMs: Win7 / Vista / Win10
       
      Compiled exe only: @MediaFire
       
      Just select the Sysinternal Tools folder or create one and press the synchronize button to download the selected items. Click on AutoIt label (near to left upper corner) to open menu.
       
      Special thanks to LarsJ, Melba23 and mesale0077 for their help. 
       
      I've still some ideas to implement which are more gimmick related, so it is not finished yet...
      If you want to add your language please check out #Region Language. Thanks. 
       
      Please report any bug or if you have any suggestions.
       
      The language of the tool tip from each of the executable in the left list view were automatically created using Google translator and weren't checked for correctness.
       
      Br,
      UEZ
    • By UEZ
      I was inspired by a CSS example to create a procedural graphic without any shader or ray tracing technique.
      Here the result using GDI+ only:

       
      Blue Orb.au3
      ;Inspired from https://codepen.io/bradleytaunt/details/VwvzKyb ;Coded by UEZ build 2020-05-07 #include <GDIPlus.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> If @OSBuild < 7600 Then Exit MsgBox(BitOR($MB_TOPMOST, $MB_ICONERROR), "ERROR", "This demo requires GDIPlus v1.1", 10) _GDIPlus_Startup() Global Const $iW = 1200, $iH = 700, $iSize_globe = 450 Global Const $hGUI = GUICreate("GDI+ Procedural Gfx / Blue Orb v1.20 by UEZ", $iW, $iH, -1, -1, $WS_POPUP, $WS_EX_TOPMOST) Global Const $hCanvas = _GDIPlus_GraphicsCreateFromHWND($hGUI) Global Const $hImage = _GDIPlus_BitmapCreateFromScan0($iW, $iH) Global Const $hGfx = _GDIPlus_ImageGetGraphicsContext($hImage) _GDIPlus_GraphicsSetSmoothingMode($hGfx, $GDIP_SMOOTHINGMODE_ANTIALIAS8X8) ;~ _GDIPlus_GraphicsSetCompositingQuality($hGfx, $GDIP_COMPOSITINGQUALITYHIGHQUALITY) _GDIPlus_GraphicsSetInterpolationMode($hGfx, $GDIP_INTERPOLATIONMODE_HIGHQUALITYBICUBIC) _GDIPlus_GraphicsSetPixelOffsetMode($hGfx, $GDIP_PIXELOFFSETMODE_HALF) ;draw background Global Const $hBrush_bg = _GDIPlus_LineBrushCreate($iW / 2, 0, $iW / 2, $iH / 2, 0xFF1E88E5, 0xFF1565C0, 2) _GDIPlus_LineBrushSetSigmaBlend ($hBrush_bg, 0.95, 1) ;create blurry edge _GDIPlus_GraphicsFillRect($hGfx, 0, 0, $iW, $iH, $hBrush_bg) ;draw blurred text Global Const $hImage_text = _GDIPlus_BitmapCreateFromScan0($iW, $iH / 2) Global Const $hGfx_text = _GDIPlus_ImageGetGraphicsContext($hImage_text) Global Const $hPath_text = _GDIPlus_PathCreate() Global Const $hFamily = _GDIPlus_FontFamilyCreate("Impact") Global Const $hStringFormat = _GDIPlus_StringFormatCreate() Global Const $hBrush_txt = _GDIPlus_LineBrushCreate($iW / 2, 0, $iW / 2, $iH / 2, 0xE0FFFFFF, 0xA01A237E) ;_GDIPlus_BrushCreateSolid(0xF02E86FB) _GDIPlus_LineBrushSetSigmaBlend($hBrush_txt, 0.66, 1) Global Const $hPen_txt = _GDIPlus_PenCreate(0x801A237E, 1) _GDIPlus_StringFormatSetAlign($hStringFormat, 1) _GDIPlus_StringFormatSetLineAlign($hStringFormat, 1) _GDIPlus_GraphicsSetSmoothingMode($hGfx_text, $GDIP_SMOOTHINGMODE_ANTIALIAS8X8) _GDIPlus_GraphicsSetTextRenderingHint($hGfx_text, $GDIP_TextRenderingHintAntialias) _GDIPlus_GraphicsSetPixelOffsetMode($hGfx_text, $GDIP_PIXELOFFSETMODE_HALF) _GDIPlus_GraphicsSetCompositingQuality($hGfx_text, $GDIP_COMPOSITINGQUALITYHIGHQUALITY) Global $tLayout = _GDIPlus_RectFCreate() $tLayout.width = $iW $tLayout.height = $iH / 2 $tLayout.y = -$iH * 0.05 _GDIPlus_PathAddString($hPath_text, "AutoIt rulez!", $tLayout, $hFamily, 0, $iW / 8, $hStringFormat) _GDIPlus_GraphicsFillPath($hGfx_text, $hPath_text, $hBrush_txt) _GDIPlus_GraphicsDrawPath($hGfx_text, $hPath_text, $hPen_txt) Global Const $hEffect_blur_text = _GDIPlus_EffectCreateBlur(20) _GDIPlus_BitmapApplyEffect($hImage_text, $hEffect_blur_text) _GDIPlus_GraphicsDrawImageRect($hGfx, $hImage_text, 0, 0, $iW, $iH / 2) ;draw shadow of the text Global Const $hBrush_txt_shadow = _GDIPlus_BrushCreateSolid(0x40000000) _GDIPlus_GraphicsClear($hGfx_text, 0) _GDIPlus_PathReset($hPath_text) $tLayout.width = $iW $tLayout.height = $iH / 2 $tLayout.y = 0 _GDIPlus_PathAddString($hPath_text, "AutoIt rulez!", $tLayout, $hFamily, 0, $iW / 8, $hStringFormat) _GDIPlus_GraphicsFillPath($hGfx_text, $hPath_text, $hBrush_txt_shadow) Global Const $hEffect_blur_text_shadow = _GDIPlus_EffectCreateBlur(60) _GDIPlus_BitmapApplyEffect($hImage_text, $hEffect_blur_text_shadow) _GDIPlus_GraphicsDrawImageRect($hGfx, $hImage_text, 0, $iH * 0.55, $iW, $iH / 8) ;draw shadow Global Const $iW_shadow1 = $iSize_globe * 0.85, $iH_shadow1 = $iSize_globe * 0.1, $iW_shadow2 = $iSize_globe * 0.60, _ $iW_shadow_Img = $iW_shadow1 * 2, $iH_shadowImg = $iH_shadow1 * 4 Global Const $hImage_shadow = _GDIPlus_BitmapCreateFromScan0($iW_shadow_Img, $iH_shadowImg) Global Const $hGfx_shadow = _GDIPlus_ImageGetGraphicsContext($hImage_shadow) _GDIPlus_GraphicsSetSmoothingMode($hGfx_shadow, $GDIP_SMOOTHINGMODE_ANTIALIAS8X8) Global Const $hBrush_shadow = _GDIPlus_BrushCreateSolid(0x66000000) _GDIPlus_GraphicsFillEllipse($hGfx_shadow, ($iW_shadow_Img - $iW_shadow1) / 2, ($iH_shadowImg / 4 + $iH_shadow1), $iW_shadow1, $iH_shadow1, $hBrush_shadow) _GDIPlus_BrushSetSolidColor($hBrush_shadow, 0xB3000000) _GDIPlus_GraphicsFillEllipse($hGfx_shadow, ($iW_shadow_Img - $iW_shadow2) / 2, ($iH_shadowImg / 4 + $iH_shadow1), $iW_shadow2, $iH_shadow1, $hBrush_shadow) Global Const $hEffect_blur_shadow = _GDIPlus_EffectCreateBlur(32) _GDIPlus_BitmapApplyEffect($hImage_shadow, $hEffect_blur_shadow) _GDIPlus_GraphicsDrawImageRect($hGfx, $hImage_shadow, ($iW - $iW_shadow_Img) / 2, $iH / 2 + $iH_shadow1 * 2.20, $iW_shadow_Img, $iH_shadowImg) ;draw globe Global Const $hPath_globe = _GDIPlus_PathCreate() _GDIPlus_PathAddEllipse($hPath_globe, ($iW - $iSize_globe) / 2, ($iH - $iSize_globe) / 2, $iSize_globe, $iSize_globe) Global Const $hLBrush_globe1 = _GDIPlus_LineBrushCreate($iW / 2, ($iH - $iSize_globe) / 2, $iW / 2, ($iH + $iSize_globe) / 2, 0, 0, 1) Global $aInterpolations[5][2] $aInterpolations[0][0] = 4 $aInterpolations[1][0] = 0xFFFFFFFF $aInterpolations[1][1] = 0 $aInterpolations[2][0] = 0xFFEEEEEE $aInterpolations[2][1] = 0.10 $aInterpolations[3][0] = 0xFF2E86FB $aInterpolations[3][1] = 0.50 $aInterpolations[4][0] = 0xFF1A237E $aInterpolations[4][1] = 1.0 _GDIPlus_LineBrushSetPresetBlend($hLBrush_globe1, $aInterpolations) _GDIPlus_GraphicsFillPath($hGfx, $hPath_globe, $hLBrush_globe1) Global Const $iSize_globe2 = $iSize_globe * 0.85, $iSize_globe2_Img = $iSize_globe2 * 1.5 Global Const $hImage_globe2 = _GDIPlus_BitmapCreateFromScan0($iSize_globe2_Img, $iSize_globe2_Img) Global Const $hGfx_globe2 = _GDIPlus_ImageGetGraphicsContext($hImage_globe2) Global Const $hBrush_globe2 = _GDIPlus_BrushCreateSolid(0x7F000000) ;draw shadow and blur it Global Const $px = ($iSize_globe2_Img - $iSize_globe2) / 2, $py = ($iSize_globe2_Img - $iSize_globe2) / 2 _GDIPlus_GraphicsFillEllipse($hGfx_globe2, $px, $py + ($iSize_globe - $iSize_globe2) * 0.25, $iSize_globe2, $iSize_globe2, $hBrush_globe2) Global Const $hEffect_blur_shadow2 = _GDIPlus_EffectCreateBlur(15) _GDIPlus_BitmapApplyEffect($hImage_globe2, $hEffect_blur_shadow2) ;draw 2nd smaller globe and blur it, too Global Const $hLBrush_globe2 = _GDIPlus_LineBrushCreate($iW / 2, $py, $iW / 2, $py + $iSize_globe2, 0, 0) Dim $aInterpolations[4][2] $aInterpolations[0][0] = 3 $aInterpolations[1][0] = 0xFFFFFFFF $aInterpolations[1][1] = 0 $aInterpolations[2][0] = 0xFF2E86FB $aInterpolations[2][1] = 0.60 $aInterpolations[3][0] = 0xFF283593 $aInterpolations[3][1] = 1.0 _GDIPlus_LineBrushSetPresetBlend($hLBrush_globe2, $aInterpolations) _GDIPlus_GraphicsFillEllipse($hGfx_globe2, $px, $py, $iSize_globe2, $iSize_globe2, $hLBrush_globe2) Global Const $hImage_globe2_blur = _Blur($hImage_globe2, $iSize_globe, $iSize_globe) ;windows gdi+ blur doesn't work properly _GDIPlus_GraphicsDrawImageRect($hGfx, $hImage_globe2_blur, ($iW - $iSize_globe2_Img) / 2 - ($iSize_globe - $iSize_globe2) / 8, ($iH - $iSize_globe2_Img) / 2, $iSize_globe2_Img, $iSize_globe2_Img) GUISetState() _GDIPlus_GraphicsDrawImageRect($hCanvas, $hImage, 0, 0, $iW, $iH) ;~ _GDIPlus_ImageSaveToFile($hImage, @ScriptDir & "\Blue Orb v1.20.png") ;clean-up ressources _GDIPlus_FontFamilyDispose($hFamily) _GDIPlus_StringFormatDispose($hStringFormat) _GDIPlus_EffectDispose($hEffect_blur_text) _GDIPlus_EffectDispose($hEffect_blur_text_shadow) _GDIPlus_EffectDispose($hEffect_blur_shadow) _GDIPlus_EffectDispose($hEffect_blur_shadow2) _GDIPlus_PathDispose($hPath_text) _GDIPlus_PathDispose($hPath_globe) _GDIPlus_PenDispose($hPen_txt) _GDIPlus_BrushDispose($hBrush_txt) _GDIPlus_BrushDispose($hBrush_txt_shadow) _GDIPlus_BrushDispose($hBrush_bg) _GDIPlus_BrushDispose($hLBrush_globe1) _GDIPlus_BrushDispose($hLBrush_globe2) _GDIPlus_BrushDispose($hBrush_globe2) _GDIPlus_ImageDispose($hImage) _GDIPlus_ImageDispose($hImage_text) _GDIPlus_ImageDispose($hImage_shadow) _GDIPlus_ImageDispose($hImage_globe2) _GDIPlus_ImageDispose($hImage_globe2_blur) _GDIPlus_GraphicsDispose($hCanvas) _GDIPlus_GraphicsDispose($hGfx_text) _GDIPlus_GraphicsDispose($hGfx_shadow) _GDIPlus_GraphicsDispose($hGfx_globe2) _GDIPlus_Shutdown() Do Until GUIGetMsg() = $GUI_EVENT_CLOSE GUIDelete($hGUI) Exit Func _Blur($hBitmap, $iW, $iH, $fScale = 0.0525, $dx1 = 0, $dy1 = 0, $dx2 = 0, $dy2 = 0, $qual = 6) ; by eukalyptus Local $hBmpSmall = _GDIPlus_BitmapCreateFromScan0($iW, $iH) Local $hGfxSmall = _GDIPlus_ImageGetGraphicsContext($hBmpSmall) _GDIPlus_GraphicsSetPixelOffsetMode($hGfxSmall, $GDIP_PIXELOFFSETMODE_HALF) Local $hBmpBig = _GDIPlus_BitmapCreateFromScan0($iW, $iH) Local $hGfxBig = _GDIPlus_ImageGetGraphicsContext($hBmpBig) _GDIPlus_GraphicsSetPixelOffsetMode($hGfxBig, $GDIP_PIXELOFFSETMODE_HALF) _GDIPlus_GraphicsScaleTransform($hGfxSmall, $fScale, $fScale) _GDIPlus_GraphicsSetInterpolationMode($hGfxSmall, $qual) _GDIPlus_GraphicsScaleTransform($hGfxBig, 1 / $fScale, 1 / $fScale) _GDIPlus_GraphicsSetInterpolationMode($hGfxBig, $qual) _GDIPlus_GraphicsDrawImageRect($hGfxSmall, $hBitmap, 0, $dx1, $iW, $iH + $dy1) _GDIPlus_GraphicsDrawImageRect($hGfxBig, $hBmpSmall, 0, $dx2, $iW, $iH + $dy2) _GDIPlus_BitmapDispose($hBmpSmall) _GDIPlus_GraphicsDispose($hGfxSmall) _GDIPlus_GraphicsDispose($hGfxBig) Return $hBmpBig EndFunc ;==>_Blur  
      I hope you like it.
       
      Feel free to post your examples here, too. 
    • 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 (10489 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
      😄 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:
       


    • 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.
×
×
  • Create New...