GDI+ Bitmap "trapezoid" zeichnen / DrawImage_4Points

  • 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 :whistling:
    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
    [autoit]

    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]

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

    Local $iW = _GDIPlus_ImageGetWidth($hImage)
    Local $iH = _GDIPlus_ImageGetHeight($hImage)

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

    If $fPrecision <= 0 Then $fPrecision = 0.01
    If $fPrecision > 1 Then $fPrecision = 1

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

    Local $iTX = Ceiling($iW * $fPrecision)
    Local $iTY = Ceiling($iH * $fPrecision)
    Local $iCnt = ($iTX + 1) * ($iTY + 1)
    Local $X, $Y

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

    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

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

    $aResult = DllCall($ghGDIPDll, "uint", "GdipAddPathPolygon", "hwnd", $hPath, "ptr", DllStructGetPtr($tPoints), "int", $iCnt)
    If @error Or Not IsArray($aResult) Then Return SetError(1, 2, False)

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

    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, 8)

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

    $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)

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

    $aResult = DllCall($ghGDIPDll, "uint", "GdipGetPathPoints", "hwnd", $hPath, "ptr", DllStructGetPtr($tPoints), "int", $iCnt)
    If @error Or Not IsArray($aResult) Then Return SetError(1, 4, False)

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

    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)

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

    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)

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

    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

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

    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)

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

    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

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

    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

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

    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)

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

    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

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

    _GDIPlus_GraphicsDispose($hContext)
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBitmap, 0, 0)
    _GDIPlus_BitmapDispose($hBitmap)
    EndFunc ;==>_GDIPlus_GraphicsDrawImage_4Points

    [/autoit]

    Beispiel:

    Spoiler anzeigen
    [autoit]

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

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

    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)

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

    _GDIPlus_Startup()
    $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGui)
    $hBmpBuffer = _GDIPlus_BitmapCreateFromGraphics(800, 540, $hGraphics)
    $hGfxBuffer = _GDIPlus_ImageGetGraphicsContext($hBmpBuffer)
    _GDIPlus_GraphicsSetSmoothingMode($hGfxBuffer, 2)
    _GDIPlus_GraphicsClear($hGfxBuffer, 0xFF000000)

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

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

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

    $hBrush = _GDIPlus_BrushCreateSolid(0x8800FF00)
    $hPen = _GDIPlus_PenCreate(0xFFFF0000)

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

    $sFile = FileOpenDialog("open image", "", "(*.jpg;*.bmp;*.png;*.tif;*.gif)")
    $hImage = _GDIPlus_ImageLoadFromFile($sFile)

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

    _ReDraw(0.02)

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

    $iIndex = 0
    While 1
    $aInfo = GUIGetCursorInfo($hGui)

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

    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

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

    Sleep(20)
    WEnd

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

    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]

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

    Local $iW = _GDIPlus_ImageGetWidth($hImage)
    Local $iH = _GDIPlus_ImageGetHeight($hImage)

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

    If $fPrecision <= 0 Then $fPrecision = 0.01
    If $fPrecision > 1 Then $fPrecision = 1

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

    Local $iTX = Ceiling($iW * $fPrecision)
    Local $iTY = Ceiling($iH * $fPrecision)
    Local $iCnt = ($iTX + 1) * ($iTY + 1)
    Local $X, $Y

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

    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

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

    $aResult = DllCall($ghGDIPDll, "uint", "GdipAddPathPolygon", "hwnd", $hPath, "ptr", DllStructGetPtr($tPoints), "int", $iCnt)
    If @error Or Not IsArray($aResult) Then Return SetError(1, 2, False)

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

    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, 8)

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

    $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)

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

    $aResult = DllCall($ghGDIPDll, "uint", "GdipGetPathPoints", "hwnd", $hPath, "ptr", DllStructGetPtr($tPoints), "int", $iCnt)
    If @error Or Not IsArray($aResult) Then Return SetError(1, 4, False)

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

    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)

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

    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)

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

    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

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

    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)

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

    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

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

    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

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

    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)

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

    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

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

    _GDIPlus_GraphicsDispose($hContext)
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBitmap, 0, 0)
    _GDIPlus_BitmapDispose($hBitmap)
    EndFunc ;==>_GDIPlus_GraphicsDrawImage_4Points

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

    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

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

    Func _Slider()
    GUICtrlSetData($cLabel, GUICtrlRead($cSlider) / 100)
    EndFunc ;==>_Slider

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

    Func _Render()
    Local $fPrecision = GUICtrlRead($cSlider) / 100
    SplashTextOn("Rendering with precision " & $fPrecision, "please wait", 250, 50)
    _ReDraw($fPrecision)
    SplashOff()
    EndFunc ;==>_Render

    [/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_ImageDispose($hImage)
    _GDIPlus_BrushDispose($hBrush)
    _GDIPlus_PenDispose($hPen)
    _GDIPlus_GraphicsDispose($hGfxBuffer)
    _GDIPlus_BitmapDispose($hBmpBuffer)
    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_Shutdown()
    Exit
    EndFunc ;==>_Exit

    [/autoit]


    Beim Beispiel einfach die grünen Eckpunkte mit der Maus verziehen und dann auf "Render" klicken

    E

  • Zitat

    _GDIPlus_GraphicsDrawImageRectRect() sollte doch das gleiche können ?

    Sollte, macht aber leider nicht.....das "Rectangle" besteht nur aus 2 Punkten, damit ein Trapez zu beschreiben fällt....äääähmmmm...etwas schwer^^

  • Hi eukalyptus!

    Zitat

    Nun hab ich eben solch eine Funktion geschrieben, allerdings ist sie nicht gerade die schnellste

    kann ich nicht bestätigen! In deiner Demo wird das Trapez bei Bewegung der Eckpunkte in Echtzeit nachgezeichnet. Bei höherer "Empfindlichkeit" ruckelt es etwas, aber das wirkt sich nur bei extrem flachen Betrachtungswinkeln aus...
    Mal schauen, die "inner Loops" lassen sich mit einer Handvoll Assemblerzeilen sicherlich beschleunigen. Wird Zeit für ein 64Bitsystem bei mir, dann baue ich so um, dass die ASM-Beschleunigungen auch auf 64Bit funktionieren/compilieren.

  • Hab nun die "Löcher" entfernt und die Funktion zu Testzwecken in folgendes Script von UEZ bzw. Lakes eingebaut:

    Spoiler anzeigen
    [autoit]

    #include <GDIPlus.au3>
    #include <Misc.au3>

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

    Opt("MustDeclareVars", 1)
    Opt("GUIOnEventMode", 1)
    Opt("MouseCoordMode", 1)

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

    Global $user32_dll = DllOpen("user32.dll")
    Global $Reset, $hPenDotted, $hPenDash, $ResetCube, $CubeX, $CubeY, $CubeZ
    Global $CubeX1, $CubeY1, $CubeX2, $CubeY2, $CubeX3, $CubeY3, $CubeX4, $CubeY4
    Global $Tog, $Tog1, $Tog2, $Tog3, $Tog4 = True, $Tog5, $Tog6, $Tog7 = True, $T, $Delay = 100
    Global $Text = "Press F1 to F6 to Toogle Cube Faces (F7 Toggles the Autoit Logo being Painted)"
    Global $text1 = "Left Mouse Button to Rotate, Right Mouse Button to Reset (Mouse wheel to Zoom)"

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

    Local $dot_distance = 150
    Local Const $Width = 600
    Local Const $Height = $Width
    Local Const $W2 = $Width / 2
    Local Const $H2 = $Height / 2
    Local Const $deg = 180 / ACos(-1)
    Local $hwnd = GUICreate("Orginal Code by UEZ ", $Width, $Height)

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

    GUISetState()

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

    If @OSBuild < 7600 Then WinSetTrans($hwnd, "", 0xFF) ;workaround for XP machines when alpha blending is activated on _GDIPlus_GraphicsClear() function to avoid slow drawing

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

    _GDIPlus_Startup()
    Local $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hwnd)
    Local $hBitmap = _GDIPlus_BitmapCreateFromGraphics($Width, $Height, $hGraphics)
    Local $hBackbuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    _GDIPlus_GraphicsClear($hBackbuffer)
    _GDIPlus_GraphicsSetSmoothingMode($hBackbuffer, 2)

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

    Local $sAutoItPath = RegRead('HKEY_LOCAL_MACHINE\SOFTWARE\AutoIt v3\AutoIt', 'InstallDir')
    Local $hImage = _GDIPlus_ImageLoadFromFile($sAutoItPath & "\Examples\GUI\logo4.gif")

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

    Local $Str
    Local $pColor = 0xFF0000F0
    Local $hPen = _GDIPlus_PenCreate($pColor, 8)
    _GDIPlus_PenSetEndCap($hPen, $GDIP_LINECAPARROWANCHOR)
    Local $hCubePen = _GDIPlus_PenCreate(0x400000F0, 8)
    _GDIPlus_PenSetEndCap($hCubePen, $GDIP_LINECAPARROWANCHOR)
    Local $hBrush = _GDIPlus_BrushCreateSolid()
    Local $hBrush1 = _GDIPlus_BrushCreateSolid(0x60FFFF00)
    Local $hBrush2 = _GDIPlus_BrushCreateSolid(0x60FF8000)
    $hPenDash = _GDIPlus_PenCreate(0xFF000000, 2)
    _GDIPlus_PenSetDashStyle($hPenDash, $GDIP_DASHSTYLEDASH)
    $hPenDotted = _GDIPlus_PenCreate(0xFF000000, 2)
    _GDIPlus_PenSetDashStyle($hPenDotted, $GDIP_DASHSTYLEDOT)
    Local Const $length = 250
    Local Const $Pi = ACos(-1)
    Local Const $amout_of_dots = 6
    Local Const $amout_of_cube_dots = 9

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

    #cs
    X Y Z
    ---------------------------------------
    1 [-$length, 0, 0 ], _
    2 [ $length, 0, 0 ], _
    3 [ 0, -$length, 0 ], _
    4 [ 0, $length, 0 ], _
    5 [ 0, 0, -$length ], _
    6 [ 0, 0, $length ]]
    #ce

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

    ; Axis Coords
    Local $draw_coordinates[$amout_of_dots][4] = [ _; X y Z
    [-$length, 0, 0], _
    [$length, 0, 0], _
    [0, -$length, 0], _
    [0, $length, 0], _
    [0, 0, -$length], _
    [0, 0, $length]]
    $Reset = $draw_coordinates

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

    Local $cube_coordinates[$amout_of_cube_dots][4] = [ _; X y Z
    [-$dot_distance, -$dot_distance, -$dot_distance], _
    [$dot_distance, -$dot_distance, -$dot_distance], _
    [$dot_distance, $dot_distance, -$dot_distance], _
    [-$dot_distance, $dot_distance, -$dot_distance], _
    [-$dot_distance, -$dot_distance, $dot_distance], _
    [$dot_distance, -$dot_distance, $dot_distance], _
    [$dot_distance, $dot_distance, $dot_distance], _
    [-$dot_distance, $dot_distance, $dot_distance]]
    $ResetCube = $cube_coordinates

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

    Local $x1, $y1, $x2, $y2
    Local $b, $j, $x, $y, $z, $mx, $my, $MPos
    Local $zoom_counter = 100
    Local Const $zoom_min = 50
    Local Const $zoom_max = 125
    Local Const $mouse_sense = 4000
    Local Const $start_x = $Width / 2
    Local Const $start_y = $Height / 2
    Local Const $dx = @DesktopWidth / 2, $dy = @DesktopHeight / 2
    Local Const $Red = 0xFFF00000
    Local Const $Green = 0xFF00F000
    Local Const $Blue = 0xFF0000F0
    Local $mwx, $mwy, $mwz, $angle, $rad = 180 / $Pi

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

    MouseMove($dx, $dy, 1)

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

    GUIRegisterMsg(0x020A, "WM_MOUSEWHEEL")

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

    GUISetOnEvent(-3, "Close")

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

    Do
    _GDIPlus_GraphicsClear($hBackbuffer, 0xF0FFFFFF)

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

    For $b = 0 To $amout_of_dots - 1 ;correct axis perspective
    $draw_coordinates[$b][3] = 1 + $draw_coordinates[$b][2] / 1500
    Next
    For $c = 0 To $amout_of_cube_dots - 1 ;correct cube perspective
    $cube_coordinates[$c][3] = 1 + $cube_coordinates[$c][2] / 0x600
    Next

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

    ;draw axis lines
    Draw_Lines(0, 1, $Red) ;draw x axis - red
    Draw_Lines(2, 3, $Green) ;draw y axis - green
    Draw_Lines(4, 5, $Blue) ;draw z axis - blue
    ;--------------------------------------------------------------------

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

    Select
    Case _IsPressed("70", $user32_dll)
    Sleep($Delay)
    $Tog1 = Not $Tog1
    ; Beep(100,50)

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

    Case _IsPressed("71", $user32_dll)
    Sleep($Delay)
    $Tog2 = Not $Tog2
    ; Beep(200,50)

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

    Case _IsPressed("72", $user32_dll)
    Sleep($Delay)
    $Tog3 = Not $Tog3
    ; Beep(300,50)

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

    Case _IsPressed("73", $user32_dll)
    Sleep($Delay)
    $Tog4 = Not $Tog4
    ; Beep(400,50)

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

    Case _IsPressed("74", $user32_dll)
    Sleep($Delay)
    $Tog5 = Not $Tog5
    ; Beep(500,50)

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

    Case _IsPressed("75", $user32_dll)
    Sleep($Delay)
    $Tog6 = Not $Tog6
    ; Beep(600,50)

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

    Case _IsPressed("76", $user32_dll)
    Sleep($Delay)
    $Tog7 = Not $Tog7
    ; Beep(700,50)
    EndSelect

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

    ; 4 -- - - - 5
    ; / | / |
    ; 0 - - - - 1 |
    ; | | | |
    ; | 7 -- - -|- 6
    ; | / | /
    ; 3 - - - - 2
    If $Tog1 = True Then Draw_Cube_Lines(3, 2, 6, 7) ;F1 bottom
    If $Tog2 = True Then Draw_Cube_Lines(5, 1, 0, 4) ;F2 top
    If $Tog3 = True Then Draw_Cube_Lines(1, 2, 3, 0) ;F3 front
    If $Tog4 = True Then Draw_Cube_Lines(7, 6, 5, 4) ;F4 rear
    If $Tog5 = True Then Draw_Cube_Lines(6, 2, 1, 5) ;F5 right
    If $Tog6 = True Then Draw_Cube_Lines(0, 3, 7, 4) ;F6 left

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

    If _IsPressed("01", $user32_dll) Then ; Left mouse button to Rotate
    $MPos = MouseGetPos()
    For $j = 0 To $amout_of_dots - 1
    $mx = ($dx - $MPos[0]) / $mouse_sense
    $my = -($dy - $MPos[1]) / $mouse_sense
    Calc($my, $mx, $j) ;calculate axis coordinates
    Next
    For $j = 0 To $amout_of_cube_dots - 1
    CubeCalc($my, $mx, $j) ;calculate cube coordinates
    Next
    EndIf
    If _IsPressed("02", $user32_dll) Then ;Right mouse button to Reset CoOrds and Toggles to inital values
    $draw_coordinates = $Reset
    $cube_coordinates = $ResetCube
    $Tog1 = False
    $Tog2 = False
    $Tog3 = False
    $Tog4 = True ;Draw this Face as Default
    $Tog5 = False
    $Tog6 = False
    $Tog7 = True ;Paint Logo
    EndIf

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

    _GDIPlus_GraphicsDrawImageRect($hGraphics, $hBitmap, 0, 0, $Width, $Height)
    Until Not Sleep(30)

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

    ;Draw Axis Lines
    Func Draw_Lines($p1, $p2, $pColor)
    $x1 = $start_x + $draw_coordinates[$p1][0] * $draw_coordinates[$p1][3]
    $y1 = $start_y + $draw_coordinates[$p1][1] * $draw_coordinates[$p1][3]

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

    $x2 = $start_x + $draw_coordinates[$p2][0] * $draw_coordinates[$p2][3]
    $y2 = $start_y + $draw_coordinates[$p2][1] * $draw_coordinates[$p2][3]

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

    _GDIPlus_PenSetColor($hPen, $pColor)
    _GDIPlus_GraphicsDrawLine($hBackbuffer, $x1, $y1, $x2, $y2, $hPen)

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

    _GDIPlus_BrushSetSolidColor($hBrush, $pColor)
    _GDIPlus_GraphicsFillEllipse($hBackbuffer, $x1 - 10, $y1 - 10, 20, 20, $hBrush)

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

    $angle = Mod(360 - Abs(Angle($draw_coordinates[$p1][0], $draw_coordinates[$p2][1])), 360)
    Select
    Case $pColor = $Red
    $Str = "XAngle = " & StringFormat("%.2f", $angle)
    Case $pColor = $Green
    $Str = "YAngle = " & StringFormat("%.2f", $angle)
    Case $pColor = $Blue
    $Str = "ZAngle = " & StringFormat("%.2f", $angle)
    EndSelect
    _GDIPlus_GraphicsFillEllipse($hBackbuffer, $start_x - 10, $start_y - 10, 20, 20, 0) ; Origin
    _GDIPlus_GraphicsDrawString($hBackbuffer, "Origin", $start_x - 20, $start_y - 30)
    _GDIPlus_GraphicsDrawString($hBackbuffer, $Str, $x2 - 20, $y2 - 30)
    EndFunc ;==>Draw_Lines

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

    Func Draw_Cube_Lines($Cp1, $Cp2, $Cp3, $Cp4)
    $CubeX1 = $start_x + $cube_coordinates[$Cp1][0] * $cube_coordinates[$Cp1][3]
    $CubeY1 = $start_y + $cube_coordinates[$Cp1][1] * $cube_coordinates[$Cp1][3]

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

    $CubeX2 = $start_x + $cube_coordinates[$Cp2][0] * $cube_coordinates[$Cp2][3]
    $CubeY2 = $start_y + $cube_coordinates[$Cp2][1] * $cube_coordinates[$Cp2][3]

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

    $CubeX3 = $start_x + $cube_coordinates[$Cp3][0] * $cube_coordinates[$Cp3][3]
    $CubeY3 = $start_y + $cube_coordinates[$Cp3][1] * $cube_coordinates[$Cp3][3]

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

    $CubeX4 = $start_x + $cube_coordinates[$Cp4][0] * $cube_coordinates[$Cp4][3]
    $CubeY4 = $start_y + $cube_coordinates[$Cp4][1] * $cube_coordinates[$Cp4][3]

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

    ;####### For Front Face #########
    ;------------------------------- Top -------------------------------------------------------
    _GDIPlus_GraphicsDrawLine($hBackbuffer, $CubeX4, $CubeY4, $CubeX1, $CubeY1, $hCubePen) ; top 0 - 1
    _GDIPlus_GraphicsFillEllipse($hBackbuffer, $CubeX4 - 5, $CubeY4 - 5, 10, 10, 0)

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

    _GDIPlus_GraphicsDrawLine($hBackbuffer, $start_x, $start_y, $CubeX4, $CubeY4, $hPenDash)
    _GDIPlus_GraphicsDrawString($hBackbuffer, $Cp4, $CubeX4 - 10, $CubeY4 - 20, "Arial", 12)
    _GDIPlus_GraphicsDrawString($hBackbuffer, $Cp1, $CubeX1, $CubeY1 - 20, "Arial", 12)
    ;-------------------------------------------------------------------------------------------
    ;------------------------------- Right -------------------------------------------------------
    _GDIPlus_GraphicsDrawLine($hBackbuffer, $CubeX1, $CubeY1, $CubeX2, $CubeY2, $hCubePen) ; right 2 - 1
    ;---------------------------------------------------------------------------------------------
    ;------------------------------- Bottom -------------------------------------------------------
    _GDIPlus_GraphicsDrawLine($hBackbuffer, $CubeX2, $CubeY2, $CubeX3, $CubeY3, $hCubePen) ; bottom 3 - 2
    _GDIPlus_GraphicsFillEllipse($hBackbuffer, $CubeX2 - 5, $CubeY2 - 5, 10, 10, 0)

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

    _GDIPlus_GraphicsDrawLine($hBackbuffer, $start_x, $start_y, $CubeX2, $CubeY2, $hPenDash)
    _GDIPlus_GraphicsDrawString($hBackbuffer, $Cp2, $CubeX2 + 5, $CubeY2, "Arial", 12)
    _GDIPlus_GraphicsDrawString($hBackbuffer, $Cp3, $CubeX3 - 10, $CubeY3, "Arial", 12)
    ;----------------------------------------------------------------------------------------------
    _GDIPlus_GraphicsDrawString($hBackbuffer, $Text, 5, 550, "Arial", 12) ;Instructions
    _GDIPlus_GraphicsDrawString($hBackbuffer, $text1, 5, 570, "Arial", 12)

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

    ;------------------------------- Left --------------------------------------------------------
    _GDIPlus_GraphicsDrawLine($hBackbuffer, $CubeX3, $CubeY3, $CubeX4, $CubeY4, $hCubePen) ; left
    ;----------------------------------------------------------------------------------------------
    _GDIPlus_GraphicsDrawString($hBackbuffer, $Cp3, $CubeX3 - 10, $CubeY3, "Arial", 12)
    ;--------------------------- Put the Autoit Logo image on one Face ----------------------------------------------
    If $Cp1 = 7 And $Tog7 = True Then
    _GDIPlus_GraphicsDrawImage_4Points($hBackbuffer, $hImage, $CubeX4, $CubeY4, _
    $CubeX3, $CubeY3, _
    $CubeX1, $CubeY1, _
    $CubeX2, $CubeY2, 0.05)
    EndIf
    EndFunc ;==>Draw_Cube_Lines

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

    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]

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

    Local $iW = _GDIPlus_ImageGetWidth($hImage)
    Local $iH = _GDIPlus_ImageGetHeight($hImage)

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

    If $fPrecision <= 0 Then $fPrecision = 0.01
    If $fPrecision > 1 Then $fPrecision = 1

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

    Local $iTX = Ceiling($iW * $fPrecision)
    Local $iTY = Ceiling($iH * $fPrecision)
    Local $iCnt = ($iTX + 1) * ($iTY + 1)
    Local $X, $Y

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

    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

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

    $aResult = DllCall($ghGDIPDll, "uint", "GdipAddPathPolygon", "hwnd", $hPath, "ptr", DllStructGetPtr($tPoints), "int", $iCnt)
    If @error Or Not IsArray($aResult) Then Return SetError(1, 2, False)

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

    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, 8)

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

    $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)

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

    $aResult = DllCall($ghGDIPDll, "uint", "GdipGetPathPoints", "hwnd", $hPath, "ptr", DllStructGetPtr($tPoints), "int", $iCnt)
    If @error Or Not IsArray($aResult) Then Return SetError(1, 4, False)

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

    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)

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

    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)

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

    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

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

    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)

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

    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

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

    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

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

    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)

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

    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

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

    _GDIPlus_GraphicsDispose($hContext)
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBitmap, 0, 0)
    _GDIPlus_BitmapDispose($hBitmap)
    EndFunc ;==>_GDIPlus_GraphicsDrawImage_4Points

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

    Func Angle($x, $y)
    Local $angle
    If $x = 0 Then
    $angle = 0
    Else
    $angle = -ATan($y / - $x) * $deg
    EndIf
    If - $x < 0 Then
    $angle = -180 + $angle
    ElseIf - $x >= 0 And $y < 0 Then
    $angle = -360 + $angle
    EndIf
    Return $angle
    EndFunc ;==>Angle

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

    Func Calc($angle_x, $angle_y, $I, $angle_z = 0)
    ;calculate axis 3D rotation
    $x = $draw_coordinates[$I][0] * Cos($angle_y) + $draw_coordinates[$I][2] * Sin($angle_y)
    $y = $draw_coordinates[$I][1]
    $z = -$draw_coordinates[$I][0] * Sin($angle_y) + $draw_coordinates[$I][2] * Cos($angle_y)

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

    $draw_coordinates[$I][0] = $x
    $draw_coordinates[$I][1] = $y * Cos($angle_x) - $z * Sin($angle_x)
    $draw_coordinates[$I][2] = $y * Sin($angle_x) + $z * Cos($angle_x)
    EndFunc ;==>Calc

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

    Func CubeCalc($angle_x, $angle_y, $I)
    ;calculate Cube 3D rotation
    $CubeX = $cube_coordinates[$I][0] * Cos($angle_y) + $cube_coordinates[$I][2] * Sin($angle_y)
    $CubeY = $cube_coordinates[$I][1]
    $CubeZ = -$cube_coordinates[$I][0] * Sin($angle_y) + $cube_coordinates[$I][2] * Cos($angle_y)

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

    $cube_coordinates[$I][0] = $CubeX
    $cube_coordinates[$I][1] = $CubeY * Cos($angle_x) - $CubeZ * Sin($angle_x)
    $cube_coordinates[$I][2] = $CubeY * Sin($angle_x) + $CubeZ * Cos($angle_x)
    EndFunc ;==>CubeCalc

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

    Func Close()
    _GDIPlus_BrushDispose($hBrush1)
    _GDIPlus_BrushDispose($hBrush2)
    _GDIPlus_PenDispose($hPen)
    _GDIPlus_PenDispose($hPenDash)
    _GDIPlus_PenDispose($hPenDotted)
    _GDIPlus_BitmapDispose($hBitmap)
    _GDIPlus_GraphicsDispose($hBackbuffer)
    _GDIPlus_GraphicsDispose($hGraphics)
    _GDIPlus_Shutdown()
    DllClose($user32_dll)
    Exit
    EndFunc ;==>Close

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

    Func Zoom($factor)
    Local $m
    For $m = 0 To $amout_of_dots - 1
    $draw_coordinates[$m][0] *= $factor
    $draw_coordinates[$m][1] *= $factor
    $draw_coordinates[$m][2] *= $factor
    Next
    For $m = 0 To $amout_of_cube_dots - 1
    $cube_coordinates[$m][0] *= $factor
    $cube_coordinates[$m][1] *= $factor
    $cube_coordinates[$m][2] *= $factor
    Next
    EndFunc ;==>Zoom

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

    Func WM_MOUSEWHEEL($hwnd, $iMsg, $wParam, $lParam)
    Local $wheel_Dir = BitAND($wParam, 0x800000)
    If $wheel_Dir > 0 Then
    If $zoom_counter <= $zoom_max Then
    Zoom(1.05)
    $zoom_counter += 1
    EndIf
    Else
    If $zoom_counter >= $zoom_min Then
    Zoom(0.95)
    $zoom_counter -= 1
    EndIf
    EndIf
    Return "GUI_RUNDEFMSG"
    EndFunc ;==>WM_MOUSEWHEEL

    [/autoit]

    Wenn man das mit Assembler noch beschleunigen könnte, wäre das natürlich der Hammer :thumbup:

  • Was soll ich da noch sagen? TOP :thumbup:

    "Die Pfade" scheinen richtig mächtig zu sein, wenn man weiß, wie sie funktionieren! :whistling:

    Die Direct2D / Direct3D Sachen sind ja auch krass und da ist bereits diese Funktion enthalten, aber der Kick ist es, dass in GDI+ zu implementieren! :D

    Die Symbiose von GDI+ und ASM würde den Turbo einschalten, aber muss man erst mal ASM können...

    Gruß,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • Zitat

    Die Symbiose von GDI+ und ASM würde den Turbo einschalten, aber muss man erst mal ASM können...

    naja, da das Bitmapformat ziemlich einfach ist, bietet sich das "üben" in ASM natürlich an. Ich breche mir auch hin und wieder einen ab, aber im grossen und ganzen braucht man wirklich nur 10 Befehle. GDI+ ist ja nur deshalb so "langsam" weil wirklich idiotensicher und universell. Wenn man das gesamte "Fehlermanagement" in die Wrapperfunktion auslagert, bleibt die eigentliche Pixelmanipulation extrem schlank und damit auch schnell. Ich setz mich mal dran....

    Gerade für 3D-Darstellungen würde sich natürlich die Trapez/Dreieck-Transformation anbieten! Inwieweit sich damit zu D3D oder OpenGl aufschliessen lässt? Schaumamal...wenn die Flächen nicht zu gross werden, sehe ich darin eigentlich kein grösseres Problem 8o

  • So, kurze Rückmeldung....

    Hab bissl Trouble mit der Transformation in die "Schiefheit". Zum Vergleich, das linke von eukalyptus(soll das so sein?), das rechte meins(soll das so sein?).
    Hab mal mehrere mathematische Varianten durchgespielt und als AutoIt-Script laufen lassen. Auf Pixelebene bin ich in AutoIt so schnell wie die Eukalyptus´sche Orginalfunktion beim High Precision Rendering. Um mal ne Hausnummer zu nennen, in Assembler sollte Faktor 100 beim Speed drin sein 8o .
    Bin zzt. ziemlich eingespannt, dazu kommt noch zeitweise Gehirnkrampf (altersbedingt :whistling: ), wäre daher für Tips/Funktionen/Infos dankbar....Welche Variante
    _IconNameToID.au3autoit.de/wcf/attachment/11796/

  • Wie füllt denn ein Malprogramm zu was? Ich kenne mich zu wenig mit Gimp aus.

    Kann jemand mal so ein Trapez zeichnen und es mit dem Bild füllen?

    Gruß,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • Andy.
    Man sieht direkt welches Programm auf was Wert legt.
    Bei dir wird das Gesicht schön vergrößert... und bei eukalyptus eher die Oberweite.^^

  • ...
    Bei dir wird das Gesicht schön vergrößert... und bei eukalyptus eher die Oberweite.^^

    :D

    Meine Version (bzw. die Gimp Version) ist perspektivisch korrekt und kann als 3D-Texture verwendet werden.

    Ich hab auch noch folgende Variante probiert:
    Ich fülle einen GDIPlus-Path wieder mit Werten (1 Rechteck 1x1 pro Pixel)
    Verzerre diesen Path und fülle die entstandenen Trapeze mit der original Farbe

    Ist zwar ohne Antialiasing, sollte jedoch leichter umzusetzen sein

    Mit einem kleinen Bild probieren...

    Spoiler anzeigen
    [autoit]

    Func _GDIPlus_GraphicsDrawImage_4Points($hGraphics, $hImage, $X1, $Y1, $X2, $Y2, $X3, $Y3, $X4, $Y4)
    ;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]

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

    Local $iW = _GDIPlus_ImageGetWidth($hImage)
    Local $iH = _GDIPlus_ImageGetHeight($hImage)

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

    For $Y = 0 To $iH - 1
    For $X = 0 To $iW - 1
    DllCall($ghGDIPDll, "uint", "GdipAddPathRectangle", "hwnd", $hPath, "float", $X, "float", $Y, "float", 1, "float", 1)
    Next
    Next

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

    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, 8)

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

    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)

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

    Local $iCnt = $iW * $iH * 4
    Local $tPoints = DllStructCreate("float[" & $iCnt * 2 & "]")
    Local $pPoints = DllStructGetPtr($tPoints)
    DllCall($ghGDIPDll, "uint", "GdipGetPathPoints", "hwnd", $hPath, "ptr", $pPoints, "int", $iCnt)

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

    Local $tRectF = DllStructCreate("float X;float Y;float Width;float Height")
    DllCall($ghGDIPDll, "uint", "GdipGetPathWorldBounds", "hwnd", $hPath, "ptr", DllStructGetPtr($tRectF), "hwnd", 0, "hwnd", 0)

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

    DllCall($ghGDIPDll, "uint", "GdipDeletePath", "hwnd", $hPath)

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

    Local $iNW = DllStructGetData($tRectF, 1) + DllStructGetData($tRectF, 3)
    Local $iNH = DllStructGetData($tRectF, 2) + DllStructGetData($tRectF, 4)
    Local $hBitmap = _GDIPlus_BitmapCreateFromGraphics($iNW, $iNH, $hGraphics)
    Local $hContext = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    Local $hBrush = _GDIPlus_BrushCreateSolid(0xFF000000)

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

    Local $BitmapData = _GDIPlus_BitmapLockBits($hImage, 0, 0, $iW, $iH, $GDIP_ILMREAD, $GDIP_PXF32ARGB)
    Local $Stride = DllStructGetData($BitmapData, "Stride")
    Local $Width = DllStructGetData($BitmapData, "Width")
    Local $Height = DllStructGetData($BitmapData, "Height")
    Local $Scan0 = DllStructGetData($BitmapData, "Scan0")
    Local $PixelData
    Local $iOff = 0
    For $row = 0 To $Height - 1
    $PixelData = DllStructCreate("dword[" & $Width & ']', $Scan0 + ($row * $Stride))
    For $col = 0 To $Width - 1
    DllCall($ghGDIPDll, "int", "GdipSetSolidFillColor", "handle", $hBrush, "dword", DllStructGetData($PixelData, 1, $col + 1))
    DllCall($ghGDIPDll, "uint", "GdipFillPolygon2", "hwnd", $hContext, "hwnd", $hBrush, "ptr", $pPoints + $iOff, "int", 4)
    $iOff += 32
    Next
    Next
    _GDIPlus_BitmapUnlockBits($hImage, $BitmapData)

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

    _GDIPlus_BrushDispose($hBrush)
    _GDIPlus_GraphicsDispose($hContext)
    _GDIPlus_GraphicsDrawImage($hGraphics, $hBitmap, 0, 0)
    _GDIPlus_BitmapDispose($hBitmap)
    EndFunc ;==>_GDIPlus_GraphicsDrawImage_4Points

    [/autoit]

    E

  • Zitat

    Verzerre diesen Path und fülle die entstandenen Trapeze mit der original Farbe

    hehe, genau das macht ja GdipWarpPath^^. Das soll ja ersetzt werden....
    Wenn ich das "zu Fuss" transferiere, komme ich ohne Winkelfunktionen nicht aus!
    Bei meiner im Bild dargestellten Transformation werden nur +-*/ verwendet, daher ist das sauschnell!

    Aber natürlich ist Ziel, perspektivisch korrekt darzustellen! Ggf reicht es, die Werte der Sinus/Cosinus in eine LUT zu schreiben, und diese zu benutzen. Siehe Assemblerbeispiel Tunnelflug, das ist dann vielleicht nicht bis auf die 8. Kommastelle genau, aber bei Bildern sollte man das verkraften können, bei bewegten Bildern erst recht!
    Naja, Wochenende naht, ich setz mich nachts mal dran, hat schon wer "zu Fuss" Transformationsfunktionen? Ich habe mir selbst welche aus den Fingern gesogen, bin daher betriebsblind, da ich immer die gleichen Vorraussetzungen ansetze!

    ciao
    Andy


    "Schlechtes Benehmen halten die Leute doch nur deswegen für eine Art Vorrecht, weil keiner ihnen aufs Maul haut." Klaus Kinski
    "Hint: Write comments after each line. So you can (better) see what your program does and what it not does. And we can see what you're thinking what your program does and we can point to the missunderstandings." A-Jay

    Wie man Fragen richtig stellt... Tutorial: Wie man Script-Fehler findet und beseitigt...X-Y-Problem

    3 Mal editiert, zuletzt von Andy (19. November 2010 um 13:46)

  • Oh, mfg....ich habs....ohne Winkelfunktionen, nur simple Verhältnsrechnung...heute Abend/Nacht in AutoIt, morgen bin ich unterwegs, aber spätestens am Sonntag in Assembler. 8o

  • Naja, Wochenende naht, ich setz mich nachts mal dran, hat schon wer "zu Fuss" Transformationsfunktionen?


    Ansatz für die Transformationsgleichung:[Blockierte Grafik: http://img529.imageshack.us/img529/962/entzerrungsansatz.png]
    Es sind also 8 Parameter nötig.
    Mit 4 Passpunkten a 2 Koordinaten ist das Gleichungssystem bestimmt.
    Lösungsweg wäre dann (wahrscheinlich denke ich aber zu kompliziert):

    • Gleichungen linearisieren (partielle Differentation auf die jeweiligen Parameter und das ganze in einer Normalgleichungsmatrix zusammenfassen)
    • Ausgleichung nach Methode der kleinsten Quadrate (kann man sich sicherlich schenken da wir keine Überbestimmung haben).
    • Mit den gewonnenen Werten für die Parameter haben wir eine allgemeingültige Transformationsgleichung mit welcher wir Pixelweise durchgehen und die Farbwerte durch Resampling (bikubisch, bilinear etc.) ermitteln.

    So läuft in der Photogrammetrie eine Ebenenentzerrung ab was im Prinzip nichts anderes als dass hier ist nur mit dem Unterschied dass da meistens eine Überbestimmung an Passpunkten existiert und wir damit auch Genauigkeiten und Zuverlässigkeitsmaße ableiten können.
    Hab grad wenig Zeit für sowas sonst hätte es mich schon gejuckt das ganze auch mal umzusetzen.

  • Hallo Aspirin Junkie!
    Deine Gleichungen hatte ich auch schon gefunden, allerdings ist das bei mir mit der partiellen Differentation schon etwas her...
    In einem anderen Manuskript fand ich folgende Gleichungen, mit meinen eigenen Transformationsgleichungen bin ich auch nicht viel weiter gekommen

    xs = C1 * x + C2 * y + C3 * xy + C4
    ys = C5 * x + C6 * y + C7 * xy + C8

    wird also zu

    xs = C1 * x + C2 * y + C3 * xy + C4 * 1 + C5 * 0 + C6 * 0 + C7 * 0 + C8 * 0
    ys = C1 * 0 + C2 * 0 + C3 * 0 + C4 * 0 + C5 * x + C6 * y + C7 * xy + C8 * 1

    Den Löser für lineare Gleichungssysteme hab ich bereits geschrieben, bissl was geht also :rolleyes:
    Leider kommt bei obiger Formel sowas raus^^(einmal mit und einmal ohne "Viereckmaske")
    autoit.de/wcf/attachment/11822/autoit.de/wcf/attachment/11823/....ich bleib am Ball

    /EDIT/
    Ich habe sogar eine Zeichnerische Lösung herausgefunden, allerdings transformiert diese das( bzw alle) Pixel aus dem Orginalbild ins verzerrte Bild. Man kann allerdings nicht "rückwärts" von einem Pixel im verzerrten Bild auf das pixel im Orginal schliessen (da will ich ja hin)
    Die zeichnerische Lösung umgesetzt in ein Programm würde mit reichlich Winkelfunktionen arbeiten, ist allerdings perspektivisch korrekt und würde einige (viele) Pixel mehrfach berechnen.

  • AspirinJunkie
    hab deine Formeln mal umgestellt:

    xs = a1*x + a2*y + a3 - a7*x*xs - a8*y*xs
    wird zu
    xs = a1*x + a2*y + a3 + a4*0 + a5*0 + a6*0 - a7*x*xs - a8*y*xs
    äquivalent dazu ys (du hast einen Schreibfehler , es soll sicher heissen a4*x' in der 2. Gleichung)
    ys = a1*0 + a2*0 + a3*0 + a4*x + a5*y + a6 - a7*x*ys - a8*y*ys

    und damit die 8x8-Matrix aufgebaut, Gleichungen gelöst, in obige Formeln eingesetzt.....tadaaaa
    autoit.de/wcf/attachment/11825/

    /EDIT/ Assemblerscript dauert noch, Essen ist wichtiger 8o

  • Kurze Umfrage an die GDI+-Freaks unter euch.
    Wie bzw in welcher Form (mit welchem GDI+-Befehl) würdet ihr am liebsten (ggf gibts Gründe) eine per Assembler bearbeitete Grafik in ein Fenster bringen.

    Folgender Hintergrund: Ich bearbeite die einzelnen Pixel in einer bis dato "leeren" Bitmap. Als Fan des blittens bringe ich die Grafik(en) so relativ einfach in ein Fenster, auch mit Transparenz.
    Da ihr aber auch mit Alphablending und anderen GDI+-Goodies arbeitet, wäre es sinnvoll, direkt die schon in GDI+ vorliegenden Bitmaps zu verwenden. Mir ist es egal, an welche Speicheradresse ich die "Pixel" schreibe, leider hält sich die GDI mit der Herausgabe von bestehenden (Bitmap)StartAdressen sehr dezent zurück....und genau diese Adressen brauche ich in Assembler.

    Zzt. erstelle ich eine "leere" Bitmap und erhalte den DC, den Pointer auf die "Pixel"(Bitmap) und ein Handle auf diese Bitmap.

    [autoit]

    $hdc_buffer=_CreateNewBmp32($width,$height,$ptr_buffer (byref), $hbmp_buffer (byref)) ;meine eierlegende Wollmilchsau
    ;per $ptr_buffer kann ich mit den "Pixeln" rumspielen nach belieben (in Assembler)
    $hGraphic = _GDIPlus_GraphicsCreateFromHDC($hdc_buffer) ;Graphics erstellen aus DC
    _GDIPlus_GraphicsDrawline($hGraphic, 1, 1,70,70,$hpen) ; malen in dieser per Assembler bearbeiteten "Bitmap"

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

    $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hBMP_buffer) ;per Handle die hBitmap nach belieben verarbeiten
    _GDIPlus_ImageSaveToFile($hbitmap, "GDIPlus_Image.jpg")

    [/autoit]

    Weiter bin ich noch nicht gekommen, reicht das? Bzw. wie müsste ein "GDI+-kompatibler Bitmapbearbeitungsbefehl" aussehen?
    Bei einer schon bestehenden_GDIPlus_Graphics() könnte ich mir den DC holen, und dort die Veränderung reinblitten. Das geht, leider aber auf Kosten der Geschwindigkeit. Ist nicht die Welt, aber wieso mehrfach unnötig Speicher verschieben und verknüpfen, wenn man direkt im Ziel die Bitmap verändern könnte?
    Kann genausogut sein, dass dieser Weg von der GDI vorgesehen ist, dann mach ich das so......

  • Hi Andy,

    da ich und auch die anderen mit dem Backbuffer arbeiten,

    [autoit]


    $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    $hBitmap = _GDIPlus_BitmapCreateFromGraphics($iX, $iY, $hGraphics)
    $hBackbuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)

    [/autoit]


    wäre es klasse, wenn wir das Bild auch direkt in den Backbuffer ($hBackbuffer) schreiben könnten!

    Geht das?

    Gruß,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯