"Verzerrung" bei Bild

  • Hallo liebe AutoIt Community,
    ich habe ein Problem beim vergrößern eines Bildes per GDI+.
    Wenn ich das Bild vergrößer so fehlen im "ecken", es verrutscht irgendwie, hier mal mein Script:

    [autoit]


    _GDIPlus_StartUp()
    $hGraphic = _GDIPlus_GraphicsCreateFromHWND($sGui)
    $hBitmap = _GDIPlus_BitmapCreateFromGraphics($Width, $Height, $hGraphic)
    $hBackbuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    $sPicture = _GDIPlus_ImageLoadFromFile($ImageFile)
    _GDIPlus_GraphicsSetInterpolationMode($hBackbuffer, 5)
    _GDIPlus_GraphicsDrawImageRect($hBackbuffer, $sPicture, 0,0 $Width, $Height)
    _GDIPlus_ImageSaveToFile($hBitmap, $Output)
    _GDIPlus_Shutdown()

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

    Func _GDIPlus_GraphicsSetInterpolationMode($hGraphics, $iInterpolationMode)
    Local $aResult = DllCall($ghGDIPDll, "uint", "GdipSetInterpolationMode", "hwnd", $hGraphics, "int", $iInterpolationMode)
    If @error Then Return SetError(@error, @extended, False)
    Return $aResult[0] = 0
    EndFunc ;==>_GDIPlus_GraphicsSetInterpolationMode
    ;5 = Non Smoothing

    [/autoit]

    Hier mal 2 Links zum vorherigen Bild und dem Ergebnis:
    Natur: http://img812.imageshack.us/img812/3329/sworddg.png
    Ergebnis: http://img94.imageshack.us/img94/1526/swordrs.png

    Okay, das original Schwert ist ein bisschen (sehr) klein, aber eigentlich sollte das nicht sein, oder ?
    Hilfe ! :D - MfG Mattthias

    Es gibt sehr viele Leute, die glauben. Aber aus Aberglauben.
    - Blaise Pascal

    Einmal editiert, zuletzt von Mattthias (27. Mai 2011 um 17:21)

  • Oben ist das nicht mehr "quadratisch" - Es ist oben abgeschnitten !
    Unten links erkennst du es auch !
    Zitat Frauentausch (nur ironisch zu nehmen): "Also entweder bist du blind auf beiden Augen, oder einfach nur BLÖD !" <- Andreas xD

    Es gibt sehr viele Leute, die glauben. Aber aus Aberglauben.
    - Blaise Pascal

  • Hmm - ich hab zwar keine Ahnung, weshalb das nun so ist (Bug?), aber als Workaround könntest du es so machen:

    Spoiler anzeigen
    [autoit]

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

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

    Opt("GUIOnEventMode", 1)

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

    _GDIPlus_Startup()

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

    Global $fScale = 30

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

    Global $hImage = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\sworddg.png")

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

    Global $iW = _GDIPlus_ImageGetWidth($hImage)
    Global $iH = _GDIPlus_ImageGetHeight($hImage)
    Global $iWidth = $iW * 96 / _GDIPlus_ImageGetHorizontalResolution($hImage) * $fScale
    Global $iHeight = $iH * 96 / _GDIPlus_ImageGetVerticalResolution($hImage) * $fScale

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

    Global $hGui = GUICreate("Test", $iWidth, $iHeight)
    GUISetOnEvent($GUI_EVENT_CLOSE, "_EXIT")
    Global $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGui)
    Global $hBmpBuffer = _GDIPlus_BitmapCreateFromGraphics($iWidth, $iHeight, $hGraphics)
    Global $hGfxBuffer = _GDIPlus_ImageGetGraphicsContext($hBmpBuffer)
    _GDIPlus_GraphicsSetSmoothingMode($hGfxBuffer, 2)
    _GDIPlus_GraphicsSetInterpolationMode($hGfxBuffer, 5)
    _GDIPlus_GraphicsClear($hGfxBuffer, 0xFFFFFFFF)
    _GDIPlus_GraphicsDrawImageRectRect_F($hGfxBuffer, $hImage, -0.5, -0.5, $iW, $iH, 0, 0, $iWidth, $iHeight)

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

    GUIRegisterMsg($WM_PAINT, "WM_PAINT")
    GUISetState()

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

    While 1
    Sleep(10)
    WEnd

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

    Func WM_PAINT($hWnd, $uMsgm, $wParam, $lParam)
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBmpBuffer, 0, 0)
    Return $GUI_RUNDEFMSG
    EndFunc ;==>WM_PAINT

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

    Func _Exit()
    _GDIPlus_GraphicsDispose($hGfxBuffer)
    _GDIPlus_BitmapDispose($hBmpBuffer)
    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_Shutdown()
    Exit
    EndFunc ;==>_Exit

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

    Func _GDIPlus_GraphicsDrawImageRectRect_F($hGraphics, $hImage, $fSrcX, $fSrcY, $fSrcWidth, $fSrcHeight, $fDstX, $fDstY, $fDstWidth, $fDstHeight, $iUnit = 2)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipDrawImageRectRect", "handle", $hGraphics, "handle", $hImage, "float", $fDstX, _
    "float", $fDstY, "float", $fDstWidth, "float", $fDstHeight, "float", $fSrcX, "float", $fSrcY, "float", $fSrcWidth, _
    "float", $fSrcHeight, "int", $iUnit, "int", 0, "int", 0, "int", 0)
    If @error Then Return SetError(@error, @extended, False)
    Return $aResult[0] = 0
    EndFunc ;==>_GDIPlus_GraphicsDrawImageRectRect_F

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

    Func _GDIPlus_GraphicsDrawImageRect_F($hGraphics, $hImage, $fX, $fY, $fW, $fH)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipDrawImageRect", "handle", $hGraphics, "handle", $hImage, "float", $fX, "float", $fY, _
    "float", $fW, "float", $fH)
    If @error Then Return SetError(@error, @extended, False)
    Return $aResult[0] = 0
    EndFunc ;==>_GDIPlus_GraphicsDrawImageRect_F

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

    Func _GDIPlus_GraphicsSetInterpolationMode($hGraphics, $iInterpolationMode)
    Local $aResult = DllCall($ghGDIPDll, "uint", "GdipSetInterpolationMode", "hwnd", $hGraphics, "int", $iInterpolationMode)
    If @error Then Return SetError(@error, @extended, False)
    Return $aResult[0] = 0
    EndFunc ;==>_GDIPlus_GraphicsSetInterpolationMode

    [/autoit]
  • Exakt SO soll es aussehen :D
    Aber - Wie hast du das hinbekommen; bekommt man das auch kürzer / noobfreundlicher hin ?

    Es gibt sehr viele Leute, die glauben. Aber aus Aberglauben.
    - Blaise Pascal

  • Es funktioniert auch mit:

    [autoit]

    _GDIPlus_GraphicsSetPixelOffsetMode($hGfxBuffer,2)

    [/autoit]


    (bzw.: 4)

    Das Geheimnis des oben geposteten Scripts liegt in der Zeile 26 => SrcRect X/Y = -0.5
    Hat wohl auch mit dem PixelOffsetMode zu tun und scheint doch kein Bug zu sein...

    E

  • Tausendfachen dank Eukalyptus; stellt sich mir nur noch die Frage: Wieso ist das so - Sollte es so sein ?
    MfG

    Es gibt sehr viele Leute, die glauben. Aber aus Aberglauben.
    - Blaise Pascal

  • Hier noch eine Möglichkeit:

    Spoiler anzeigen
    [autoit]


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

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

    Opt("GUIOnEventMode", 1)

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

    _GDIPlus_Startup()
    Global Const $fScale = 30
    Global Const $hImage = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\sworddg.png")
    Global Const $iW = _GDIPlus_ImageGetWidth($hImage)
    Global Const $iH = _GDIPlus_ImageGetHeight($hImage)
    Global Const $iWidth = $iW * 96 / _GDIPlus_ImageGetHorizontalResolution($hImage) * $fScale
    Global Const $iHeight = $iH * 96 / _GDIPlus_ImageGetVerticalResolution($hImage) * $fScale

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

    Global Const $hGui = GUICreate("Test", $iWidth, $iHeight)
    GUISetBkColor(0xE0E080)
    Global Const $cPic = GUICtrlCreatePic("", 0, 0, $iWidth, $iHeight)
    Global Const $hPic = GUICtrlGetHandle($cPic)
    GUISetState()

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

    Global Const $hDC = _WinAPI_GetWindowDC($hPic)
    Global Const $hDC_backbuffer = _WinAPI_CreateCompatibleDC($hDC)
    Global Const $hBitmap_backbuffer = _WinAPI_CreateCompatibleBitmap($hDC, $iWidth, $iHeight)
    Global Const $DC_obj = _WinAPI_SelectObject($hDC_backbuffer, $hBitmap_backbuffer)
    Global Const $hGfx = _GDIPlus_GraphicsCreateFromHDC($hDC_backbuffer)
    _GDIPlus_GraphicsDrawImage($hGfx, $hImage, 0, 0)
    _GDIPlus_ImageDispose($hImage)
    _GDIPlus_GraphicsDispose($hGfx)
    _GDIPlus_Shutdown()

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

    _WinAPI_AlphaBlend($hDC, 0, 0, $iWidth, $iHeight, $hDC_backbuffer, 0, 0, $iW, $iH, 255, 1)
    _WinAPI_BitBlt($hDC_backbuffer, 0, 0, $iWidth, $iHeight, $hDC, 0, 0, $SRCCOPY)

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

    _WinAPI_ReleaseDC($hPic, $hDC)
    _WinAPI_SelectObject($hDC_backbuffer, $DC_obj)
    _WinAPI_DeleteDC($hDC_backbuffer)

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

    Global Const $STM_SETIMAGE = 0x0172
    Global Const $STM_GETIMAGE = 0x0173
    _SendMessage($hPic, $STM_SETIMAGE, 0, $hBitmap_backbuffer)
    Global Const $hObj = _SendMessage($hPic, $STM_GETIMAGE)
    If $hObj <> $hBitmap_backbuffer Then
    _WinAPI_DeleteObject($hBitmap_backbuffer)
    EndIf

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

    GUISetOnEvent($GUI_EVENT_CLOSE, "_EXIT")

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

    While Sleep(100000)
    WEnd

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

    Func _Exit()
    GUIDelete($hGui)
    Exit
    EndFunc ;==>_Exit

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

    Func _WinAPI_AlphaBlend($hDestDC, $iXDest, $iYDest, $iWidthDest, $iHeightDest, $hSrcDC, $iXSrc, $iYSrc, $iWidthSrc, $iHeightSrc, $iAlpha, $fAlpha = 0)
    Local $iBlend = BitOR(BitShift(Not ($fAlpha = 0), -24), BitShift(BitAND($iAlpha, 0xFF), -16))
    Local $Ret = DllCall('gdi32.dll', 'int', 'GdiAlphaBlend', 'hwnd', $hDestDC, 'int', $iXDest, 'int', $iYDest, 'int', $iWidthDest, 'int', $iHeightDest, 'hwnd', $hSrcDC, 'int', $iXSrc, 'int', $iYSrc, 'int', $iWidthSrc, 'int', $iHeightSrc, 'dword', $iBlend)
    If @error Or (Not $Ret[0]) Then Return SetError(1, 0, 0)
    Return 1
    EndFunc ;==>_WinAPI_AlphaBlend

    [/autoit]

    Gruß,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

    3 Mal editiert, zuletzt von UEZ (27. Mai 2011 um 23:27)