_GDIPlus_BitmapLoadFromFile spezifische Größe

  • Hi com,

    hier mal wieder was von mir, nur eine Kleinigkeit. Damit ist es möglich, ein Bild zu laden (GDIPlus) und ihm eine spezifische Größe zu geben. Nach wunsch können Verhältnisse eingehalten werden. Genaueres steht im Beispiel.
    Viel Spaß damit ;)

    Spoiler anzeigen
    [autoit]

    #cs Kommentar:
    Diese Funktion läd euch ein Bild wie _GDIPlus_BitmapCreateFromFile in ein Bitmapobjekt, nur dass ihr
    bestimmen könnt, welche Größe es hat. Anpassungsfähigkeit ist gegeben.
    Der Zweck besteht darin, dass ein großes Bild nicht ständig wieder kleiner gezeichnet werden muss, was Vorteile hat,
    besonders bei Performence. In meinem Test hatte ich statt 22-30ms nurnoch 6-10ms Zeichenzeit.
    Viel Spaß damit ;)
    PS: Wer will kann diese Funktion auch _GDIPlus_BitmapLoadSpecialSize nennen.
    #ce
    #include <GDIPlus.au3> ; benötigt
    $hWnd = GUICreate("Beispiel Bitmap Laden", 600, 400)
    GUISetState(@SW_SHOW)
    _GDIPlus_StartUp()
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWnd)
    $sPath = FileOpenDialog("Bild auswählen", @MyDocumentsDir, "(*.jpg;*.bmp;*.gif;*.png)")
    $hTime = TimerInit()
    $hBitmap = _GDIPlus_BitmapLoadFromFile($sPath, 600, 400) ; Es wird automatisch angepasst, das angegebene Rechteck wird nicht überschritten
    ; Um eine feste Höhe anzulegen, setzt ihr die Weite auf -1 (anpassen), für eine feste Weite die Höhe auf -1
    WinSetTitle("Beispiel Bitmap Laden", "", Round(TimerDiff($hTime), 2) & "ms zum Laden benötigt")
    _GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap, 0, 0, _GDIPlus_ImageGetWidth($hBitmap), _GDIPlus_ImageGetHeight($hBitmap))
    While 1 * Sleep(30)
    If GUIGetMsg() = -3 Then ExitLoop
    WEnd
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_Shutdown()
    GUIDelete($hWnd)
    Exit

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

    ; #FUNCTION# ====================================================================================================================
    ; Name...........: _GDIPlus_BitmapLoadFromFile
    ; Description ...: Erstellt ein Bitmapobjekt mit einer Spezifischen Größe
    ; Syntax.........: _GDIPlus_BitmapLoadFromFile($s_Path[, $i_Widht[, $i_Height[, $i_Opt]]])
    ; Parameters ....: $s_Path - Pfad der Bilddatei
    ; $i_Widht - Weite des Bitmapobjektes (-1 = der Höhe im Verhältnis anpassen)
    ; $i_Height - Höhe des Bitmapobjektes (-1 = der Weite im Verhältnis anpassen)
    ; $i_Opt - (optional) Verhältnisse automatisch ausrichten (1=Ja/0=Nein; Standart 1)
    ; Return values .: Sucess - Bitmapobjekt mit dem geladenen Bild
    ; Failure - 0 und setzt @error auf
    ; |1 - Dateipfad ungültig
    ; |2 - Option falsch gesetzt
    ; Author ........: black_skorpi (@autoit.de)
    ; Example .......: Yes
    ; ===============================================================================================================================
    Func _GDIPlus_BitmapLoadFromFile($s_Path, $i_Widht, $i_Height, $i_Opt = 1)
    If (($i_Opt <> 0) And ($i_Opt <> 1)) Or (($i_Widht < 0) And ($i_Height < 0)) Then SetError(2, 0, 0)
    Local $h_Image = _GDIPlus_ImageLoadFromFile($s_Path), $s_ExY = "$i_Widht", $s_ExX = "$i_Height"
    If @error Then Return SetError(1, 0, 0)
    Local $a_Verh[3] = [_GDIPlus_ImageGetHeight($h_Image),_GDIPlus_ImageGetWidth($h_Image),_GDIPlus_ImageGetHeight($h_Image) / _GDIPlus_ImageGetWidth($h_Image)]
    If $i_Opt = 1 Then
    If $a_Verh[2] < 1 Then
    $i_Height = -1
    ElseIf $a_Verh[2] > 1 Then
    $i_Widht = -1
    ElseIf $a_Verh[2] = 1 Then
    If $i_Widht > $i_Height Then
    $i_Widht = $i_Height
    Else
    $i_Height = $i_Widht
    EndIf
    EndIf
    EndIf
    Switch -1
    Case $i_Height
    $s_ExX = "$i_Widht * $a_Verh[2]"
    Case $i_Widht
    $s_ExY = "$i_Height / $a_Verh[2]"
    EndSwitch
    Local $h_Graphic = _GDIPlus_GraphicsCreateFromHWND(DllCall("user32.dll", "hwnd", "GetDesktopWindow"))
    Local $h_Bitmap = _GDIPlus_BitmapCreateFromGraphics(Execute($s_ExY), Execute($s_ExX), $h_Graphic), $h_Buffer = _GDIPlus_ImageGetGraphicsContext($h_Bitmap)
    _GDIPlus_GraphicsSetSmoothingMode($h_Buffer, 2)
    DllCall($ghGDIPDll, "int", "GdipSetInterpolationMode", "handle", $h_Buffer, "int", 7)
    _GDIPlus_GraphicsDrawImageRectRect($h_Buffer, $h_Image, 0, 0, $a_Verh[1], $a_Verh[0], 0, 0, Execute($s_ExY), Execute($s_ExX))
    _GDIPlus_GraphicsDispose($h_Graphic)
    _GDIPlus_GraphicsDispose($h_Buffer)
    _GDIPlus_ImageDispose($h_Image)
    Return $h_Bitmap
    EndFunc ;==>_GDIPlus_BitmapLoadFromFile

    [/autoit]

    PS: Die Performence kann extrem verbessert werden!!

    Edit2: Code überarbeitet (mit e's Vorschlag) und gekürzt, Funktion nun um 2-5ms schneller
    Edit3: Parameter leicht verändert, Funktion nurnoch an den Desktop gebunden (nicht mehr an ein GUI)
    Edit4: Bug mit quadratischen Bildern gefixxt. Nun sollte alles prima laufen.
    Edit5: Wieder minimal abgeändert, Problem mit überdimensionalen Bildern entdeckt (ich habs mit 6000x6000 getestet, Grund unbekannt)

  • Nein, brauchst du nicht!

    Spoiler anzeigen
    [autoit]

    #cs Kommentar:
    Der Quelltext geht sicherlich kürzer, allerdings habe ich jetzt keine lust, ihn zu überarbeiten
    Wenn Zeit da ist, werde ich dies villt. machen
    Diese Funktion läd euch ein Bild wie _GDIPlus_BitmapCreateFromFile in ein Bitmapobjekt, nur dass ihr
    bestimmen könnt, welche Größe es hat. Anpassungsfähigkeit ist gegeben.
    Der Zweck besteht darin, dass ein großes Bild nicht ständig wieder kleiner gezeichnet werden muss, was Vorteile hat,
    besonders bei Performence. In meinem Test hatte ich statt 22-30ms nurnoch 6-10ms Zeichenzeit.
    Viel Spaß damit ;)
    #ce
    #include <GDIPlus.au3>
    _GDIPlus_StartUp()
    $hWnd = GUICreate("Beispiel Bitmap Laden", 200, 200)
    GUISetState(@SW_SHOW)
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($hWnd)
    $sPath = FileOpenDialog("Bild auswählen", @MyDocumentsDir, "(*.jpg)|(*.bmp)|(*.gif)|(*.png)")
    $hTime = TimerInit()
    $hBitmap = _GDIPlus_BitmapLoadFromFile($sPath, 200, 200, 1) ; es wird automatisch passen
    ; um eine feste höhe anzulegen, nehmt als letzte parameter 2 und "height", für eine feste weite einfach 2 und "widht"
    WinSetTitle("Beispiel Bitmap Laden", "", Round(TimerDiff($hTime), 2) & "ms zum Laden benötigt")
    _GDIPlus_GraphicsDrawImageRect($hGraphic, $hBitmap, 0, 0, _GDIPlus_ImageGetWidth($hBitmap), _GDIPlus_ImageGetHeight($hBitmap))
    Sleep(3000)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_Shutdown()
    GUIDelete($hWnd)
    Exit

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

    ; #FUNCTION# ====================================================================================================================
    ; Name...........: _GDIPlus_BitmapLoadFromFile
    ; Description ...: Erstellt ein Bitmapobjekt mit einer Spezifischen Größe
    ; Syntax.........: _GDIPlus_BitmapLoadFromFile($s_Path[, $i_Widht[, $i_Height[, $i_Opt]]])
    ; Parameters ....: $s_Path - Pfad der Bilddatei
    ; $i_Widht - Weite des Bitmapobjektes
    ; $i_Height - Höhe des Bitmapobjektes
    ; $i_Opt - (optional) Verhältnisse anpassen, falls gewollt (0=Nein/1=Ja/2=Fortgeschritten ; Standart = 0)
    ; Return values .: Sucess - Bitmapobjekt mit dem geladenen Bild
    ; Failure - 0 und setzt @error auf
    ; |1 - Dateipfad ungültig
    ; |2 - Option falsch gesetzt
    ; Author ........: black_skorpi (@autoit.de)
    ; Example .......: Yes
    ; ===============================================================================================================================
    Func _GDIPlus_BitmapLoadFromFile($s_Path, $i_Widht, $i_Height, $i_Opt = 0, $s_Opt = "")
    Local $hWnd=_WinAPI_GetDesktopWindow()
    Local $h_Image = _GDIPlus_ImageLoadFromFile($s_Path)
    If @error Then Return SetError(1, 0, 0)
    Local $a_Verh[3] = [_GDIPlus_ImageGetHeight($h_Image),_GDIPlus_ImageGetWidth($h_Image),_GDIPlus_ImageGetHeight($h_Image) / _GDIPlus_ImageGetWidth($h_Image)]
    If ($i_Opt <> 0) And ($i_Opt <> 1) And ($i_Opt <> 2) Then SetError(2, 0, 0)
    If $i_Opt = 1 Then
    If $a_Verh[2] < 1 Then
    $s_Opt = "widht"
    ElseIf $a_Verh[2] > 1 Then
    $s_Opt = "height"
    ElseIf $a_Verh[2] = 1 Then
    $i_Opt = 0
    EndIf
    EndIf
    If $i_Opt = 0 Then
    Local $h_Graphic = _GDIPlus_GraphicsCreateFromHWND($hWnd)
    Local $h_Bitmap = _GDIPlus_BitmapCreateFromGraphics($i_Widht, $i_Height, $h_Graphic), $h_Buffer = _GDIPlus_ImageGetGraphicsContext($h_Bitmap)
    _GDIPlus_GraphicsDrawImageRectRect($h_Buffer, $h_Image, 0, 0, $a_Verh[0], $a_Verh[1], 0, 0, $i_Widht, $i_Height)
    Else
    Switch $s_Opt
    Case "widht"
    Local $h_Graphic = _GDIPlus_GraphicsCreateFromHWND($hWnd)
    Local $h_Bitmap = _GDIPlus_BitmapCreateFromGraphics($i_Widht, $i_Widht * $a_Verh[2], $h_Graphic), $h_Buffer = _GDIPlus_ImageGetGraphicsContext($h_Bitmap)
    _GDIPlus_GraphicsDrawImageRectRect($h_Buffer, $h_Image, 0, 0, $a_Verh[1], $a_Verh[0], 0, 0, $i_Widht, $i_Widht * $a_Verh[2])
    Case "height"
    Local $h_Graphic = _GDIPlus_GraphicsCreateFromHWND($hWnd)
    Local $h_Bitmap = _GDIPlus_BitmapCreateFromGraphics($i_Height / $a_Verh[2], $i_Height, $h_Graphic), $h_Buffer = _GDIPlus_ImageGetGraphicsContext($h_Bitmap)
    _GDIPlus_GraphicsDrawImageRectRect($h_Buffer, $h_Image, 0, 0, $a_Verh[1], $a_Verh[0], 0, 0, $i_Height / $a_Verh[2], $i_Height)
    EndSwitch
    EndIf
    _GDIPlus_GraphicsDispose($h_Graphic)
    _GDIPlus_GraphicsDispose($h_Buffer)
    _GDIPlus_ImageDispose($h_Image)
    Return $h_Bitmap
    EndFunc

    [/autoit]

    Du könntest noch diese Funktionen einbinden:

    [autoit]

    _GDIPlus_GraphicsSetSmoothingMode($h_Buffer, 2)
    DllCall($ghGDIPDll, "int", "GdipSetInterpolationMode", "handle", $h_Buffer, "int", 7)

    [/autoit]


    Damit wird das Bild schöner verkleinert

    E