GDI + viel zu langsam ..

  • Abend,

    ich habe mal mit GDI + eine Progressbar erstellt und mir ist dabei aufgefallen, dass es sehr langsam ist. Normal ist dies auf jeden Fall nicht.

    Weiß jemand vielleicht wie ich die Geschwindigkeit ankurbeln kann?

    Skript :

    Spoiler anzeigen
    [autoit]

    #include <GUIConstantsEx.au3>
    #include <StaticConstants.au3>
    #include <WindowsConstants.au3>
    #Include <GDIPlus.au3>
    $hGUI1 = GUICreate("Form1", 396, 56, 192, 124)
    $Pic1 = GUICtrlCreatePic("", 8, 8, 372, 36)
    GUISetState(@SW_SHOW)
    _GDIPlus_Startup ()
    $hImage = _GDIPlus_ImageLoadFromFile ("C:\Users\Benutzer\Documents\Jellyfish.jpg")
    $hGraphic1 = _GDIPlus_GraphicsCreateFromHWND ($hGUI1)
    $hImage2 = _GDIPlus_ImageLoadFromFile ("C:\Users\Benutzer\Documents\Prog.jpg")
    $hGraphic2 = _GDIPlus_GraphicsCreateFromHWND ($hGUI1)
    _GDIPlus_GraphicsDrawImageRect($hGraphic2, $hImage2, 0, 0 ,360,60)
    For $i = 1 to 396
    _GDIPlus_GraphicsDrawImageRect($hGraphic1, $hImage, 0, 0 ,$i,60)
    Next
    _GDIPlus_Shutdown ()

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
    Case $GUI_EVENT_CLOSE
    Exit

    [/autoit] [autoit][/autoit] [autoit]

    EndSwitch
    WEnd

    [/autoit]
  • Wozu benötigst du bitte 2 Grafiken vom sleben Fenster? 8| ...

    Zitat

    Normal ist dies auf jeden Fall nicht.


    Doch. Das ist völlig normal bei solch ineffizienter Programmierung...
    Erstens benötigt die Interpolation von Bildern bei Skalierung, je nach Interpolationsmodus, enorm viel Zeit. Und da du nicht z.B. das Bild in der benötigten Größe zwischenspeicherst o.Ä. Dauert das möglicherweise sehr lange.

  • Was meinst du denn mit zwischenspeichern? Das Bild wird doch sowieso nur 1x geladen und danach wird es zwischengespeichert und ich kann es immer zeichnen oder ?

  • Das Bild wird einmal in voller Größe in den Arbeitsspeicher geladen und dann in unterschiedliche Größen skaliert. Dabei wird ein Interpolationsmodus angewendet und der macht dein Script langsam (und das Bild hübsch).
    Abgesehen davon ist das längst nicht das einzige Problem in deinem Script.. Es werden z.B. keinerlei Ressourcen bei Scriptende aus dem Arbeitsspeicher entfernt und 2 Grafik Objekte brauchst du auch nicht, das macht gar keinen Sinn.

  • Normalerweise möchte ich das Bild nur als Progressbar benutzen und das eine Bild ist der Hintergrund.
    Nun möchte ich es so, dass es am Besten nur 1% gezeichnet wird und nicht das gesamte Bild skaliert wird, aber mir fällt dazu einfach keine Lösung ein. Das 2 te Bild soll nachher von mir auch noch erneut gezeichnet werden, nachdem ich GraphicsClear verwendet habe und das alles beginnt wieder von vorne, aber keiner kann mir bei der Geschichte helfen ;/

  • Okay. ;)

    So ?

    Spoiler anzeigen
    [autoit]

    #include <GUIConstantsEx.au3>
    #include <StaticConstants.au3>
    #include <WindowsConstants.au3>
    #Include <GDIPlus.au3>
    $hGUI1 = GUICreate("Form1", 396, 56, 192, 124)
    GUISetState(@SW_SHOW)
    _GDIPlus_Startup ()
    $hImage = _GDIPlus_ImageLoadFromFile ("C:\Users\Benutzer\Documents\Jellyfish.jpg") ; Bild, welches als Progressbar benutzt werden soll
    $hImage2 = _GDIPlus_ImageLoadFromFile ("C:\Users\Benutzer\Documents\Prog.jpg") ; Hintergrundbild, auf dem die Progressbar benutzt werden soll
    $hGraphic1 = _GDIPlus_GraphicsCreateFromHWND ($hGUI1)
    _GDIPlus_GraphicsDrawImageRect($hGraphic1, $hImage2, 0, 0 ,360,60)
    For $i = 1 to 396
    _GDIPlus_GraphicsDrawImageRect($hGraphic1, $hImage, 0, 0 ,$i,60)
    Next
    _GDIPlus_Shutdown ()

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    While 1
    $nMsg = GUIGetMsg()
    If $nMsg = $GUI_EVENT_CLOSE Then Exit
    WEnd

    [/autoit]

    Muss nun erstmal weg, da ich noch eine Verabredung habe, falls es so nicht vernünftig aufgeräumt ist, werde ich es nachher machen.

  • Hi,

    Du solltest nur den Bereich neu zeichnen, der auch wirklich nur neu gezeichnet werden muss.
    In Deiner Schleife fängst Du immer wieder bei x=0 an, das ist unnötig und macht es so langsam.

    Und halte Dich an die Dokumentation der Funktionen, bzgl. der Ressourcen.
    Also immer schön wieder freigeben was angefordert wurde, wenn Du es nicht mehr brauchst, so wie name22 es schon angedeutet hat.
    Verlasse Dich nicht auf AutoIt oder das OS, wegen der Aufräumarbeiten.


    Gruß
    Greenhorn


  • So...

    Spoiler anzeigen
    [autoit]

    #include <GUIConstantsEx.au3>
    #include <WindowsConstants.au3>
    #Include <GDIPlus.au3>

    [/autoit] [autoit][/autoit] [autoit]

    $hGUI = GUICreate("Form1", 360, 60, 129, 124)
    GUISetState(@SW_SHOW)

    [/autoit] [autoit][/autoit] [autoit]

    _GDIPlus_Startup ()

    [/autoit] [autoit][/autoit] [autoit]

    $hGraphic = _GDIPlus_GraphicsCreateFromHWND ($hGUI)
    _GDIPlus_GraphicsSetSmoothingMode($hGraphic, 2)

    [/autoit] [autoit][/autoit] [autoit]

    $hImageProgress = _GDIPlus_ImageLoadFromFile ("C:\Users\Torge\Documents\Jellyfish.jpg") ; Bild, welches als Progressbar benutzt werden soll
    $hImageBG = _GDIPlus_ImageLoadFromFile ("C:\Users\Torge\Documents\Prog.jpg") ; Hintergrundbild, auf dem die Progressbar benutzt werden soll

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 1 to 360
    _GDIPlus_GraphicsSetClipRect($hGraphic, 0, 0, $i, 60) ;Begrenzt den Zeichenbereich der Grafik auf das angegebene Rechteck
    _GDIPlus_GraphicsDrawImageRect($hGraphic, $hImageBG, 0, 0, 360, 60)
    _GDIPlus_GraphicsDrawImageRect($hGraphic, $hImageProgress, 0, 0, 360, 60)
    Next

    [/autoit] [autoit][/autoit] [autoit]

    OnAutoItExitRegister("_Shutdown") ;Führt _Shutdown vor dem beenden des Scripts aus.

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    Switch GUIGetMsg()
    Case $GUI_EVENT_CLOSE
    Exit
    EndSwitch
    WEnd

    [/autoit] [autoit][/autoit] [autoit]

    Func _Shutdown()
    _GDIPlus_GraphicsDispose($hGraphic) ;Grafik Objekt löschen
    _GDIPlus_ImageDispose($hImageProgress) ;Bild löschen
    _GDIPlus_ImageDispose($hImageBG) ;Bild löschen
    _GDIPlus_Shutdown() ;Standard Ressourcen löschen und DLL Handle schließen.
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    ;GDIP.au3 Funcion:
    Func _GDIPlus_GraphicsSetClipRect($hGraphics, $nX, $nY, $nWidth, $nHeight, $iCombineMode = 0)
    Local $aResult = DllCall($ghGDIPDll, "uint", "GdipSetClipRect", "hwnd", $hGraphics, "float", $nX, "float", $nY, "float", $nWidth, "float", $nHeight, "int", $iCombineMode)

    [/autoit] [autoit][/autoit] [autoit]

    If @error Then Return SetError(@error, @extended, False)
    $GDIP_STATUS = $aResult[0]
    Return $aResult[0] = 0
    EndFunc ;==>_GDIPlus_GraphicsSetClipRect

    [/autoit]


    Das ist zwar immer noch nicht besonders gut, aber es sollte korrekt funktionieren. Wenn dein bild flackern sollte musst du noch einen Backbuffer einbauen (dazu gibt es ein Tutorial im Forum "GDI+ Tutorial").
    Wenn du dann noch das beachtest was Greenhorn gepostet hat, könnte daraus sogar noch was werden. Dein Bild sollte übrigens die Maße 360x60 Pixel haben (exakt). Sonst bringt das hier keinen Geschwindigkeitsvorteil.