GDI+ Bitmap "trapezoid" zeichnen / DrawImage_4Points

  • OK,
    dann hole ich mir den Pointer und $hBmp_buffer über CreateNewBitmap32($ix,$iy,$Ptr_buffer,$hBmp_buffer), welches dann

    [autoit]

    $hBitmap = _GDIPlus_BitmapCreateFromGraphics($iX, $iY, $hGraphics)

    [/autoit]

    ersetzt, und ihr könnt euch per

    [autoit]

    $hImage = _GDIPlus_BitmapCreateFromHBITMAP($hBmp_buffer)
    $hBackbuffer = _GDIPlus_ImageGetGraphicsContext($hImage)

    [/autoit]

    den $hBackbuffer holen? Ist das so ok?

    Danach könnte man z.B. eine Funktion _Rect_to_Trapezoid($aEckpunkteRect[],$aEckpunkte_Trapezoid,$ix,$iy,$ptr_buffer) aufrufen, welche direkt in den Backbuffer schreibt.

    Btw, in CreateNewBitmap32() werden nur AutoIt-Funktionen verwendet.

    Nächste Frage:
    Durch bestimmte Prozessorbefehle (MMX/SSE), die ab den P3/P4 implementiert wurden, kann die Grafikberechnung wesentlich beschleunigt werden. Kann ich vorraussetzen, dass nur Prozessoren neuer als P3 (also ab P4) eingesetzt werden? Immerhin hat diese schon 10 Jahre alte Technik in den neuesten Linuxkernel Einzug gehalten. Auch die "großen" Bildbe(ver)arbeitungs-Softwarepakete setzen in den neuesten Versionen nun endlich diese uralten Prozessor-Befehle ein. Heureka, die Software tappert 10 Jahre hinter der Hardware her...

    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 (24. November 2010 um 09:56)

  • Wir sollten P4+ voraussetzen!

    Gruß,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • Hab was für euch, bin zufrieden...

    [autoit]

    $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    $hBitmap = _GDIPlus_BitmapCreateFromGraphics($iX, $iY, $hGraphics)
    $hBackbuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap) ;bisher wie gehabt
    _GDIPlus_GraphicsDrawLine($hbackbuffer, 20,50, 50, 0, $hPen) ;in backbuffer zeichnen

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

    _func_blablub($hbitmap, para1,para2.....) ;ASM- prog schreibt/verändert backbuffer

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

    _GDIPlus_GraphicsDrawImage($hGraphics, $hbitmap, 0, 0) ;backbuffer in gui

    [/autoit]

    so braucht sich keiner zu verbiegen, und ggf. bestehende und zu ersetzende GDI+-Funktionen können einfach ausgetauscht werden.
    Und ich habe eine "saubere" Schnittstelle ins GDI :D

    jetzt fehlt nur noch der ASM-Code für eukalyptus´ Funktion.... :whistling:;(

  • Ja dann, jetzt wird in die Hände gespuckt...

    Gruß,
    UEZ

    PS: ich wünschte, ich könnte dich in ASM unterstützen, abgesehen davon, dass ich wieder momentan voll ausgelastet und keine große Hilfe in ASM bin...

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • Zitat

    dass ich wieder momentan voll ausgelastet und keine große Hilfe in ASM bin...

    hehe, ausgelastet bin ich zzt. voll, ich knabbere mich Viertelstundenweise durch^^
    Du wirst dich wundern, der eigentliche ASM-code ist supersimpel!

    [autoit]

    for u=xmin to xmax
    for v=ymin to ymax
    x=f(u,v) ; siehe formeln
    y=f(u,v)
    col=f(x,y)
    setpixel(u,v,col)
    next
    next

    [/autoit]

    den kompletten Rest lasse ich in Autoit, die Lösung der 8 Gleichungen mit 8 Unbekannten und die Transformation bzw. gesamte Berechnung der Umgebung ist in 2-3 Millisekunden gemacht, dafür schreibe ich keinen ASM-Code!
    Die o.g. Schleife dauert per dllstructsetdata() in AutoIt 2-3 Sekunden! DA ist dann Potenzial, hehe 8o

  • sodele, erste lauffähige ASM-Version, unoptimiert! Gebraucht werden zzt. noch die FASM.au3 und AssembleIt.au3.

    Ich hab die Schnittstelle zu GDI jetzt so gelöst wie bereits beschrieben, ziemlich "sauber".
    d.h. ihr könnt einfach eukalyptus´Funktion
    _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)
    mit
    _projective_mapping($hBmpBuffer, $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])
    ersetzen! Wenn DAS nicht fein ist :D

    Was mich ehrlich gesagt bissl aufregt, ist die Schwierigkeit, an einen Pointer zu den Pixeln einer HBITMAP zu kommen.
    In GDI+ gibts da mehrere Möglichkeiten, alle bis auf _GDIPlus_BitmapLockBits legen Kopien der Bitmp an.
    Ich weiss nicht was _GDIPlus_BitmapLockBits grossartig macht, aber es ist alles andere als performant! Habs interessehalber mal durchgespielt, bei grossen Bitmaps dauert es die Hälfte der Zeit zu locken(+unlocken), die andere Hälfte geht für den gesamten restlichen AutoIt-Code drauf! Inclusive der Berechnung der 8 Unbekannten + sämtliche Initialisierungen.

    Der Assemblercode schreibt nur die Pixel in den Buffer (wie gesagt noch unoptimiert). Probiert mal aus, und schreibt, was man noch verbessern könnte/sollte.
    Ich setz mich mal dran und bringe den ASM-Code in eine Form, bei der man keine weiteren ASM-Includes und den ASM-Quellcode (FASM.au3) mehr braucht.

    Btw, die Funktion _solve_linear_quad($a, $b) ist ein von mir erstellter Gleichungslöser für lineare quadratische Gleichungssysteme. Erst wollte ich den auch in Assembler schreiben, aber der geht auch in AutoIt-Code superfix!
    100 Gleichungen mit 100 Unbekannten löst er auch ^^

    Spoiler anzeigen
    [autoit]

    #include <GDIPlus.au3>
    #include <WinAPI.au3>
    #include <WindowsConstants.au3>
    #include <GDIPlusConstants.au3>
    #include <StructureConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <array.au3>
    #include <GDIConstants.au3>
    #include <AssembleIt.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]]
    Global $aDrag[5][2] = [[0, 0],[35, 100],[100, 35],[750, 350],[110, 380]]

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

    Global $minx, $miny, $maxx, $maxy, $struct_float, $ptr_Hintergrund, $b, $b_buffer, $struct_buffer, $h
    Global $b_buffer = 800, $h_buffer = 540, $struct_koord

    [/autoit] [autoit][/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($b_buffer, $h_buffer, $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)")
    ;$sfile = "mona-lisa.jpg"
    $hImage = _GDIPlus_ImageLoadFromFile($sFile)
    Global $iwidth, $iheight
    Local $ptr_Hintergrund
    Local $hDC_Hintergrund = getDCfromfile($sFile, $ptr_Hintergrund) ;GDI+ lädt auch jpg

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

    Global $struct = DllStructCreate("dword[" & $iwidth * $iheight & "]", $ptr_Hintergrund)
    ;global $himagefile="mona-lisa.jpg"

    [/autoit] [autoit][/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
    Sleep(100)
    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]

    Func _projective_mapping($hbitmap_1, $hImage, $1x, $1y, $2x, $2y, $3x, $3y, $4x, $4y) ;eck-koordinaten projektion, obere linke und untere rechte Ecke Orginal

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

    $b = _GDIPlus_ImageGetWidth($hImage)
    $h = _GDIPlus_ImageGetHeight($hImage)

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

    $u = 0 ;koordinaten oben rechts im $image
    $v = 0

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

    $BitmapData = _GDIPlus_BitmapLockBits($hbitmap_1, 0, 0, $b_buffer, $h_buffer, BitOR($GDIP_ILMREAD, $GDIP_ILMWRITE), $GDIP_PXF32ARGB)

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

    If @error Then MsgBox(0, "", "Error locking region " & @error)
    Global $ptr_buffer = DllStructGetData($BitmapData, "Scan0");Scan0 - Pointer to the first (index 0) scan line of the bitmap.
    Global $struct_buffer = DllStructCreate("dword [" & $b_buffer * $h_buffer & "]", $ptr_buffer)

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

    Dim $bl[8] = [$u, $b, $b, $u, $v, $v, $h, $h] ;lösungen der 8 Gleichungen (Eck-Koordinaten Orginalbild)
    Dim $a[8][8] = [ _ ;8 gleichungen in Matrix
    [$1x, $1y, 1, 0, 0, 0, -$1x * $u, -$1y * $u], _ ;Eckpunkte Transformiertes Rechteck
    [$2x, $2y, 1, 0, 0, 0, -$2x * $b, -$2y * $b], _
    [$3x, $3y, 1, 0, 0, 0, -$3x * $b, -$3y * $b], _ ;Eckpunkte Transformiertes Rechteck
    [$4x, $4y, 1, 0, 0, 0, -$4x * $u, -$4y * $u], _
    [0, 0, 0, $1x, $1y, 1, -$1x * $v, -$1y * $v], _ ;Eckpunkte Transformiertes Rechteck
    [0, 0, 0, $2x, $2y, 1, -$2x * $v, -$2y * $v], _
    [0, 0, 0, $3x, $3y, 1, -$3x * $h, -$3y * $h], _ ;Eckpunkte Transformiertes Rechteck
    [0, 0, 0, $4x, $4y, 1, -$4x * $h, -$4y * $h]]

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

    $s = _solve_linear_quad($a, $bl) ;8 lineare Gleichungen lösen
    ; _arraydisplay($s)
    $struct_float = DllStructCreate("float [8]") ;die 8 variablen in struct
    For $I = 1 To 8
    DllStructSetData($struct_float, 1, $s[$I - 1], $I)
    Next
    ;geraden 4-1 und 3-2 y=mx+b
    $m1 = ($4y - $1y) / ($4x - $1x)
    $b1 = $1y - $m1 * $1x

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

    $m2 = ($3y - $2y) / ($3x - $2x)
    $b2 = $2y - $m2 * $2x
    ;geraden 1-2 und 3-4 y=mx+b
    $m3 = ($2y - $1y) / ($2x - $1x)
    $b3 = $1y - $m3 * $1x

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

    $m4 = ($3y - $4y) / ($3x - $4x)
    $b4 = $3y - $m4 * $3x

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

    $struct_koord = DllStructCreate("uint[8]"); struct für die x- und y-koordinaten

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

    ;kleinstes und grösstes x und y finden, um nicht die gesamte bitmap durchzurechnen, sondern
    ;nur den Teil, der von dem quadrilateral belegt ist
    Global $minx = 1e9, $miny = 1e9, $maxx = 0, $maxy = 0
    For $I = 1 To 4
    DllStructSetData($struct_koord, 1, Eval($I & "x"), $I * 2 - 1);struct füllen
    DllStructSetData($struct_koord, 1, Eval($I & "y"), $I * 2);1x,1y,2x,2y,3x...

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

    If Eval($I & "x") < $minx Then $minx = Eval($I & "x");minimum und maximum finden
    If Eval($I & "x") > $maxx Then $maxx = Eval($I & "x")
    If Eval($I & "y") > $maxy Then $maxy = Eval($I & "y")
    If Eval($I & "y") < $miny Then $miny = Eval($I & "y")
    Next

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

    $ret = _AssembleIt("float", "_quadrilateral")
    ; MsgBox(262144,'Debug line ~' & @ScriptLineNumber,'Selection:' & @lf & '$ret' & @lf & @lf & 'Return:' & @lf & $ret) ;### Debug MSGBOX

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

    ;folgende Zeilen in AutoItcode sind genau so in Assembler überführt
    ;~ For $py = $miny To $maxy Step 5
    ;~ For $px = $minx To $maxx Step 5
    ;~ ;ist y<mx+b , dann
    ;~ If $4x > $1x And $m1 * $px + $b1 < $py Then ContinueLoop ;grösser = unter der linie
    ;~ If $4x < $4x And $m1 * $px + $b1 > $py Then ContinueLoop ;grösser = unter der linie
    ;~ If $3x > $2x And $m2 * $px + $b2 > $py Then ContinueLoop ;grösser = unter der linie
    ;~ If $3x < $2x And $m2 * $px + $b2 < $py Then ContinueLoop ;grösser = unter der linie
    ;~ $X = int(($s[0] * $px + $s[1] * $py + $s[2]) / ($s[6] * $px + $s[7] * $py + 1))
    ;~ $Y = int(($s[3] * $px + $s[4] * $py + $s[5]) / ($s[6] * $px + $s[7] * $py + 1))
    ;~ If $X < 0 Or $Y < 0 Then ContinueLoop
    ;~ If $X * $Y > $b * $h Then ContinueLoop
    ;~ $col = DllStructGetData($struct, 1, $Y * $b + $X) ;farbe aus bild holen
    ;~ DllStructSetData($struct_buffer, 1, $col, ($py -1) * $b_buffer + $px)
    ;~ Next
    ;~ Next
    ;~ $t = TimerInit()
    $a = _GDIPlus_BitmapUnlockBits($hbitmap_1, $BitmapData)

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

    EndFunc ;==>_projective_mapping

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

    Func _quadrilateral()
    _("use32")
    _("org " & FasmGetBasePtr($Fasm))
    _("jmp _los")
    _("align 4")
    ; _("_speicher:")
    _("_px dd 0")
    _("_py dd 0")
    _("_x dd 0")
    _("_y dd 0")
    _("_b_buffer dd 0")
    _("_m1 dd 0.0") ;y=m*x+b geradengleichung
    _("_m2 dd 0.0") ;m=(x2-x1)/(y2-y1)
    _("_b1 dd 0.0") ;b=y-m*x
    _("_b2 dd 0.0")

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

    _("_los:")

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

    _("finit") ;coproinit
    ;geradengleichung wird gebraucht, um festzustellen, ob das aktuelle
    ;pixel innerhalb der zu zeichnenden fläche liegt
    ;$m1 = ($4y - $1y) / ($4x - $1x)
    _("mov ecx," & DllStructGetPtr($struct_koord));koordinaten
    _("fild dword[ecx+4*7]") ;st0=4y
    _("fisub dword[ecx+4*1]") ;st0=(4y-1y)
    _("fild dword[ecx+4*6]") ;st0=4x st1=(4y-1y)
    _("fisub dword[ecx+4*0]") ;st0=(4x-1x)
    _("fdivp") ;st0=m1
    _("fst dword[_m1]") ;st0=m1

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

    ;$b1 = $1y - $m1 * $1x
    _("fimul dword[ecx+4*0]") ;st0=m1*1x
    _("fisubr dword[ecx+4*1]") ;st0=1y-m1*1x = b1
    _("fstp dword[_b1]") ;b1 speichern, fpstack clean

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

    ;$m2 = ($3y - $2y) / ($3x - $2x)
    _("fild dword[ecx+4*5]") ;st0=3y
    _("fisub dword[ecx+4*3]") ;st0=(3y-2y)
    _("fild dword[ecx+4*4]") ;st0=3x st1=(3y-2y)
    _("fisub dword[ecx+4*2]") ;st0=(3x-2x)
    _("fdivp") ;st0=m2
    _("fst dword[_m2]") ;st0=m2
    ;$b2 = $2y - $m2 * $2x
    _("fimul dword[ecx+4*2]") ;st0=m2*2x
    _("fisubr dword[ecx+4*3]") ;st0=2y-m2*2x = b2
    _("fstp dword[_b2]") ;b2 speichern, fpstack clean
    _("")

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

    ;variablen in speicher schreiben
    _("mov eax," & $b_buffer)
    _("mov dword[_b_buffer],eax")
    ;register mit den laufvariablen laden
    _("mov edx," & $miny - 1) ;for ymin to ymax
    _("mov esi," & $ptr_Hintergrund) ;pointer auf orginal bitmap
    _("mov edi," & DllStructGetPtr($struct_buffer));pointer auf den backbuffer
    _("mov ebx," & DllStructGetPtr($struct_float));die 8 variablen

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

    _(".start:") ;hier gehts los

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

    _(".y_loop:") ;for py=ymin to ymax
    _("add edx,1") ;py
    _("cmp edx," & $maxy)
    _("jae .ende")
    _("mov ecx," & $minx - 1)

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

    _(".x_loop:") ;for px=xmin to xmax
    _("add ecx,1") ;px
    _("cmp ecx," & $maxx) ;ist maxx erreicht?
    _("jae .y_loop") ;ja, dann next py

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

    _("mov dword[_py],edx")
    _("mov dword[_px],ecx") ;abspeichern 17
    _("")
    _("jmp .is_pixel_inside_quadrilateral") ;prüfen, ob pixel in der fläche ist
    _(".pixelinside:")
    _("")
    _("")
    _("")
    _("fild dword[_py]") ;st0=py
    _("fild dword[_px]") ;st0=px st1=py

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

    ;x=int($s[0] * $px + $s[1] * $py + $s[2]) / ($s[6] * $px + $s[7] * $py + 1) bissl floatingpoint
    _("fld dword[ebx+4*0]") ;st0=s[0] st1=px st2=py
    _("fmul st0,st1") ;st0=s[0]*px
    _("fld dword[ebx+4*1]") ;st0=s[1] st1=s[0]*px st2=px st3=py
    _("fmul st0,st3") ;st0=s[1]*py st1=s[0]*px st2=px st3=py
    _("faddp") ;st0=s[1]*py+s[0]*px st1=px st2=py
    _("fadd dword[ebx+4*2]") ;st0=s[1]*py+s[0]*px+s[2] st1=px st2=py
    _("fld dword[ebx+4*6]") ;st0=$s[6] st1=s[1]*py+s[0]*px+s[2] st2=px st3=py
    _("fmul st0,st2") ;st0=$s[6]*px st1=s[1]*py+s[0]*px+s[2] st2=px st3=py
    _("fld dword[ebx+4*7]") ;st0=s[7] st1=$s[6]*px st2=s[1]*py+s[0]*px+s[2] st3=px st4=py
    _("fmul st0,st4") ;st0=s[7]* py st1=$s[6]*px st2=s[1]*py+s[0]*px+s[2] st3=px st4=py
    _("faddp ") ;st0=s[7]*py+$s[6]*px st1=s[1]*py+s[0]*px+s[2] st1=px st2=py
    _("fld1")
    _("faddp ") ;st0=s[7]*py+$s[6]*px+1 st1=s[1]*py+s[0]*px+s[2] st2=px st3=py
    _("fdivp") ;st0=x st1=px st2=py
    _("fistp dword[_x]") ;abspeichern als integer st0=px st1=py
    _("")
    ;$Y = Int(($s[3] * $px + $s[4] * $py + $s[5]) / ($s[6] * $px + $s[7] * $py + 1))
    _("fld dword[ebx+4*3]") ;st0=s[3] st1=px st2=py
    _("fmul st0,st1") ;st0=s[3]*px
    _("fld dword[ebx+4*4]") ;st0=s[4] st1=s[3]*px st2=px st3=py
    _("fmul st0,st3") ;st0=s[4]*py st1=s[3]*px st2=px st3=py
    _("faddp") ;st0=s[4]*py+s[3]*px st1=px st2=py
    _("fadd dword[ebx+4*5]") ;st0=s[4]*py+s[3]*px+s[5] st1=px st2=py
    _("fld dword[ebx+4*6]") ;st0=$s[6] st1=s[4]*py+s[3]*px+s[5] st2=px st3=py
    _("fmul st0,st2") ;st0=$s[6]*px st1=s[4]*py+s[3]*px+s[5] st2=px st3=py
    _("fld dword[ebx+4*7]") ;st0=s[7] st1=$s[6]*px st2=st1=s[4]*py+s[3]*px+s[5] st3=px st4=py
    _("fmul st0,st4") ;st0=s[7]* py st1=$s[6]*px st2=st1=s[4]*py+s[3]*px+s[5] st3=px st4=py
    _("faddp ") ;st0=s[7]*py+$s[6]*px st1=st1=s[4]*py+s[3]*px+s[5] st1=px st2=py
    _("fld1")
    _("faddp ") ;st0=s[7]*py+$s[6]*px+1 st1=st1=s[4]*py+s[3]*px+s[5] st2=px st3=py
    _("fdivp") ;st0=y st1=px st2=py
    _("fistp dword[_y]") ;abspeichern als integer st0=px st1=py 50
    _("FUCOMPP") ;pop, pop => stack clean!

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

    ;$col = DllStructGetData($struct, 1, $Y * $b + $X) ;farbe aus bild holen
    _("mov eax," & $b)
    _("push edx") ;sichern
    _("mul dword[_y]") ;eax=$b*y
    _("add eax,dword[_x]") ;eax=$b*y+x
    _("pop edx") ;

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

    _("test eax, 10000000000000000000000000000000b") ;zahl positiv?
    _("jnz .x_loop") ;wenn negativ, jump

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

    _("cmp eax," & $b * $h - $b) ;addresse grösser als bitmap?
    _("ja .x_loop")

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

    _("shl eax,2") ;4 byte = 1 pixel! daher anzahl der byte vervierfachen
    _("mov eax,dword[esi+eax*1]") ;pixelfarbe holen aus ursprungsbitmap
    _("push eax") ;pixelfarbe sichern

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

    ;DllStructSetData($struct_buffer, 1, $col, ($py - 1) * $b_buffer + $px)
    _("mov eax,dword[_py]")
    _("sub eax,1") ;eax=py-1
    _("push edx") ;sichern
    _("mul dword[_b_buffer]")
    _("pop edx") ;sichern
    _("add eax,dword[_px]") ;eax=($py - 1) * $b_buffer + $px
    _("test eax, 10000000000000000000000000000000b") ;zahl positiv?
    _("jnz .popeax")
    ;_("ret")
    ;~ _("cmp eax,"&$maxy*$maxx-$maxy)
    ;~ ; ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $b*$h = ' & $b*$h & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
    ;~ _("ja .popeax")

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

    _("mov edi," & DllStructGetPtr($struct_buffer));pointer auf den backbuffer
    _("shl eax,2") ;4 byte = 1 pixel! daher anzahl der byte vervierfachen
    _("add edi,eax") ;edi=adresse pixel im buffer
    _("pop eax") ;farbe holen
    _("mov [edi],eax") ;pixel in buffer schreiben
    _("jmp .x_loop") ;next x
    _("")
    _(".ende:")
    _("ret")

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

    _("")
    _(".popeax:")
    _("pop eax")
    _("jmp .x_loop")

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

    _(".is_pixel_inside_quadrilateral:")
    ;prüfen ob pixel in der fläche liegt
    _("push eax")
    _("push ecx")
    _("mov ecx," & DllStructGetPtr($struct_koord));koordinaten
    ;~If $4x>$1x and $m1 * $px + $b1 < $py Then ContinueLoop ;ist punkt ausserhalb der fläche, dann nächstes px
    _("mov eax,dword[ecx+4*6]") ;eax=4x
    _("cmp eax,dword[ecx+4*0]") ;ist $4x>$1x
    _("jb @f") ;wenn kleiner, ein label weiter
    _("fld dword[_m1]") ;$m1 * $px + $b1
    _("fimul dword[_px]")
    _("fadd dword[_b1]")
    _("fistp dword[_y]") ;y=$m1 * $px + $b1
    _("mov eax,dword[_y]")
    _("test eax, 10000000000000000000000000000000b") ;zahl positiv?
    _("jnz .weiter") ;wenn negativ, dann nächstes px
    _("cmp eax,dword[_py]") ;ist y<py?
    _("jb .weiter") ;wenn py grösser, dann nächstes px
    _("@@:")
    ;If $4x<$1x and $m1 * $px + $b1 > $py Then ContinueLoop ;ist punkt ausserhalb der fläche, dann nächstes px
    _("mov eax,dword[ecx+4*6]") ;eax=4x
    _("cmp eax,dword[ecx+4*0]") ;ist $4x<$1x
    _("ja @f") ;wenn grösser, ein label weiter
    _("fld dword[_m1]") ;$m1 * $px + $b1
    _("fimul dword[_px]")
    _("fadd dword[_b1]")
    _("fistp dword[_y]") ;y=$m1 * $px + $b1
    _("mov eax,dword[_y]")
    _("test eax, 10000000000000000000000000000000b") ;zahl positiv?
    _("jnz @f") ;wenn negativ, dann nächstes px
    _("cmp eax,dword[_py]") ;ist py<y?
    _("ja .weiter") ;wenn py kleiner, dann nächstes px
    _("@@:")
    ;If $3x>$2x and $m2 * $px + $b2 > $py Then ContinueLoop ;ist punkt ausserhalb der fläche, dann nächstes px
    _("mov eax,dword[ecx+4*4]") ;eax=3x
    _("cmp eax,dword[ecx+4*2]") ;ist $3x>$2x
    _("jb @f") ;wenn kleiner, ein label weiter
    _("fld dword[_m2]") ;$m2* $px + $b2
    _("fimul dword[_px]")
    _("fadd dword[_b2]")
    _("fistp dword[_y]") ;
    _("mov eax,dword[_y]")
    _("test eax, 10000000000000000000000000000000b") ;zahl positiv?
    _("jnz @f") ;wenn negativ, dann
    _("cmp eax,dword[_py]") ;ist y<py?
    _("ja .weiter") ;wenn py kleiner, dann nächstes px
    _("@@:")
    ;If $3x<$2x and $m2 * $px + $b2 < $py Then ContinueLoop ;ist punkt ausserhalb der fläche, dann nächstes px
    _("mov eax,dword[ecx+4*4]") ;eax=3x
    _("cmp eax,dword[ecx+4*2]") ;if $3x<$2x
    _("ja @f") ;wenn kleiner, ein label weiter
    _("fld dword[_m2]") ;$m2 * $px + $b2
    _("fimul dword[_px]")
    _("fadd dword[_b2]")
    _("fistp dword[_y]") ;
    _("mov eax,dword[_y]")
    _("test eax, 10000000000000000000000000000000b") ;zahl positiv?
    _("jnz .weiter") ;wenn negativ, dann nächstes px
    _("cmp eax,dword[_py]") ;ist py>y?
    _("jb .weiter") ;wenn py grösser, dann nächstes px

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

    _("@@:")
    _("pop ecx")
    _("pop eax")
    _("jmp .pixelinside")

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

    _(".weiter:")
    _("pop ecx")
    _("pop eax")
    _("jmp .x_loop")
    _("")
    _("")
    _("")
    _("")
    _("")
    _("")
    _("")
    _("")
    _("")
    _("")
    _("")
    _("")
    _("")
    _("")
    EndFunc ;==>_quadrilateral

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

    ;GDI+ wird nur verwendet, um andere Dateien als das BMP-Format zu laden
    Func getDCfromfile($bmpfile, ByRef $ptr) ;ptr to bitmapdata, it is possible to manipulate one pixel if needed
    Local $hBitmap = _GDIPlus_BitmapCreateFromFile($bmpfile)
    Local $hbmp = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap)
    $iwidth = _GDIPlus_ImageGetWidth($hBitmap)
    $iheight = _GDIPlus_ImageGetHeight($hBitmap)

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

    Local $tBMI = DllStructCreate($tagBITMAPINFO)
    DllStructSetData($tBMI, "Size", DllStructGetSize($tBMI) - 4)
    DllStructSetData($tBMI, "Width", $iwidth)
    DllStructSetData($tBMI, "Height", -$iheight)
    DllStructSetData($tBMI, "Planes", 1)
    DllStructSetData($tBMI, "BitCount", 32)
    Local $hdc = _WinAPI_GetDC(0)
    Local $hcdc = _WinAPI_CreateCompatibleDC($hdc)
    Local $adib = DllCall('gdi32.dll', 'ptr', 'CreateDIBSection', 'ptr', 0, 'ptr', DllStructGetPtr($tBMI), 'uint', 1, 'ptr*', 0, 'ptr', 0, 'uint', 0)
    ; select object
    _WinAPI_SelectObject($hcdc, $adib[0])
    ; copy the content of the bitmap into the buffer ...
    _WinAPI_GetDIBits($hdc, $hbmp, 0, $iheight, $adib[4], DllStructGetPtr($tBMI), 1)
    ; create the a dllstruct with the pointer $aDIB[4]
    Local $stride = 3 * $iwidth + Mod($iwidth, 4) ;number of bytes in one line (filled with some bytes, because it must be a multiple of four!)
    $tbits = DllStructCreate('byte[' & $stride * $iheight & ']', $adib[4])
    $ptr = DllStructGetPtr($tbits)
    _GDIPlus_BitmapDispose($hBitmap)
    _WinAPI_DeleteObject($adib[0])
    Return $hcdc ;MemoryDC of bitmap
    EndFunc ;==>getDCfromfile

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

    Func _solve_linear_quad($a, $b) ;matrix,lösung Gaußsches Eliminationsverfahren, löst x gleichungen mit x unbekannten
    ;by Andy
    Dim $Y[UBound($b)] ;ergebnisse
    $n = UBound($a) - 1 ;anzahl der zeilen/spalten
    ;falls erforderlich, zeilen und spalten tauschen
    If $a[0][0] = 0 Then ;wenn erster koeffizient = 0, dann kann das system nicht starten => spalten tauschen ggf zeilen tauschen
    For $k = 0 To $n ;jede zeile
    For $j = 0 To $n ;alle spalten in dieser Zeile testen
    If $a[$k][$j] <> 0 Then
    For $m = 0 To $n ;treffer, die erste spalte mit der j. tauschen
    $t = $a[$m][$j] ;sichern
    $a[$m][$j] = $a[$m][0] ;mit erster spalte tauschen
    $a[$m][0] = $t
    Next
    For $j = 0 To $n ;zeilen tauschen
    $t = $a[0][$j] ;sichern
    $a[0][$j] = $a[$k][$j] ;mit erster spalte tauschen
    $a[$k][$j] = $t
    Next
    $t = $b[0] ;ergebnisse auch tauschen
    $b[0] = $b[$k]
    $b[$k] = $t
    ExitLoop 2
    EndIf
    Next
    Next
    EndIf

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

    If $a[0][0] = 0 Then Return SetError(1, 0, 1)

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

    ;endlich rechnen :)
    For $I = 0 To $n ;alle zeilen
    ;erstes element auf 1 bringen indem man gesamte zeile durch erstes Element teilt
    For $k = $I To $n
    $t = $a[$k][$I] ;erstes element merken
    If $t <> 0 Then ;nur, wenn das erste element ungleich null ist...
    For $j = $I To $n
    $a[$k][$j] /= $t ;alle zeilenmitglieder durch erstes element teilen
    Next
    ;b durch i teilen
    $b[$k] /= $t ;ergebnis natürlich auch
    EndIf
    Next
    ;zeile i von allen weiteren zeilen subtrahieren, erstes element wird zu 0
    For $k = $I + 1 To $n
    If $a[$k][$I] <> 0 Then ;wenn null, dann überspringen
    For $j = $I To $n
    $a[$k][$j] -= $a[$I][$j] ;die i.zeile von der aktuellen zeile subtrahieren
    Next
    $b[$k] -= $b[$I] ;ergebnisse natürlich auch
    EndIf
    Next
    Next
    ;_ArrayDisplay($a)
    ;alle parameter bestimmen durch rückwärtseinsetzen

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

    $Y[$n] = $b[$n] ;letzter ist bereits bekannt
    For $I = $n - 1 To 0 Step -1
    For $j = $n To $I + 1 Step -1
    $b[$I] -= $a[$I][$j] * $Y[$j]
    Next
    $Y[$I] = $b[$I]
    Next
    Return $Y
    EndFunc ;==>_solve_linear_quad
    Exit

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

    Func _ReDraw($fPrecision)
    _GDIPlus_GraphicsClear($hGfxBuffer, 0xFF000000)
    _projective_mapping($hBmpBuffer, $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])
    ;_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)

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

    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]
  • GROSSARTIG :thumbup:
    Oh Mann - ich bin ganz aufgeregt :rock:

    Wie ist es, wenn du $GDIP_ILMUSERINPUTBUF bei BitLock benutzt?
    wird dann auch eine Kopie erstellt?! vielleicht geht das ja schneller...

    2 Bugs sind mir aufgefallen:
    1) konnte ich leider nicht mehr reproduzieren, als ich die Koordinaten der Eckpunkte auslesen wollte, aber manchmal ist das Bild einfach nur schwarz.
    Verschiebt man einen Punkt etwas, dann ist das Bild wieder da - wieder zurück ist es wieder weg...

    2) siehe Screenshot: autoit.de/wcf/attachment/11884/


    ps.: Du includest in deinen ASM-Scripts immer die Datei GDIConstants.au3, welche aber standartmässig nicht bei AutoIt dabei ist.

  • Zitat

    Wie ist es, wenn du $GDIP_ILMUSERINPUTBUF bei BitLock benutzt?

    hab schon einiges getestet, scheinbar wird jeder GDI-Funktion im System mitgeteilt, dass ab nun bestimmte Bytes im Speicher gelockt sind ^^ ....und das dauert ;)

    Zitat

    2 Bugs sind mir aufgefallen:
    1) konnte ich leider nicht mehr reproduzieren,

    yepp, hatte ich auch, als ich das Script das erste mal auf einem Rechner gestartet hatte...aber nur beim ersten Mal....

    Zitat

    ps.: Du includest in deinen ASM-Scripts immer die Datei GDIConstants.au3, welche aber standartmässig nicht bei AutoIt dabei ist.

    uups, ich drücke F2 für OrganizeIncludes, hab nie geguckt, was der da einbindet!
    Kann auch sein, dass ich nicht die allerneueste Version der GDI+-Includefiles habe....

  • [autoit]

    $u = 1 ;koordinaten oben rechts im $image
    $v = 1

    [/autoit]

    in Zeile 87/88 ändern, beseitigt das "überlappen"

    /EDIT/ muss asmcode bissl ändern

  • Hab hier ein paar Koordinate für dich zum debuggen:

    Code
    Global $aDrag[5][2] = [[0, 0],[140, 99],[554, 99],[750, 350],[99, 454]]
    Global $aDrag[5][2] = [[0, 0],[135, 108],[698, 154],[698, 347],[99, 454]]
    Global $aDrag[5][2] = [[0, 0],[91, 242],[696, 172],[705, 447],[91, 314]]
    Global $aDrag[5][2] = [[0, 0],[35, 107],[693, 79],[715, 434],[89, 461]]
    Global $aDrag[5][2] = [[0, 0],[587, 67],[693, 79],[715, 434],[89, 461]]

    Zu verwenden mit dem Bild Logo4.gif aus dem Autoit\Examples\Gui -Ordner

    1) sollte selbsterklärend sein ;)
    2) Bild ist schwarz, linke Punkte können bewegt werden - Bild bleibt schwarz
    3) Bild ist schwarz, rechte Punkte können bewegt werden - Bild bleibt schwarz
    4) Bild scheint generell etwas zu hoch zu sitzen, es ragt über die obernen Punkte hinaus (bzw ist abgeschnitten) und hat zu den unteren Punkten Luft
    5) Komisches Eck links unten

    E

    Noch die Zeile um immer gleich die Koordinaten zu bekommen:

    [autoit]

    ConsoleWrite("Global $aDrag[5][2] = [[0, 0],[" & $aDrag[1][0] & ", " & $aDrag[1][1] & "],[" & $aDrag[2][0] & ", " & $aDrag[2][1] & "],[" & $aDrag[3][0] & ", " & $aDrag[3][1] & "],[" & $aDrag[4][0] & ", " & $aDrag[4][1] & "]]" & @CRLF)

    [/autoit]


    In die Hauptschleife in Switch/Else

  • hmm, ich hab mal zum testen ein Rechteck gebastelt und dieses dann auf
    Global $aDrag[5][2] = [[0, 0],[10, 30],[700, 30],[700, 500],[10, 500]]
    gelegt. Und auch nicht mit dem Assemblercode gerechnet, nur mit dem AutoItcode.
    Also ein Rechteck(Ursprung) auf ein Rechteck(Transformation). Das seltsame ist dabei, die Transformation ist schief! Eine Ecke verschieben (einige Pixel weiter, also kein Rechteck als Ziel) und es ist "richtig"....
    /EDIT/ Bitmap gelöscht
    Ich habe festgestellt, dass bei bestimmten Koordinaten die Transformationsvariablen (die 8 Unbekannten) "seltsame" Werte annehmen. Ich habe den Gleichungslöser im Verdacht.... :huh:

    /EDIT/ ja, genau, der Gleichungslöser wars! Der hatte alle Grafikbugs zu verantworten....

    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

    2 Mal editiert, zuletzt von Andy (6. Juni 2012 um 05:14)

  • Zwischenbericht:
    Bekannte Grafikbugs sind entfernt (kamen vom Gleichungslöser), ein bissl hänge ich in den Seilen mit 2 Punkten:

    Erstens, bei extrem verzerrten Vierecken wird aufgrund von Rundungsfehlern (hab schon 80 Bit Genauigkeit) durch Multiplikation von sehr großen mit sehr kleinen Zahlen die "letzte Pixelreihe" nicht exakt berechnet. Man sieht das, wenn man das Viereck so verzerrt, dass nur noch die letzten 5-6 Pixelreihen "im Vordergrund" sichtbar sind (dementsprechend vergrössert). Aber ich denke, damit kann man leben! Die unterste Pixelreihe ist dann nur noch halb so hoch....

    Zweitens, ich habe einige Versuche gemacht um eine schnelle Methode zu finden um festzustellen, ob sich ein Punkt in dem transformierten Viereck/Dreieck befindet. Das ist relativ aufwendig, zzt. bin ich dabei, mich zeilenweise "innerhalb" des transformierten Vierecks (begrenzt durch 4 Geraden y=mx+b) zu bewegen. Das scheint besser zu sein. Weiterhin hab ich den Assemblerteil schon teilweise von Floatingpoint-Berechnung auf Integer umgestellt, das fetzt speedmässig richtig! Jetzt ist sogar reichlich Zeit für Firlefanz wie z.B. bilineare Filter!

    Ziel ist, ein Video in Echtzeit zu "transformieren". Dann mache ich aber den Gleichungslöser auch komplett in Assembler, das ist nur Fleissarbeit...
    6 Videos auf UEZ´s rotierendem Würfel, muhaaaaa^^
    Ich bitte daher um bissl Geduld, habe zzt. mehrere Baustellen, aber vor Weihnachten wird das sicher was....
    Überlegt euch mal eine 3D-Anwendung z.b. Darstellung von Texturen auf einem Mesh. :rolleyes:

    Bin grade nicht zuhause, aber in den nächsten Tagen stelle ich die neue Version (ohne Fasm) schon mal online....

  • Funktion steht soweit, ich hab bissl getestet und mir ist kein Grafik-Bug mehr aufgefallen.
    Einschränkend muss man allerdings sagen, dass nur "richtige" Trapezoide verwendet werden dürfen, soll heissen, konvexe konkave Vierecke (bei denen ein Eckpunkt innerhalb des Dreiecks der anderen drei Eckpunkte liegt) werden nicht dargestellt!
    Die Abfrage dahingehend ist noch nicht implementiert, also ist es (noch) nicht möglich, die "Rückseite" eines Bildes zu betrachten :rolleyes:

    Anbei der grob zusammengehackte Code. Bin gerade dabei, alles bissl zu straffen und aufzuhübschen. Dann wird es auch eine FASM-lose AutoIt-Funktion geben, und natürlich auch eine DLL, um die Funktion in anderen Programmen nutzen zu können.

    Spoiler anzeigen
    [autoit]

    #include <GDIPlus.au3>
    #include <WinAPI.au3>
    #include <WindowsConstants.au3>
    #include <GDIPlusConstants.au3>
    #include <StructureConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <array.au3>
    #include <GDIConstants.au3>
    #include <AssembleIt.au3>

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

    Opt("GuiOnEventMode", 1)

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

    ;Global $aDrag[5][2] = [[0, 0],[1, 1],[800, 50],[700, 530],[500, 450]]
    ;Global $aDrag[5][2] = [[0, 0],[15,10],[700, 300],[720, 330],[11, 380]]
    ;Global $aDrag[5][2] = [[0, 0],[35, 100],[100, 35],[750, 350],[110, 380]]
    ;Global $aDrag[5][2] = [[0, 0],[10, 30],[700, 30],[700, 500],[10, 500]]
    Global $aDrag[5][2] = [[0, 0],[10, 30],[175, 30],[175, 157],[10, 157]]
    ;Global $aDrag[5][2] = [[0, 0],[587, 67],[693, 79],[715, 434],[89, 461]]
    ;Global $aDrag[5][2] = [[0, 0],[200, 67],[450, 67],[500, 100],[300, 150]]

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

    ;Global $aDrag[5][2] = [[0, 0],[140, 99],[554, 99],[750, 350],[99, 454]]
    ;Global $aDrag[5][2] = [[0, 0],[135, 108],[140, 100],[658, 347],[429, 454]]
    ;Global $aDrag[5][2] = [[0, 0],[91, 242],[696, 172],[705, 447],[91, 314]]
    ;Global $aDrag[5][2] = [[0, 0],[35, 107],[693, 79],[715, 434],[89, 461]]
    ;Global $aDrag[5][2] = [[0, 0],[35, 30],[45, 25],[715, 334],[489, 491]]

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

    Global $minx, $miny, $maxx, $maxy, $struct_float, $ptr_orginal, $bi, $b_buffer, $struct_buffer, $h
    Global $b_buffer = 800, $h_buffer = 540, $struct_koord

    [/autoit] [autoit][/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($b_buffer, $h_buffer, $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)
    Global $iwidth, $iheight
    Local $ptr_orginal
    Local $hDC_orginal = getDCfromfile($sfile, $ptr_orginal) ;GDI+ lädt auch jpg

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

    Global $struct = DllStructCreate("dword[" & $iwidth * $iheight & "]", $ptr_orginal)
    ;global $himagefile="mona-lisa.jpg"

    [/autoit] [autoit][/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
    Sleep(100)
    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]

    Func _projective_mapping($hbitmap_1, $hImage, $1x, $1y, $2x, $2y, $3x, $3y, $4x, $4y) ;eck-koordinaten projektion, obere linke und untere rechte Ecke Orginal

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

    ;struct aufbauen, in der sämtliche für das ASM-Programm wichtigen Werte gesammelt werden.
    ;so muss nur noch die Startadresse dieser Struct an das ASM-Programm übergeben werden
    $struct_float = DllStructCreate("align 16;float _var[8];uint _pos[8];ptr _buffer;ptr _orginal;int _b_buffer;int b_orginal; uint size") ;die 8 variablen und die 8 koordinaten

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

    $bi = _GDIPlus_ImageGetWidth($hImage)
    $h = _GDIPlus_ImageGetHeight($hImage)

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

    $u = 1 ;koordinaten oben rechts im $image
    $v = 1
    $2x = $2x - 1 ;breite und höhe sind eins kleiner, wenn man von 0 anfängt zu zählen...
    $3x = $3x - 1
    $3y = $3y - 1
    $4y = $4y - 1

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

    $BitmapData = _GDIPlus_BitmapLockBits($hbitmap_1, 0, 0, $b_buffer, $h_buffer, BitOR($GDIP_ILMREAD, $GDIP_ILMWRITE), $GDIP_PXF32ARGB)

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

    ;struct mit Daten füllen
    Global $ptr_buffer = DllStructGetData($BitmapData, "Scan0");Scan0 - Pointer to the first (index 0) scan line of the bitmap.
    ; Global $struct_buffer = DllStructCreate("dword [" & $b_buffer * $h_buffer & "]", $ptr_buffer)
    DllStructSetData($struct_float, 3, $ptr_buffer, 1)
    DllStructSetData($struct_float, 4, $ptr_orginal, 1)
    DllStructSetData($struct_float, 5, $b_buffer, 1)
    DllStructSetData($struct_float, 6, $bi, 1)
    DllStructSetData($struct_float, 7, $bi*$h, 1)

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

    Dim $bl[8] = [$u, $bi, $bi, $u, $v, $v, $h, $h] ;lösungen der 8 Gleichungen (Eck-Koordinaten Orginalbild)
    Dim $a[8][8] = [ _ ;8 gleichungen in Matrix
    [$1x, $1y, 1, 0, 0, 0, -$1x * $u, -$1y * $u], _ ;Eckpunkte Transformiertes Rechteck
    [$2x, $2y, 1, 0, 0, 0, -$2x * $bi, -$2y * $bi], _
    [$3x, $3y, 1, 0, 0, 0, -$3x * $bi, -$3y * $bi], _ ;Eckpunkte Transformiertes Rechteck
    [$4x, $4y, 1, 0, 0, 0, -$4x * $u, -$4y * $u], _
    [0, 0, 0, $1x, $1y, 1, -$1x * $v, -$1y * $v], _ ;Eckpunkte Transformiertes Rechteck
    [0, 0, 0, $2x, $2y, 1, -$2x * $v, -$2y * $v], _
    [0, 0, 0, $3x, $3y, 1, -$3x * $h, -$3y * $h], _
    [0, 0, 0, $4x, $4y, 1, -$4x * $h, -$4y * $h]] ;Eckpunkte Transformiertes Rechteck

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

    $s = _solve_linear_quad($a, $bl) ;8 lineare Gleichungen lösen

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

    For $I = 1 To 8 ;struct mit daten aus dem gleichungslöser füllen
    DllStructSetData($struct_float, 1, $s[$I - 1], $I)
    Next
    ;~ Dim $m[5]
    ;~ Dim $b[5]

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

    ;geraden 4-1 und 3-2 y=mx+b

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

    ;~ If $4x = $1x Then ;falls gerade senkrecht
    ;~ $m[4] = 1.234e9 ;irgendeinen wert generieren zum kennzeichnen
    ;~ Else ;ansonsten
    ;~ $m[4] = ($4y - $1y) / ($4x - $1x)
    ;~ $b[4] = $1y - $m[4] * $1x
    ;~ EndIf

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

    ;~ If $3x = $2x Then
    ;~ $m[2] = 1.234e9
    ;~ Else
    ;~ $m[2] = ($3y - $2y) / ($3x - $2x)
    ;~ $b[2] = $2y - $m[2] * $2x
    ;~ EndIf
    ;~ ;geraden 1-2 und 3-4 y=mx+b
    ;~ If $2x = $1x Then
    ;~ $m[1] = 1.234e9
    ;~ Else
    ;~ $m[1] = ($2y - $1y) / ($2x - $1x)
    ;~ $b[1] = $1y - $m[1] * $1x
    ;~ EndIf

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

    ;~ If $3x = $4x Then
    ;~ $m[3] = 1.234e9
    ;~ Else
    ;~ $m[3] = ($3y - $4y) / ($3x - $4x)
    ;~ $b[3] = $3y - $m[3] * $3x
    ;~ EndIf

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

    ;$struct_koord = DllStructCreate("uint[8]"); struct für die x- und y-koordinaten

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

    ;kleinstes und grösstes x und y finden, um nicht die gesamte bitmap durchzurechnen, sondern
    ;nur den Teil, der von dem quadrilateral belegt ist
    ;~ Global $minx = 1e9, $miny = 1e9, $maxx = 0, $maxy = 0
    ;~ Dim $sx[5] ;Eckpunkte x
    ;~ Dim $sy[5] ;Eckpunkte y

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

    For $I = 1 To 4
    DllStructSetData($struct_float, 2, Eval($I & "x"), $I * 2 - 1);struct füllen
    DllStructSetData($struct_float, 2, Eval($I & "y"), $I * 2);1x,1y,2x,2y,3x...
    ;~ If Eval($I & "x") < $minx Then $minx = Eval($I & "x");minimum und maximum finden
    ;~ If Eval($I & "x") > $maxx Then $maxx = Eval($I & "x")
    ;~ If Eval($I & "y") > $maxy Then $maxy = Eval($I & "y")
    ;~ If Eval($I & "y") < $miny Then
    ;~ $miny = Eval($I & "y")
    ;~ $indexL = $I ;index ist die aktuelle Koordinate, L=linksrum R=rechtsrum gezählt von der minimalen (obersten) y-Position
    ;~ EndIf
    ;~ $sx[$I] = Eval($I & "x") ;adresse punkt1
    ;~ $sy[$I] = Eval($I & "y") ;adresse punkt1
    Next
    $time = TimerInit()
    ; $_assembleit_flag = 0
    $ret = _AssembleIt("ptr", "_quadrilateral", "ptr", DllStructGetPtr($struct_float))
    ;MsgBox(262144,'Debug line ~' & @ScriptLineNumber,'Selection:' & @lf & '$ret' & @lf & @lf & 'Return:' & @lf & $ret) ;### Debug MSGBOX
    $mtime = TimerDiff($time)
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $Mtime = ' & $mtime & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console

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

    ;~ $indexR = $indexL ;rechte seite nächster punkt
    ;~ $mR = $m[$indexR] ;steigung rechte gerade
    ;~ $bR = $b[$indexR]
    ;~ $indexR += 1 ;gerade zum nächsten Punkt im Uhrzeigersinn
    ;~ If $indexR = 5 Then $indexR = 1
    ;~ $indexL = $indexL - 1 ;linke seite vorheriger punkt
    ;~ If $indexL = 0 Then $indexL = 4
    ;~ $mL = $m[$indexL] ;steigung linke gerade
    ;~ $bl = $b[$indexL]
    ; MsgBox(262144, 'Debug line ~' & @ScriptLineNumber, 'Selection:' & @LF & '$ret' & @LF & @LF & 'Return:' & @LF & $ret) ;### Debug MSGBOX

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

    ;MsgBox(262144, 'Debug line ~' & @ScriptLineNumber, 'Selection:' & @LF & '$indexL' & @LF & @LF & 'Return:' & @LF & $indexL) ;### Debug MSGBOX
    ; _arraydisplay($s)
    ;~ For $py = $miny To $maxy Step 1
    ;~ ; ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : p = ' & $py & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
    ;~ If $py = $sy[$indexL] Then ;nächsten punkt links gefunden
    ;~ If $sy[$indexL] <> $maxy Then ;nur, wenn nächster schnittpunkt nicht der unterste ist..
    ;~ $indexL = $indexL - 1 ;linke seite
    ;~ If $indexL = 0 Then $indexL = 4
    ;~ ; msgbox(0,$indexL&" sy="&$sy[$indexL]&" ymax="&$maxy,"linke seite nächsten punkt gefunden")
    ;~ $mL = $m[$indexL] ;steigung linke gerade
    ;~ $bl = $b[$indexL]
    ;~ EndIf
    ;~ EndIf
    ;~ If $mL = 1.234e9 Or $mL = 0 Then
    ;~ $xL = $sx[$indexL]
    ;~ Else
    ;~ $xL = Int(($py - $bl) / $mL) ;von rechter grenze
    ;~ EndIf
    ;~ ; MsgBox(262144, 'Debug line ~' & @ScriptLineNumber, 'Selection:' & @LF & '$xL' & @LF & @LF & 'Return:' & @LF & $xL) ;### Debug MSGBOX
    ;~ ;if $sx[$indexL]=$sx[$index then $xR=$sx[$indexL]

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

    ;~ If $mR = 1.234e9 Or $mR = 0 Then ;falls steigung 0 oder unendlich
    ;~ $xR = $sx[$indexR]
    ;~ Else
    ;~ $xR = Int(($py - $bR) / $mR);...bis zur linken
    ;~ EndIf
    ;~ ; MsgBox(262144, 'Debug line ~' & @ScriptLineNumber, 'Selection:' & @LF & '$xR' & @LF & @LF & 'Return:' & @LF & $xR) ;### Debug MSGBOX
    ;~ ;if $sy[$indexR]=$py then $xR=$sx[$indexR]

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

    ;~ For $px = $xL To $xR
    ;~ $X = Round(($s[0] * $px + $s[1] * $py + $s[2]) / ($s[6] * $px + $s[7] * $py + 1))
    ;~ ; ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $X = ' & $X & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
    ;~ $Y = Round(($s[3] * $px + $s[4] * $py + $s[5]) / ($s[6] * $px + $s[7] * $py + 1))
    ;~ ; ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $Y = ' & $Y & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
    ;~ $col = DllStructGetData($struct, 1, ($Y - 1) * $bi + $X) ;farbe aus bild holen
    ;~ ; ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $bi = ' & $bi & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
    ;~ ; ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $col = ' & $col & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
    ;~ DllStructSetData($struct_buffer, 1, $col, $py * $b_buffer + $px + 1)
    ;~ ;MsgBox(262144,'Debug line ~' & @ScriptLineNumber,'Selection:' & @lf & '$py * $b_buffer + $px + 1' & @lf & @lf & 'Return:' & @lf & hex($py * $b_buffer + $px + 1)) ;### Debug MSGBOX
    ;~ Next

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

    ;~ If $xR = $sx[$indexR] And $sy[$indexR] = $py Then ;auf rechter Seite nächsten Schnittpunkt gefunden
    ;~ ; msgbox(0,$indexR,"schnittpunkt gefunden")

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

    ;~ If $sy[$indexR] <> $maxy Then ;nur, wenn nächster schnittpunkt nicht der unterste ist..

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

    ;~ $mR = $m[$indexR] ;steigung rechte gerade
    ;~ $bR = $b[$indexR]
    ;~ $indexR += 1 ;gerade zum nächsten Punkt im Uhrzeigersinn
    ;~ If $indexR = 5 Then $indexR = 1
    ;~ ; msgbox(0,$indexR,"nächster schnittpunkt ist "&$indexR)
    ;~ EndIf
    ;~ EndIf
    ;~ Next

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

    ;~ $t = TimerInit()
    _GDIPlus_BitmapUnlockBits($hbitmap_1, $BitmapData)

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

    EndFunc ;==>_projective_mapping

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

    Func _quadrilateral()
    _("use32")
    _("org " & FasmGetBasePtr($Fasm))
    _("jmp _los")
    _("align 4")
    ; Alle Variablen deklarieren und für SIMD an 16 Bytegrenzen ausrichten = alignen

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

    _("_m1 dd 12345678") ;y=m*x+b geradengleichung
    _("_m2 dd 12345678") ;m=(x2-x1)/(y2-y1)
    _("_m3 dd 12345678") ;addresse _m3=_m1+(4*(index-1))
    _("_m4 dd 12345678") ;
    _("_b1 dd 0.0") ;b=y-m*x
    _("_b2 dd 0.0")
    _("_b3 dd 0.0") ;
    _("_b4 dd 0.0")
    _("_mR dd 0.0") ;
    _("_bR dd 0.0") ;
    _("_mL dd 0.0") ;
    _("_bL dd 0.0") ;
    _("_indexL dd 0")
    _("_indexR dd 0")
    _("_minx dd 100000")
    _("_miny dd 100000")
    _("_maxx dd 1")
    _("_maxy dd 1")
    _("_eins dd 1")
    _("_vier dd 4") ;30
    _("_xL dd 0")
    _("_xR dd 0")
    _("_ptr_var dd 8 dup(0)") ;ptr variablen aus gleichungslöser
    _("_ptr_posxy dd 8 dup(0)") ;ptr auf liste eckpunkte
    _("_buffer dd 0") ;pointer auf den backbuffer
    _("_orginal dd 0") ;pointer auf die orginal bitmap
    _("_b_buffer dd 0") ;breite backbuffer
    _("_b_orginal dd 0") ;breite backbuffer
    _("_size_orginal dd 0") ;breite backbuffer

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

    _("_px dd 0") ;koordinaten im backbuffer
    _("_py dd 0")
    _("_x dd 0") ;koordinaten im orginal
    _("_y dd 0")

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

    ; _("_ausgleich dd 0.001")

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

    _("_los:")
    _("finit") ;coproinit 27

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

    ;struct auflösen, macht weniger arbeit...
    _("mov esi,dword[esp+4]")
    _("mov ecx,21") ;breite backbuffer
    _("mov edi,_ptr_var")
    _("rep movsd")

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

    ;~ _("mov eax,esi");dword[_b_orginal]")
    ;~ _("ret") ;breite backbuffer

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

    ;minimum und maximum der koordinaten bestimmen
    _("mov ebx,_ptr_posxy")
    _("mov ecx,4") ;for $i=3 to 1 step -1
    _("_minmax:")
    _("mov eax,dword[ebx+(ecx-1)*4*2]") ;x-koordinate holen
    _("cmp eax,dword[_minx]") ;mit minx vergleichen
    _("jg @f") ;wenn grösser, weiter
    _("mov dword[_minx],eax") ;wenn kleiner, dann speichern
    _("@@:")
    _("cmp eax,dword[_maxx]") ;mit maxx vergleichen
    _("jl @f") ;wenn kleiner, weiter
    _("mov dword[_maxx],eax") ;wenn grösser, dann speichern
    _("@@:")
    _("mov eax,dword[ebx+(ecx-1)*4*2+4]") ;y-koordinate holen
    _("cmp eax,dword[_miny]") ;mit miny vergleichen
    _("jg @f") ;wenn grösser, weiter
    _("mov dword[_miny],eax") ;wenn kleiner, dann speichern
    _("mov dword[_indexL],ecx") ;wenn kleiner, dann speichern
    _("@@:")
    _("cmp eax,dword[_maxy]") ;mit maxy vergleichen
    _("jl @f") ;wenn kleiner, weiter
    _("mov dword[_maxy],eax") ;wenn grösser, dann speichern
    _("@@:")
    _("loop _minmax") ;solange, bis ecx=0

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

    ;~ _("mov eax,dword[_maxx]")
    ;~ _("ret")

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

    ;geradengleichungen werden gebraucht, um die bei gegebenen y (zeile)
    ;die anfangs und endpunkte (x) der pixelzeile im viereck zu finden

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

    ;$m4 = ($4y - $1y) / ($4x - $1x)
    ;If $4x = $1x Then ;falls gerade senkrecht
    ; $m[4] = 1.234e9 ;irgendeinen wert generieren zum kennzeichnen
    ;Else ;ansonsten
    ; $m[4] = ($4y - $1y) / ($4x - $1x)
    ; $b[4] = $1y - $m[4] * $1x
    ;EndIf
    _("")
    _("")
    _("mov ecx,_ptr_posxy") ;koordinaten
    _("")
    _("mov eax,dword[ecx+4*6]") ;4x
    ;_("ret")

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

    _("cmp eax,dword[ecx+4*0]") ;ist 4x=1x
    _("je @f") ;wenn gleich, dann springe zum nächsten lokalen label
    _("fild dword[ecx+4*7]") ;st0=4y
    _("fisub dword[ecx+4*1]") ;st0=(4y-1y)
    _("fild dword[ecx+4*6]") ;st0=4x st1=(4y-1y)
    _("fisub dword[ecx+4*0]") ;st0=(4x-1x)
    _("fdivp") ;st0=m4
    _("fst dword[_m4]") ;st0=m4
    ;$b1 = $1y - $m1 * $1x
    _("fimul dword[ecx+4*0]") ;st0=m1*1x
    _("fisubr dword[ecx+4*1]") ;st0=1y-m1*1x = b1
    _("fstp dword[_b4]") ;b1 speichern, fpstack clean

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

    ;$m2 = ($3y - $2y) / ($3x - $2x)
    ;If $3x = $2x Then
    ; $m[2] = 1.234e9
    ;Else
    ; $m[2] = ($3y - $2y) / ($3x - $2x)
    ; $b[2] = $2y - $m[2] * $2x
    ;EndIf
    _("@@:") ;lokales label
    _("mov eax,dword[ecx+4*4]") ;3x
    _("cmp eax,dword[ecx+4*2]") ;ist 3x=2x
    _("je @f") ;wenn gleich, dann springe zum nächsten lokalen label
    _("fild dword[ecx+4*5]") ;st0=3y
    _("fisub dword[ecx+4*3]") ;st0=(3y-2y)
    _("fild dword[ecx+4*4]") ;st0=3x st1=(3y-2y)
    _("fisub dword[ecx+4*2]") ;st0=(3x-2x)
    _("fdivp") ;st0=m2
    _("fst dword[_m2]") ;st0=m2
    ;$b2 = $2y - $m2 * $2x
    _("fimul dword[ecx+4*2]") ;st0=m2*2x
    _("fisubr dword[ecx+4*3]") ;st0=2y-m2*2x = b2
    _("fstp dword[_b2]") ;b2 speichern, fpstack clean
    _("")

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

    ;$m1 = ($2y - $1y) / ($2x - $1x)
    _("@@:") ;lokales label
    _("mov eax,dword[ecx+4*2]") ;2x
    _("cmp eax,dword[ecx+4*0]") ;ist 2x=1x
    _("je @f") ;wenn gleich, dann springe zum nächsten lokalen label
    _("fild dword[ecx+4*3]") ;st0=2y
    _("fisub dword[ecx+4*1]") ;st0=(2y-1y)
    _("fild dword[ecx+4*2]") ;st0=2x st1=(2y-1y)
    _("fisub dword[ecx+4*0]") ;st0=(2x-1x)
    _("fdivp") ;st0=m1
    _("fst dword[_m1]") ;st0=m1
    ;$b3 = $1y - $m3 * $1x
    _("fimul dword[ecx+4*0]") ;st0=m1*1x
    _("fisubr dword[ecx+4*1]") ;st0=1y-m1*1x = b1
    _("fstp dword[_b1]") ;b1 speichern, fpstack clean
    _("")

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

    ;$m3 = ($3y - $4y) / ($3x - $4x)
    _("@@:") ;lokales label
    _("mov eax,dword[ecx+4*4]") ;3x
    _("cmp eax,dword[ecx+4*6]") ;ist 3x=4x
    _("je @f") ;wenn gleich, dann springe zum nächsten lokalen label
    _("fild dword[ecx+4*5]") ;st0=3y
    _("fisub dword[ecx+4*7]") ;st0=(3y-4y)
    _("fild dword[ecx+4*4]") ;st0=3x st1=(3y-4y)
    _("fisub dword[ecx+4*6]") ;st0=(3x-4x)
    _("fdivp") ;st0=m4
    _("fst dword[_m3]") ;st0=m4
    ;$b4 = $3y - $m4 * $3x
    _("fimul dword[ecx+4*4]") ;st0=m4*3x
    _("fisubr dword[ecx+4*5]") ;st0=3y-m4*3x = b4
    _("fstp dword[_b3]") ;b4 speichern, fpstack clean
    _("@@:") ;lokales label 108
    _("")

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

    ;minx/maxx und miny/maxy finden

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

    ;~ $indexR = $indexL ;rechte seite nächster punkt
    ;~ $mR = $m[$indexR] ;steigung rechte gerade
    ;~ $bR = $b[$indexR]
    ;~ $indexR += 1 ;gerade zum nächsten Punkt im Uhrzeigersinn
    ;~ If $indexR = 5 Then $indexR = 1

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

    _("mov eax,dword[_indexL]")
    _("mov dword[_indexR],eax")
    _("call _mR_und_bR")

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

    _("")
    _("add eax,1")
    _("cmp eax,5")
    _("cmove eax,dword[_eins]")
    _("mov dword[_indexR],eax") ;$indexR += 1
    _("")
    _("")
    ;$indexL = $indexL - 1 ;linke seite vorheriger punkt
    ;If $indexL = 0 Then $indexL = 4
    ;$mL = $m[$indexL] ;steigung linke gerade
    ;$bl = $b[$indexL]
    _("mov eax,dword[_indexL]")
    _("sub eax,1")
    _("cmp eax,0")
    _("cmove eax,dword[_vier]")
    _("mov dword[_indexL],eax") ;$indexL -= 1
    _("call _mL_und_bL")
    _("")

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

    ;variablen in speicher schreiben
    _("mov eax,_buffer") ; & DllStructGetPtr($struct_float) + 64) ;pointer auf den buffer holen
    _("mov eax,dword[eax]")
    _("mov dword[_buffer],eax")

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

    ;register mit den laufvariablen laden
    _("mov edx,dword[_miny]")
    _("sub edx,1") ;miny-1 ;;for ymin to ymax
    _("mov esi,dword[_orginal]") ; & DllStructGetPtr($struct_float) + 68) ;pointer auf orginal bitmap
    _("mov eax,[_b_buffer]") ; & DllStructGetPtr($struct_float) + 72) ;pointer breite buffer
    _("mov dword[_b_buffer],eax")
    _("mov eax,dword[_b_orginal]") ; & DllStructGetPtr($struct_float) + 76) ;pointer breite orginal
    _("mov dword[_b_orginal],eax")
    _("mov edi,dword[_buffer]");pointer auf den backbuffer
    _("mov ebx,_ptr_var") ; & DllStructGetPtr($struct_float));pointer auf die die 8 variablen

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

    _(".start:") ;hier gehts los
    ;edx = zeilenzähler
    ;ecx = aktuelle position x-koordinate in der zeile
    _(".y_loop:") ;for py=ymin to ymax
    _("add edx,1") ;py, zeilenzähler
    _("mov dword[_py],edx")

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

    _("cmp edx,dword[_maxy]") ;wenn letzte Zeile erreicht, ende
    _("ja .ende") ; 133
    ;schnittpunkt der aktuellen zeile mit der geraden zwischen 2 punkten bestimmen
    ;ergibt die rechte und die linke x-koordinate in der zeile, in der die transformierten Pixel sind

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

    ; If $py = $sy[$indexL] Then ;nächsten punkt links gefunden
    ; If $sy[$indexL] <> $maxy Then ;nur, wenn nächster schnittpunkt nicht der unterste ist..
    ; $indexL = $indexL - 1 ;linke seite
    ; If $indexL = 0 Then $indexL = 4
    ; ; msgbox(0,$indexL&" sy="&$sy[$indexL]&" ymax="&$maxy,"linke seite nächsten punkt gefunden")
    ; $mL = $m[$indexL] ;steigung linke gerade
    ; $bl = $b[$indexL]
    ; EndIf
    ; EndIf
    _("mov eax,dword[_indexL]") ;
    _("lea ebx,[_ptr_posxy+8*(eax-1)+4]");ebx =adresse y-koordinate des linken eckpunktes
    _("mov ebx,dword[ebx]") ;wert y-koordinate
    _("cmp ebx,dword[_py]") ;vgl y-koordinate des nächsten punktes mit aktueller y-koordinate sy[indexR]
    _("jne .xLxR_berechnen") ;wenn nicht, x-koordinaten berechnen
    _("cmp ebx,dword[_maxy]") ;nur, wenn nächster schnittpunkt nicht der unterste ist..
    _("je .xLxR_berechnen") ;wenn nächster schnittpunkt der unterste ist, dann sind wir im letzten feld
    _("sub eax,1") ;indexL -= 1
    _("cmovz eax,dword[_vier]");If $indexL = 0 Then $indexL = 4
    _("mov dword[_indexL],eax");indexL speichern
    _("call _mL_und_bL") ;mL und bL berechnen
    _(".xLxR_berechnen:") ;linke und rechte x-koordinate berechnen _xL und _xR

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

    ;***********************************************************************************************************************
    ;If $mL = 1.234e9 Or $mL = 0 Then
    ; $xL = $sx[$indexL]
    ;Else
    ; $xL = Int(($py - $bl) / $mL) ;von linker grenze
    ;EndIf
    _("cmp dword[_mL],12345678"); steigung unendlich?
    _("je @f") ;ja, dann nächstes label
    _("cmp dword[_mL],0") ;steigung 0? ;150
    _("je @f") ;ja, dann nächstes label
    _("jmp .getXL")
    _("@@:") ;$xL = $sx[$indexL]
    ; _("mov eax,dword[_indexL]"); UNNÖTIG, falls eax = indexL
    _("lea ebx,[_ptr_posxy+8*(eax-1)]");ebx =adresse x-koordinate des linken eckpunktes
    _("mov ebx,dword[ebx]") ;x-koordinate
    _("mov dword[_xL],ebx") ;speichern

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

    _("jmp .xR_berechnen") ;_xR berechnen
    _(".getXL:") ;$xL = Int(($py - $bL) / $mL) ;von linker grenze
    _("fild dword[_py]")
    _("fsub dword[_bL]")
    _("fdiv dword[_mL]")
    _("fistp dword[_xL]")
    _("")
    _(".xR_berechnen:") ;164

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

    ;If $mR = 1.234e9 Or $mR = 0 Then ;falls steigung 0 oder unendlich
    ; $xR = $sx[$indexR]
    ;Else
    ; $xR = Int(($py - $bR) / $mR);...bis zur rechten
    ;EndIf
    _("cmp dword[_mR],12345678"); steigung unendlich?
    _("je @f") ;ja, dann nächstes label
    _("cmp dword[_mR],0") ;steigung 0?
    _("je @f") ;ja, dann nächstes label
    _("jmp .getXR")
    _("@@:") ;$xR = $sx[$indexR]
    _("mov eax,dword[_indexR]");
    ;_("mov ebx,_ptr_posxy") ; & DllStructGetPtr($struct_float) + 32);pointer auf koordinaten
    _("lea ebx,[_ptr_posxy+8*(eax-1)]");ebx =adresse x-koordinate des linken eckpunktes
    _("mov ebx,dword[ebx]") ;x-koordinate
    _("mov dword[_xR],ebx") ;speichern
    _("jmp .xL_to_xR_loop") ;
    _(".getXR:") ;$xR = Int(($py - $bR) / $mR);...bis zur rechten
    _("fild dword[_py]")
    _("fsub dword[_bR]")
    _("fdiv dword[_mR]")
    _("fistp dword[_xR]")
    _("")
    ;****************************************************schleife xL to xR************
    _(".xL_to_xR_loop:") ;for $x = xL to $xR
    _("mov ecx,dword[_xL]") ;linke seite 184
    _("mov ebx,_ptr_var") ; & DllStructGetPtr($struct_float));pointer auf die a()-variablen
    _("mov dword[_py],edx")

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

    _(".x_loop:")
    _("add ecx,1") ;px
    _("cmp ecx,dword[_xR]") ;ist xR rechter Rand erreicht?
    _("ja .nextline") ;ja, dann nextline (ggf xR + xL anpassen)

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

    ;***************************

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

    _("mov dword[_px],ecx") ;abspeichern
    _("")
    _("fild dword[_py]") ;st0=py
    _("fild dword[_px]") ;st0=px st1=py

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

    ;x=int($s[0] * $px + $s[1] * $py + $s[2]) / ($s[6] * $px + $s[7] * $py + 1) bissl floatingpoint
    _("fld dword[ebx+4*0]") ;st0=s[0] st1=px st2=py
    _("fmul st0,st1") ;st0=s[0]*px
    _("fld dword[ebx+4*1]") ;st0=s[1] st1=s[0]*px st2=px st3=py
    _("fmul st0,st3") ;st0=s[1]*py st1=s[0]*px st2=px st3=py
    _("faddp") ;st0=s[1]*py+s[0]*px st1=px st2=py
    _("fadd dword[ebx+4*2]") ;st0=s[1]*py+s[0]*px+s[2] st1=px st2=py
    _("fld dword[ebx+4*6]") ;st0=$s[6] st1=s[1]*py+s[0]*px+s[2] st2=px st3=py
    _("fmul st0,st2") ;st0=$s[6]*px st1=s[1]*py+s[0]*px+s[2] st2=px st3=py
    _("fld dword[ebx+4*7]") ;st0=s[7] st1=$s[6]*px st2=s[1]*py+s[0]*px+s[2] st3=px st4=py
    _("fmul st0,st4") ;st0=s[7]* py st1=$s[6]*px st2=s[1]*py+s[0]*px+s[2] st3=px st4=py
    _("faddp ") ;st0=s[7]*py+$s[6]*px st1=s[1]*py+s[0]*px+s[2] st1=px st2=py
    _("fld1")
    _("faddp ") ;st0=s[1]*py+s[0]*px+s[2] st1=s[7]*py+$s[6]*px+1 st2=px st3=py
    _("fxch st1") ;
    _("fdiv st0,st1") ;st0=st0/st1 st1=s[7]*py+$s[6]*px+1 st2=px st3=py
    _("fistp dword[_x]") ;abspeichern als integer st0=px st1=py
    _("")
    ;$Y = Int(($s[3] * $px + $s[4] * $py + $s[5]) / ($s[6] * $px + $s[7] * $py + 1))
    _("fld dword[ebx+4*3]") ;st0=s[3] st1=s[7]*py+$s[6]*px+1 st2=px st3=py
    _("fmul st0,st2") ;st0=s[3]*px
    _("fld dword[ebx+4*4]") ;st0=s[4] st1=s[3]*px st2=s[7]*py+$s[6]*px+1 st3=px st4=py
    _("fmul st0,st4") ;st0=s[4]*py st1=s[3]*px st2=s[7]*py+$s[6]*px+1 st3=px st4=py
    _("faddp") ;st0=s[4]*py+s[3]*px st1=s[7]*py+$s[6]*px+1 st2=px st3=py
    _("fadd dword[ebx+4*5]") ;st0=s[4]*py+s[3]*px+s[5] st1=s[7]*py+$s[6]*px+1 st2=px st3=py
    _("fdivrp st1,st0") ;st0=y st1=px st2=py
    _("fistp dword[_y]") ;abspeichern als integer st0=px st1=py 111
    _("FUCOMPP") ;pop, pop => stack clean!

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

    ;~ _("mov eax,dword[_y]")
    ;~ _("test eax, 10000000000000000000000000000000b") ;zahl positiv?
    ;~ _("jnz .x_loop") ;wenn negativ, jump 162

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

    ;~ _("mov eax,dword[_x]")
    ;~ _("test eax, 10000000000000000000000000000000b") ;zahl positiv?
    ;~ _("jnz .x_loop") ;wenn negativ, jump

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

    ;$col = DllStructGetData($struct, 1, ($Y+1) * $b + $X) ;farbe aus bild holen
    _("mov eax,dword[_b_orginal]")
    _("push edx") ;sichern, mul zerstört edx
    _("mov edx,dword[_y]") ;eax=$b*y
    _("sub edx,1") ;eax=$b*y
    _("mul edx") ;eax=$b*y
    _("add eax,dword[_x]") ;eax=$b*y+x
    _("sub eax,1")
    _("pop edx") ;

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

    _("test eax, 10000000000000000000000000000000b") ;zahl positiv?
    _("jnz .x_loop") ;wenn negativ, jump

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

    _("cmp eax,dword[_size_orginal]") ;addresse grösser als bitmap?
    _("ja .x_loop")

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

    _("shl eax,2") ;4 byte = 1 pixel! daher anzahl der byte vervierfachen
    _("mov eax,dword[esi+eax]") ;pixelfarbe holen aus ursprungsbitmap
    _("push eax") ;pixelfarbe sichern

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

    ;DllStructSetData($struct_buffer, 1, $col, $py * $b_buffer + $px+1)
    _("mov eax,dword[_py]")
    _("push edx") ;sichern
    _("mul dword[_b_buffer]") ;mal breite
    _("pop edx") ;sichern
    _("add eax,dword[_px]") ;eax=$py * $b_buffer + $px +1
    _("add eax,1")
    ;~ _("test eax, 10000000000000000000000000000000b") ;zahl positiv?
    ;~ _("jnz .popeax")

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

    _("mov edi,dword[_buffer]");pointer auf den backbuffer
    _("shl eax,2") ;4 byte = 1 pixel! daher anzahl der byte vervierfachen
    _("add edi,eax") ;edi=adresse pixel im buffer
    _("pop eax") ;farbe holen
    _("mov [edi],eax") ;pixel in buffer schreiben
    _("jmp .x_loop") ;next x

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

    _(".nextline:")
    ;If $xR = $sx[$indexR] And $sy[$indexR] = $py Then ;auf rechter Seite nächsten Schnittpunkt gefunden
    ; msgbox(0,$indexR,"schnittpunkt gefunden")
    ; If $sy[$indexR] <> $maxy Then ;nur, wenn nächster schnittpunkt nicht der unterste ist..
    ; $mR = $m[$indexR] ;steigung rechte gerade
    ; $bR = $b[$indexR]
    ; $indexR += 1 ;gerade zum nächsten Punkt im Uhrzeigersinn
    ; If $indexR = 5 Then $indexR = 1
    ; msgbox(0,$indexR,"nächster schnittpunkt ist "&$indexR)
    ;EndIf
    ;EndIf
    _("mov eax,dword[_indexR]") ;
    _("mov ebx,_ptr_posxy") ; & DllStructGetPtr($struct_float) + 32);pointer auf koordinaten
    _("lea ebx,[ebx+8*(eax-1)]");ebx =adresse x-koordinate des linken eckpunktes
    _("mov ebx,dword[ebx]") ;wert x-koordinate

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

    _("cmp ebx,dword[_xR]") ;vgl x-koordinate aktueller x-koordinate sx[indexR]
    _("jne .y_loop") ;wenn nicht, nächste zeile
    _("mov ebx,_ptr_posxy") ; & DllStructGetPtr($struct_float) + 32);pointer auf koordinaten
    _("lea ebx,[ebx+8*(eax-1)+4]");ebx =adresse y-koordinate sy[indexR]
    _("mov ebx,dword[ebx]") ;wert y-koordinate
    _("cmp ebx,dword[_py]") ;vgl y-koordinate aktueller y-koordinate sy[indexR]
    _("jne .y_loop") ;wenn nicht, nächste zeile

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

    _("cmp ebx,dword[_maxy]") ;nur, wenn nächster schnittpunkt nicht der unterste ist..
    _("je .y_loop") ;wenn nächster schnittpunkt der unterste ist, dann sind wir im letzten feld
    ;rechten schnittpunkt gefunden
    _("call _mR_und_bR") ;mL und bL berechnen
    _("mov eax,dword[_indexR]") ;
    _("add eax,1") ;indexR += 1
    _("cmp eax,5") ;GGF RAUSWERFEN; DA UNNÖTIG!!!!!!!
    _("cmovz eax,dword[_eins]");If $indexR = 5 Then $indexR = 1
    _("mov dword[_indexR],eax");indexR speichern
    _("jmp .y_loop") ;next y

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

    _("")
    _(".ende:")
    _("ret")

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

    ;~ _("")
    ;~ _(".popeax:")
    ;~ _("pop eax")
    ;~ _("mov eax,1010101010")
    ;~ _("ret")
    ;~ _("jmp .x_loop")

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

    ;****************************************************funktionen**********
    _("_mL_und_bL:") ;eax muss _indexL sein
    _("lea ebx,[_m1+4*(eax-1)]")
    _("mov ebx,[ebx]")
    _("mov [_mL],ebx") ; $mL = $m[$indexL]
    _("lea ebx,[_b1+4*(eax-1)]");adresse _bx ausrechnen
    _("mov ebx,[ebx]")
    _("mov [_bL],ebx") ; $bL = $b[$indexL]
    _("ret ")

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

    _("_mR_und_bR:") ;eax muss indexR sein
    _("lea ebx,[_m1+4*(eax-1)]")
    _("mov ebx,[ebx]")
    _("mov [_mR],ebx") ; $mR = $m[$indexR]
    _("lea ebx,[_b1+4*(eax-1)]")
    _("mov ebx,[ebx]")
    _("mov [_bR],ebx") ; $bR = $b[$indexR]
    _("ret")
    _("")

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

    EndFunc ;==>_quadrilateral

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

    ;GDI+ wird nur verwendet, um andere Dateien als das BMP-Format zu laden
    Func getDCfromfile($bmpfile, ByRef $ptr) ;ptr to bitmapdata, it is possible to manipulate one pixel if needed
    Local $hBitmap = _GDIPlus_BitmapCreateFromFile($bmpfile)
    Local $hbmp = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBitmap)
    $iwidth = _GDIPlus_ImageGetWidth($hBitmap)
    $iheight = _GDIPlus_ImageGetHeight($hBitmap)

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

    Local $tBMI = DllStructCreate($tagBITMAPINFO)
    DllStructSetData($tBMI, "Size", DllStructGetSize($tBMI) - 4)
    DllStructSetData($tBMI, "Width", $iwidth)
    DllStructSetData($tBMI, "Height", -$iheight)
    DllStructSetData($tBMI, "Planes", 1)
    DllStructSetData($tBMI, "BitCount", 32)
    Local $hdc = _WinAPI_GetDC(0)
    Local $hcdc = _WinAPI_CreateCompatibleDC($hdc)
    Local $adib = DllCall('gdi32.dll', 'ptr', 'CreateDIBSection', 'ptr', 0, 'ptr', DllStructGetPtr($tBMI), 'uint', 1, 'ptr*', 0, 'ptr', 0, 'uint', 0)
    ; select object
    _WinAPI_SelectObject($hcdc, $adib[0])
    ; copy the content of the bitmap into the buffer ...
    _WinAPI_GetDIBits($hdc, $hbmp, 0, $iheight, $adib[4], DllStructGetPtr($tBMI), 1)
    ; create the a dllstruct with the pointer $aDIB[4]
    Local $stride = 3 * $iwidth + Mod($iwidth, 4) ;number of bytes in one line (filled with some bytes, because it must be a multiple of four!)
    $tbits = DllStructCreate('byte[' & $stride * $iheight & ']', $adib[4])
    $ptr = DllStructGetPtr($tbits)
    _GDIPlus_BitmapDispose($hBitmap)
    _WinAPI_DeleteObject($adib[0])
    Return $hcdc ;MemoryDC of bitmap
    EndFunc ;==>getDCfromfile

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

    Func _solve_linear_quad($a, $b) ;matrix,lösung Gaußsches Eliminationsverfahren, löst x gleichungen mit x unbekannten
    ;by Andy
    Local $n, $t
    Dim $Y[UBound($b)] ;ergebnisse
    $n = UBound($a) - 1 ;anzahl der zeilen/spalten
    ;falls erforderlich, zeilen und spalten tauschen
    If $a[0][0] = 0 Then ;wenn erster koeffizient = 0, dann kann das system nicht starten => spalten tauschen ggf zeilen tauschen
    For $k = 0 To $n ;jede zeile
    For $j = 0 To $n ;alle spalten in dieser Zeile testen
    If $a[$k][$j] <> 0 Then
    For $m = 0 To $n ;treffer, die erste spalte mit der j. tauschen
    $t = $a[$m][$j] ;sichern
    $a[$m][$j] = $a[$m][0] ;mit erster spalte tauschen
    $a[$m][0] = $t
    Next
    For $j = 0 To $n ;zeilen tauschen
    $t = $a[0][$j] ;sichern
    $a[0][$j] = $a[$k][$j] ;mit erster spalte tauschen
    $a[$k][$j] = $t
    Next
    $t = $b[0] ;ergebnisse auch tauschen
    $b[0] = $b[$k]
    $b[$k] = $t
    ExitLoop 2
    EndIf
    Next
    Next
    EndIf

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

    If $a[0][0] = 0 Then Return SetError(1, 0, 1)

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

    ;endlich rechnen :)
    For $I = 0 To $n ;alle zeilen
    If $a[$I][$I] <> 0 Then
    ;erstes element auf 1 bringen indem man gesamte zeile durch erstes Element teilt
    For $k = $I To $n
    $t = $a[$k][$I] ;erstes element merken
    If $t <> 0 Then ;nur, wenn das erste element ungleich null ist...
    For $j = $I To $n
    $a[$k][$j] /= $t ;alle zeilenmitglieder durch erstes element teilen
    Next
    ;b durch i teilen
    $b[$k] /= $t ;ergebnis natürlich auch
    EndIf
    Next
    ; _ArrayDisplay($a, "oben " & $I)
    ;zeile i von allen weiteren zeilen subtrahieren, erstes element wird zu 0
    For $k = $I + 1 To $n
    If $a[$k][$I] <> 0 Then ;wenn null, dann überspringen
    For $j = $I To $n
    $a[$k][$j] -= $a[$I][$j] ;die i.zeile von der aktuellen zeile subtrahieren
    Next
    $b[$k] -= $b[$I] ;ergebnisse natürlich auch
    EndIf
    Next
    ; _ArrayDisplay($a, "unten " & $I)
    Else ;null in aktueller spalte
    ;zeilen tauschen
    ; msgbox(0,$i,"null gefunden")
    For $k = $I + 1 To $n
    If $a[$k][$I] <> 0 Then ;zeile tauschen
    For $j = $I To $n ;zeilen tauschen
    $t = $a[$I][$j] ;sichern
    $a[$I][$j] = $a[$k][$j] ;mit erster spalte tauschen
    $a[$k][$j] = $t
    Next
    $t = $b[$I] ;ergebnisse auch tauschen
    $b[$I] = $b[$k]
    $b[$k] = $t
    EndIf
    ;erstes element auf 1 bringen indem man gesamte zeile durch erstes Element teilt
    For $k = $I To $n
    $t = $a[$k][$I] ;erstes element merken
    If $t <> 0 Then ;nur, wenn das erste element ungleich null ist...
    For $j = $I To $n
    $a[$k][$j] /= $t ;alle zeilenmitglieder durch erstes element teilen
    Next
    ;b durch i teilen
    $b[$k] /= $t ;ergebnis natürlich auch
    EndIf
    Next
    ; _ArrayDisplay($a, "oben1 " & $I)
    ;zeile i von allen weiteren zeilen subtrahieren, erstes element wird zu 0
    For $k = $I + 1 To $n
    If $a[$k][$I] <> 0 Then ;wenn null, dann überspringen
    For $j = $I To $n
    $a[$k][$j] -= $a[$I][$j] ;die i.zeile von der aktuellen zeile subtrahieren
    Next
    $b[$k] -= $b[$I] ;ergebnisse natürlich auch
    EndIf
    Next
    ;_ArrayDisplay($a, "unten1 " & $I)

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

    Next
    EndIf
    Next

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

    ;alle parameter bestimmen durch rückwärtseinsetzen

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

    $Y[$n] = $b[$n] ;letzter ist bereits bekannt
    For $I = $n - 1 To 0 Step -1
    For $j = $n To $I + 1 Step -1
    $b[$I] -= $a[$I][$j] * $Y[$j]
    Next
    $Y[$I] = $b[$I]
    Next
    Return $Y
    EndFunc ;==>_solve_linear_quad
    Exit

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

    Func _ReDraw($fPrecision)
    _GDIPlus_GraphicsClear($hGfxBuffer, 0xFF000000)
    _projective_mapping($hBmpBuffer, $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])
    ;_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)
    ; MsgBox(262144,'Debug line ~' & @ScriptLineNumber,'Selection:' & @lf & '$hGraphics' & @lf & @lf & 'Return:' & @lf & $hGraphics) ;### Debug MSGBOX

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

    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]

    Die AutoIt-Variante ist auskommentiert.

    Verfahren:
    Eckpunkte einlesen und zwischen den benachbarten Eckpunkten eine Geradengleichung y=mx+b erstellen. Das führt zu den Steigungen "_m" und den y-Achsenabschnitten "_b"
    Kleinster y(x)-Wert und grösster y(x)-Wert aus den Eckpunkten berechnen.
    Den "höchsten" Eckpunkt (kleinstes y(x) ) herausfinden.
    Nun hab ich mir was einfallen lassen^^
    Ich habe 2 Indizes erstellt, R und L (rechts und links), und den Geradengleichungen zugeordnet, einmal "linksrum" bis zur Koordinate mit dem grössten y-Wert, und einmal "rechtsrum"
    Somit brauchte ich nur, wenn die nächste Zeile (y) zu bestimmen war, den x-Wert der beiden Geradengleichungen aus dem (bekannten) y zu bestimmen, das führte zu xL und xR. Alle Punkte zwischen xL und xR sind immer innerhalb des Trapezoids! Somit entfällt die Abfrage, ob ein Punkt innerhalb des Vierecks ist, völlig!
    Die x-Koordinaten zwischen xL und xR werden mithilfe der Formel ausgerechnet und die entsprechende Pixelfarbe aus der Orginalbitmap gezogen.

    Wer eine Zeichnung braucht um das zu kapieren, soll sich melden^^

    Die "Zeile" der x-Koordinaten bietet sich natürlich für SSE2 (128 Bit berechnung) an, damit könnte man 4 Pixel auf einen Schlag berechnen, zzt mach ich das schön "langsam" nach der Reihe :D
    Schaumamal, was da noch geht...
    Bei den derzeitigen Grössen der Bitmap (s. Beispiel) ist bei mir die komplette Berechnung per ASM in ca 10ms erledigt, plus das locken (das dauert irre lange imho) der Bitmap und dem Gleichungslöser (3ms)

    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

    2 Mal editiert, zuletzt von Andy (5. Dezember 2010 um 22:16)

  • Zitat

    Bei einem 2000x2000 Bild 15 ms rechendauer.

    hehe, bei der "Rechendauer" ist der gesamte FASM-Kram noch dabei, das heisst incl. Programm Assemblieren!
    Bei meinem Referenz-P3 mit 1,2Ghz dauert z.B. das Assemblieren genauso lange wie das die eigentliche ASM-Programmlaufzeit!
    Mal schauen, was die SSE-Befehle bringen, ich hoffe, ich habe in der nächsten Woche bissl mehr Zeit...
    Aber Faktor 2-3 sollte mindestens dabei rauskommen.
    Aber auch mein selbstausgedachter Algorithmus ist nicht der langsamste, ein Referenzprogramm in C# hab ich jedenfalls schonmal um Faktor 50 abgehängt. Der prüft jedes Pixel des Buffers erstmal, ob es überhaupt im Viereck liegt. Das dauert... :D

    Da der ASM-Code threadsicher ist, könnte man natürlich auch mehrere Kerne einbinden! Dazu muss der Assemblercode nicht geändert werden, das funktioniert auch direkt aus AutoIt!

  • Habe mal ein Test durchgeführt und es kommt zum Hardcrash (Ausnahmefehler) -> C0000005 (!>20:35:34 AutoIT3.exe ended.rc:-1073741819)!

    Wenn ich die Mona Lisa (dein Lieblingsbild) lade und die linke obere Ecke in Richtung Mitte bewege, stürzt der Code ab (wenn ein Dreick entsteht)!

    Gruß,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

  • Zitat von UEZ

    Habe mal ein Test durchgeführt und es kommt zum Hardcrash (Ausnahmefehler) -> C0000005 (!>20:35:34 AutoIT3.exe ended.rc:-1073741819)!

    Das kommt daher...

    Zitat von Andy

    Einschränkend muss man allerdings sagen, dass nur "richtige" Trapezoide verwendet werden dürfen, soll heissen, konvexe konkave Vierecke (bei denen ein Eckpunkt innerhalb des Dreiecks der anderen drei Eckpunkte liegt) werden nicht dargestellt!

    Die Abfrage, ob das Viereck "konkav" ist, also einer der Eckpunkte innerhalb der von den drei anderen aufgespannten Fläche liegt, hab ich mir gespart....ist aber schon (seit längerem *hüstel*) auf der ToDo-Liste! Ich bin mir noch nicht so ganz sicher, ob man in diesem Fall überhaupt etwas darstellen sollte. Und wenn, was? Denn "perspektivisch" betrachtet, wird dabei die Fläche im Raum gekrümmt, und man sieht das Bild teilweise von hinten. Irgendwo habe ich mal eine Java-Animation gesehen, die das konnte. Allerdings nicht perspektivisch, sondern "nur" eine einfache distortion. Ich bleib am Ball....

  • Ich habe eine Bitte für dich, falls du mal Langeweile hast und nichts großes angehen kannst, weil zu wenig Zeit da ist.

    Ich bräuchte eine asm-Funktion die WinApi_StretchBlt ersetzen kann, aber schneller ist^^
    Dazu kann man auch die Funktion nutzen die hier vorgestellt ist, aber die enthält ja unmengen Code der für iene einfache Vergrößerung garnicht gebraucht wird.

    Da die DrawImage4Points ähnlich schnell im Vergrößern ist die die StretchBlt schätze ich, dass eine Asm-Func die ausschließlich aufs vergrößern ausgelegt ist wesentlich schneller ist.
    (Schätze das ist keine große Aufgabe, deshalb bettel ich hier mal :P)

    mfg
    Mars(i)