Hi
Wie manche schon wissen, kann man mit der Funtion _GDIPlus_DrawImagePoints ein Bitmap als Parallelogramm (3 Punkt) zeichnen.
Ich suche schon seit langem nach einer Möglichkeit die Bilder als Trapeze (4 Punkt) zu zeichnen
Nun hab ich eben solch eine Funktion geschrieben, allerdings ist sie nicht gerade die schnellste
Man kann aber die Geschwindigkeit auf Kosten der Prezision erhöhen; von 0 (schnell/grob) bis 1 (langsam/fein)
Des weiteren treten bei zu starken Verzerrungen Löcher im fertigen Bild auf - das muss ich erst irgendwann mal beheben.
autoit.de/wcf/attachment/11750/
autoit.de/wcf/attachment/11751/
_GDIPlus_GraphicsDrawImage_4Points:
Spoiler anzeigen
Func _GDIPlus_GraphicsDrawImage_4Points($hGraphics, $hImage, $X1, $Y1, $X2, $Y2, $X3, $Y3, $X4, $Y4, $fPrecision = 0.25)
;by eukalyptus
Local $aResult = DllCall($ghGDIPDll, "uint", "GdipCreatePath", "int", 0, "int*", 0)
If @error Or Not IsArray($aResult) Then Return SetError(1, 1, False)
Local $hPath = $aResult[2]
Local $iW = _GDIPlus_ImageGetWidth($hImage)
Local $iH = _GDIPlus_ImageGetHeight($hImage)
If $fPrecision <= 0 Then $fPrecision = 0.01
If $fPrecision > 1 Then $fPrecision = 1
Local $iTX = Ceiling($iW * $fPrecision)
Local $iTY = Ceiling($iH * $fPrecision)
Local $iCnt = ($iTX + 1) * ($iTY + 1)
Local $X, $Y
Local $tPoints = DllStructCreate("float[" & $iCnt * 2 & "]")
Local $I
For $Y = 0 To $iTY
For $X = 0 To $iTX
$I = ($Y * ($iTX + 1) + $X) * 2
DllStructSetData($tPoints, 1, $X * $iW / $iTX, $I + 1)
DllStructSetData($tPoints, 1, $Y * $iH / $iTY, $I + 2)
Next
Next
$aResult = DllCall($ghGDIPDll, "uint", "GdipAddPathPolygon", "hwnd", $hPath, "ptr", DllStructGetPtr($tPoints), "int", $iCnt)
If @error Or Not IsArray($aResult) Then Return SetError(1, 2, False)
Local $tWarp = DllStructCreate("float[8]")
DllStructSetData($tWarp, 1, $X1, 1)
DllStructSetData($tWarp, 1, $Y1, 2)
DllStructSetData($tWarp, 1, $X2, 3)
DllStructSetData($tWarp, 1, $Y2, 4)
DllStructSetData($tWarp, 1, $X3, 5)
DllStructSetData($tWarp, 1, $Y3, 6)
DllStructSetData($tWarp, 1, $X4, 7)
DllStructSetData($tWarp, 1, $Y4,
$aResult = DllCall($ghGDIPDll, "uint", "GdipWarpPath", "hwnd", $hPath, "hwnd", 0, "ptr", DllStructGetPtr($tWarp), "int", 4, "float", 0, "float", 0, "float", $iW, "float", $iH, "int", 0, "float", 0)
If @error Or Not IsArray($aResult) Then Return SetError(1, 3, False)
$aResult = DllCall($ghGDIPDll, "uint", "GdipGetPathPoints", "hwnd", $hPath, "ptr", DllStructGetPtr($tPoints), "int", $iCnt)
If @error Or Not IsArray($aResult) Then Return SetError(1, 4, False)
Local $tRectF = DllStructCreate("float X;float Y;float Width;float Height")
$aResult = DllCall($ghGDIPDll, "uint", "GdipGetPathWorldBounds", "hwnd", $hPath, "ptr", DllStructGetPtr($tRectF), "hwnd", 0, "hwnd", 0)
If @error Or Not IsArray($aResult) Then Return SetError(1, 5, False)
DllCall($ghGDIPDll, "uint", "GdipDeletePath", "hwnd", $hPath)
[/autoit] [autoit][/autoit] [autoit]Local $hBitmap = _GDIPlus_BitmapCreateFromGraphics(DllStructGetData($tRectF, 1) + DllStructGetData($tRectF, 3), DllStructGetData($tRectF, 2) + DllStructGetData($tRectF, 4), $hGraphics)
Local $hContext = _GDIPlus_ImageGetGraphicsContext($hBitmap)
Local $tDraw = DllStructCreate("float[6]")
Local $pDraw = DllStructGetPtr($tDraw)
Local $W = $iW / $iTX
Local $H = $iH / $iTY
Local $iO = ($iTX + 1) * 2
Local $fX1, $fY1, $fX2, $fY2, $fX3, $fY3, $fSX, $fSY
For $Y = 0 To $iTY - 1
For $X = 0 To $iTX - 1
$I = ($Y * ($iTX + 1) + $X) * 2
$fX1 = DllStructGetData($tPoints, 1, $I + 1)
$fY1 = DllStructGetData($tPoints, 1, $I + 2)
Switch $X
Case $iTX - 1
$fX2 = DllStructGetData($tPoints, 1, $I + 3)
$fY2 = DllStructGetData($tPoints, 1, $I + 4)
$fSX = 1
Case Else
$fX2 = DllStructGetData($tPoints, 1, $I + 5)
$fY2 = DllStructGetData($tPoints, 1, $I + 6)
$fSX = 2
EndSwitch
Switch $Y
Case $iTY - 1
$fX3 = DllStructGetData($tPoints, 1, $I + 1 + $iO)
$fY3 = DllStructGetData($tPoints, 1, $I + 2 + $iO)
$fSY = 1
Case Else
$fX3 = DllStructGetData($tPoints, 1, $I + 1 + $iO * 2)
$fY3 = DllStructGetData($tPoints, 1, $I + 2 + $iO * 2)
$fSY = 2
EndSwitch
DllStructSetData($tDraw, 1, $fX1, 1)
DllStructSetData($tDraw, 1, $fY1, 2)
DllStructSetData($tDraw, 1, $fX2, 3)
DllStructSetData($tDraw, 1, $fY2, 4)
DllStructSetData($tDraw, 1, $fX3, 5)
DllStructSetData($tDraw, 1, $fY3, 6)
DllCall($ghGDIPDll, "uint", "GdipDrawImagePointsRect", "hwnd", $hContext, "hwnd", $hImage, "ptr", $pDraw, "int", 3, "float", $X * $W, "float", $Y * $H, "float", $W * $fSX, "float", $H * $fSY, "int", 2, "hwnd", 0, "ptr", 0, "ptr", 0)
Next
Next
_GDIPlus_GraphicsDispose($hContext)
_GDIPlus_GraphicsDrawImage($hGraphics, $hBitmap, 0, 0)
_GDIPlus_BitmapDispose($hBitmap)
EndFunc ;==>_GDIPlus_GraphicsDrawImage_4Points
Beispiel:
Spoiler anzeigen
#include <GDIPlus.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
Opt("GuiOnEventMode", 1)
[/autoit] [autoit][/autoit] [autoit]Global $aDrag[5][2] = [[0, 0],[0, 0],[800, 50],[100, 530],[700, 450]]
[/autoit] [autoit][/autoit] [autoit]$hGui = GUICreate("DrawImage_4Points Test", 800, 580)
GUISetOnEvent(-3, "_Exit")
GUICtrlCreateButton("render with higher precision", 200, 550, 200, 20)
GUICtrlSetOnEvent(-1, "_Render")
GUICtrlCreateLabel("precision:", 410, 550, 80, 20, 0x0002)
$cSlider = GUICtrlCreateSlider(500, 545, 100, 25)
GUICtrlSetData(-1, 25)
GUICtrlSetOnEvent(-1, "_Slider")
$cLabel = GUICtrlCreateLabel("0.25", 610, 550, 50, 20)
_GDIPlus_Startup()
$hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGui)
$hBmpBuffer = _GDIPlus_BitmapCreateFromGraphics(800, 540, $hGraphics)
$hGfxBuffer = _GDIPlus_ImageGetGraphicsContext($hBmpBuffer)
_GDIPlus_GraphicsSetSmoothingMode($hGfxBuffer, 2)
_GDIPlus_GraphicsClear($hGfxBuffer, 0xFF000000)
GUIRegisterMsg($WM_PAINT, "WM_PAINT")
GUISetState()
$hBrush = _GDIPlus_BrushCreateSolid(0x8800FF00)
$hPen = _GDIPlus_PenCreate(0xFFFF0000)
$sFile = FileOpenDialog("open image", "", "(*.jpg;*.bmp;*.png;*.tif;*.gif)")
$hImage = _GDIPlus_ImageLoadFromFile($sFile)
_ReDraw(0.02)
[/autoit] [autoit][/autoit] [autoit]$iIndex = 0
While 1
$aInfo = GUIGetCursorInfo($hGui)
If Not $aInfo[2] Then $iIndex = 0
Switch $iIndex
Case 0
If $aInfo[2] Then
For $I = 1 To 4
If $aInfo[0] > $aDrag[$I][0] - 5 And $aInfo[0] < $aDrag[$I][0] + 5 And $aInfo[1] > $aDrag[$I][1] - 5 And $aInfo[1] < $aDrag[$I][1] + 5 Then
$iIndex = $I
ExitLoop
EndIf
Next
EndIf
Case Else
$aDrag[$iIndex][0] = $aInfo[0]
$aDrag[$iIndex][1] = $aInfo[1]
_ReDraw(0.02)
EndSwitch
Sleep(20)
WEnd
Func _GDIPlus_GraphicsDrawImage_4Points($hGraphics, $hImage, $X1, $Y1, $X2, $Y2, $X3, $Y3, $X4, $Y4, $fPrecision = 0.25)
;by eukalyptus
Local $aResult = DllCall($ghGDIPDll, "uint", "GdipCreatePath", "int", 0, "int*", 0)
If @error Or Not IsArray($aResult) Then Return SetError(1, 1, False)
Local $hPath = $aResult[2]
Local $iW = _GDIPlus_ImageGetWidth($hImage)
Local $iH = _GDIPlus_ImageGetHeight($hImage)
If $fPrecision <= 0 Then $fPrecision = 0.01
If $fPrecision > 1 Then $fPrecision = 1
Local $iTX = Ceiling($iW * $fPrecision)
Local $iTY = Ceiling($iH * $fPrecision)
Local $iCnt = ($iTX + 1) * ($iTY + 1)
Local $X, $Y
Local $tPoints = DllStructCreate("float[" & $iCnt * 2 & "]")
Local $I
For $Y = 0 To $iTY
For $X = 0 To $iTX
$I = ($Y * ($iTX + 1) + $X) * 2
DllStructSetData($tPoints, 1, $X * $iW / $iTX, $I + 1)
DllStructSetData($tPoints, 1, $Y * $iH / $iTY, $I + 2)
Next
Next
$aResult = DllCall($ghGDIPDll, "uint", "GdipAddPathPolygon", "hwnd", $hPath, "ptr", DllStructGetPtr($tPoints), "int", $iCnt)
If @error Or Not IsArray($aResult) Then Return SetError(1, 2, False)
Local $tWarp = DllStructCreate("float[8]")
DllStructSetData($tWarp, 1, $X1, 1)
DllStructSetData($tWarp, 1, $Y1, 2)
DllStructSetData($tWarp, 1, $X2, 3)
DllStructSetData($tWarp, 1, $Y2, 4)
DllStructSetData($tWarp, 1, $X3, 5)
DllStructSetData($tWarp, 1, $Y3, 6)
DllStructSetData($tWarp, 1, $X4, 7)
DllStructSetData($tWarp, 1, $Y4,
$aResult = DllCall($ghGDIPDll, "uint", "GdipWarpPath", "hwnd", $hPath, "hwnd", 0, "ptr", DllStructGetPtr($tWarp), "int", 4, "float", 0, "float", 0, "float", $iW, "float", $iH, "int", 0, "float", 0)
If @error Or Not IsArray($aResult) Then Return SetError(1, 3, False)
$aResult = DllCall($ghGDIPDll, "uint", "GdipGetPathPoints", "hwnd", $hPath, "ptr", DllStructGetPtr($tPoints), "int", $iCnt)
If @error Or Not IsArray($aResult) Then Return SetError(1, 4, False)
Local $tRectF = DllStructCreate("float X;float Y;float Width;float Height")
$aResult = DllCall($ghGDIPDll, "uint", "GdipGetPathWorldBounds", "hwnd", $hPath, "ptr", DllStructGetPtr($tRectF), "hwnd", 0, "hwnd", 0)
If @error Or Not IsArray($aResult) Then Return SetError(1, 5, False)
DllCall($ghGDIPDll, "uint", "GdipDeletePath", "hwnd", $hPath)
[/autoit] [autoit][/autoit] [autoit]Local $hBitmap = _GDIPlus_BitmapCreateFromGraphics(DllStructGetData($tRectF, 1) + DllStructGetData($tRectF, 3), DllStructGetData($tRectF, 2) + DllStructGetData($tRectF, 4), $hGraphics)
Local $hContext = _GDIPlus_ImageGetGraphicsContext($hBitmap)
Local $tDraw = DllStructCreate("float[6]")
Local $pDraw = DllStructGetPtr($tDraw)
Local $W = $iW / $iTX
Local $H = $iH / $iTY
Local $iO = ($iTX + 1) * 2
Local $fX1, $fY1, $fX2, $fY2, $fX3, $fY3, $fSX, $fSY
For $Y = 0 To $iTY - 1
For $X = 0 To $iTX - 1
$I = ($Y * ($iTX + 1) + $X) * 2
$fX1 = DllStructGetData($tPoints, 1, $I + 1)
$fY1 = DllStructGetData($tPoints, 1, $I + 2)
Switch $X
Case $iTX - 1
$fX2 = DllStructGetData($tPoints, 1, $I + 3)
$fY2 = DllStructGetData($tPoints, 1, $I + 4)
$fSX = 1
Case Else
$fX2 = DllStructGetData($tPoints, 1, $I + 5)
$fY2 = DllStructGetData($tPoints, 1, $I + 6)
$fSX = 2
EndSwitch
Switch $Y
Case $iTY - 1
$fX3 = DllStructGetData($tPoints, 1, $I + 1 + $iO)
$fY3 = DllStructGetData($tPoints, 1, $I + 2 + $iO)
$fSY = 1
Case Else
$fX3 = DllStructGetData($tPoints, 1, $I + 1 + $iO * 2)
$fY3 = DllStructGetData($tPoints, 1, $I + 2 + $iO * 2)
$fSY = 2
EndSwitch
DllStructSetData($tDraw, 1, $fX1, 1)
DllStructSetData($tDraw, 1, $fY1, 2)
DllStructSetData($tDraw, 1, $fX2, 3)
DllStructSetData($tDraw, 1, $fY2, 4)
DllStructSetData($tDraw, 1, $fX3, 5)
DllStructSetData($tDraw, 1, $fY3, 6)
DllCall($ghGDIPDll, "uint", "GdipDrawImagePointsRect", "hwnd", $hContext, "hwnd", $hImage, "ptr", $pDraw, "int", 3, "float", $X * $W, "float", $Y * $H, "float", $W * $fSX, "float", $H * $fSY, "int", 2, "hwnd", 0, "ptr", 0, "ptr", 0)
Next
Next
_GDIPlus_GraphicsDispose($hContext)
_GDIPlus_GraphicsDrawImage($hGraphics, $hBitmap, 0, 0)
_GDIPlus_BitmapDispose($hBitmap)
EndFunc ;==>_GDIPlus_GraphicsDrawImage_4Points
Func _ReDraw($fPrecision)
_GDIPlus_GraphicsClear($hGfxBuffer, 0xFF000000)
_GDIPlus_GraphicsDrawImage_4Points($hGfxBuffer, $hImage, $aDrag[1][0], $aDrag[1][1], $aDrag[2][0], $aDrag[2][1], $aDrag[3][0], $aDrag[3][1], $aDrag[4][0], $aDrag[4][1], $fPrecision)
For $I = 1 To 4
_GDIPlus_GraphicsFillRect($hGfxBuffer, $aDrag[$I][0] - 5, $aDrag[$I][1] - 5, 10, 10, $hBrush)
_GDIPlus_GraphicsDrawRect($hGfxBuffer, $aDrag[$I][0] - 5, $aDrag[$I][1] - 5, 10, 10, $hPen)
Next
_GDIPlus_GraphicsDrawImage($hGraphics, $hBmpBuffer, 0, 0)
EndFunc ;==>_ReDraw
Func _Slider()
GUICtrlSetData($cLabel, GUICtrlRead($cSlider) / 100)
EndFunc ;==>_Slider
Func _Render()
Local $fPrecision = GUICtrlRead($cSlider) / 100
SplashTextOn("Rendering with precision " & $fPrecision, "please wait", 250, 50)
_ReDraw($fPrecision)
SplashOff()
EndFunc ;==>_Render
Func WM_PAINT($hWnd, $uMsgm, $wParam, $lParam)
_GDIPlus_GraphicsDrawImage($hGraphics, $hBmpBuffer, 0, 0)
Return $GUI_RUNDEFMSG
EndFunc ;==>WM_PAINT
Func _Exit()
_GDIPlus_ImageDispose($hImage)
_GDIPlus_BrushDispose($hBrush)
_GDIPlus_PenDispose($hPen)
_GDIPlus_GraphicsDispose($hGfxBuffer)
_GDIPlus_BitmapDispose($hBmpBuffer)
_GDIPlus_GraphicsDispose($hGraphics)
_GDIPlus_Shutdown()
Exit
EndFunc ;==>_Exit
Beim Beispiel einfach die grünen Eckpunkte mit der Maus verziehen und dann auf "Render" klicken
E