1. Dashboard
  2. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team
    4. Mitgliedersuche
  3. Forenregeln
  4. Forum
    1. Unerledigte Themen
  • Anmelden
  • Registrieren
  • Suche
Alles
  • Alles
  • Artikel
  • Seiten
  • Forum
  • Erweiterte Suche
  1. AutoIt.de - Das deutschsprachige Forum.
  2. Mitglieder
  3. Andy

Beiträge von Andy

  • Bitmap invertieren

    • Andy
    • 23. Dezember 2010 um 19:46

    Ich seh schon, wird Zeit, dass ich mir mal ein 64Bit BS besorge....thx fürs Testen jedenfalls!

  • Bitmap invertieren

    • Andy
    • 23. Dezember 2010 um 19:33

    Danke Oscar, liegt wohl daran, dass es bei 64Bit zwei der "user.dll" gibt....und ich die "falsche" benutze

  • Bitmap invertieren

    • Andy
    • 23. Dezember 2010 um 19:18

    eine Steilvorlage für Assemblerprogrammierer (oder die, die es werden wollen^^)
    Invertieren heisst auf Bitmapbearbeiterisch nämlich XOR 0xFFFFFF
    Das geht natürlich auch Pixel für Pixel in AutoIt, oder aber in Assembler 8o
    per XOR kann man nämlich direkt Speicherzellen bearbeiten (in diesem Fall invertieren)
    XOR [Speicher],0xFFFFFF
    invertiert somit das Pixel. Mit das einfachste, was man in Assembler machen kann

    Spoiler anzeigen
    [autoit]

    ;#include <AssembleIt.au3>
    #include <GDIPlus.au3>

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

    _GDIPlus_Startup()
    $file = FileOpenDialog("Grafikdatei öffnen", @ScriptDir, "Bilder (*.jpg;*.bmp;*.png)")
    If @error Then Exit
    $hBitmap = _GDIPlus_BitmapCreateFromFile($file)
    $iWidth = _GDIPlus_ImageGetWidth($hBitmap)
    $iHeight = _GDIPlus_ImageGetHeight($hBitmap)

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

    $hBitmapData = _GDIPlus_BitmapLockBits($hBitmap, 0, 0, $iWidth, $iHeight, BitOR($GDIP_ILMREAD, $GDIP_ILMWRITE), $GDIP_PXF32RGB)
    $Scan = DllStructGetData($hBitmapData, "Scan0") ;Pointer auf bitmapdaten(Pixel)

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

    ;$ret=_AssembleIt("ptr","_invertieren","ptr", $scan, "int", $iWidth * $iHeight) ;ptr als Rückgabe, um die hexzahlen schön zu sehen
    ;oder
    Global $tCodeBuffer = DllStructCreate("byte[23]") ;reserve Memory for opcodes
    DllStructSetData($tCodeBuffer, 1, "0x8B7424048B4C24088136FFFFFF0083C60483E90177F2C3") ;write opcodes into memory
    $ret = DllCall("user32.dll", "ptr", "CallWindowProcW", "ptr", DllStructGetPtr($tCodeBuffer), "ptr", $Scan, "int", $iWidth * $iHeight, "int", 0, "int", 0)

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

    _GDIPlus_BitmapUnlockBits($hBitmap, $hBitmapData)
    _GDIPlus_ImageSaveToFile($hBitmap, "invert.jpg")

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

    ShellExecute("invert.jpg")

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

    ;~ Func _invertieren()
    ;~ _("use32") ;sollte immer eingesetzt werden!

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

    ;~ _("mov esi,dword[esp+4]") ;Startadresse Bitmapdaten (Pixel)
    ;~ _("mov ecx,dword[esp+8]") ;anzahl Pixel

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

    ;~ _("_schleife:") ;so lange, bis ecx=0
    ;~ _("xor dword[esi],0xFFFFFF") ;Pixel invertieren
    ;~ _("add esi,4") ;adresse nächstes Pixel
    ;~ _("sub ecx,1") ;schleifendurchgang
    ;~ _("ja _schleife") ;so lange, bis ecx=0
    ;~ _("ret ")
    ;~ EndFunc ;==>_invertieren

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

    Geht auch bissl kürzer, aber so ist es verständlicher

    /EDIT/ Funktioniert das so eigentlich auch in 64Bit BS?

  • [GDI+] Hintergrund bzw Buffer clearen

    • Andy
    • 23. Dezember 2010 um 08:55

    @sprenger, bei weißem Hintergrund hast du Recht, wenn man allerdings ein Bild als Hintergrund hat, dann kopiert man nur die entsprechenden Bildteile, um die von den Ellipsen überdeckten Bereiche zu "löschen". Da sämtliche durch die GDI-Funktionen bearbeiteten Daten komplett über den Bus zur Graka geschoben werden, ist es schon ein Unterschied, ob man 1920x1080 Pixel über den Bus jagt, oder nur 50x50. Pro Frame natürlich.

    Zitat

    und wie?

    Du weisst, an welcher Position die "alte" Ellipse gezeichnet wurde. Diese bedeckt nur einen kleinen Teil des Hintergrundes. Anstatt nun den kompletten Hintergrund (Backbuffer) mit dem Hintergrund zu überschreiben um die winzige Ellipse zu "löschen", überschreibt man nur den Teil des Hintergrundes, der von der Ellipse bedeckt wird.
    Wenn deine Ellipse 30x30 Pixel gross ist, kopiere aus dem Hintergund die Fläche an der Position der Ellipse (30x30 Pixel) in den Backbuffer und danach die "neue" Ellipse.

    In AutoIt könnte es damit irgendwann kritisch werden, da der Verwaltungsaufwand bzw der Overhead der GDI-Funktionsaufrufe bei vielen kleinen Sprites die Geschichte eher verlangsamt. Aber wer "richtig schnell" Grafiken darstellen möchte, dem bleibt nur übrig, so wenige Pixel wie möglich zu bearbeiten.

  • GDI+ Bitmap "trapezoid" zeichnen / DrawImage_4Points

    • Andy
    • 23. Dezember 2010 um 08:25
    Zitat

    Ich bräuchte eine asm-Funktion die WinApi_StretchBlt ersetzen kann, aber schneller ist

    ja, das wäre sicher machbar, allein durch SSE wäre da einiges rauszuholen. Wozu brauchst du etwas derart schnelles? Stretchblt() hat jedenfalls bei mir noch nie für Verzögerungen gesorgt, da hängts grösstenteils an ganz anderen Punkten :D
    Ich muss erstmal die anderen Baustellen fertigbekommen...

  • [GDI+] Hintergrund bzw Buffer clearen

    • Andy
    • 22. Dezember 2010 um 18:14

    hi,
    wie du schon bemerkt hast, überschreibt _GDIPlus_GraphicsClear nur den bestehenden Graphic-context mit einer Farbe.
    Du musst dein Bild benutzen, um darauf die Ellipsen zu zeichnen.
    Bild in Backbuffer, Ellipsen in Backbuffer, aklles weitere in Backbuffer, zum Schluss Backbuffer in GUI kopieren.

    /edit/ wenn es zu langsam ist, immer das komplette Bild in den Backbuffer zu zeichnen, erstelle eine Kopie des Bildes und kopiere immer nur den kleinen Teil, der durch die Ellippsen überschrieben wurde.

  • GDI-Vector

    • Andy
    • 22. Dezember 2010 um 10:39
    Zitat

    Mit der linearen Funktionsgleichung ist es gut umsetzbar für den linken Strahl aber nicht für den rechten
    weil der bei ($Width|$Height) anfängt und auf ($Mouse[0]|$Mouse[1]) geht.

    wieso?
    Der Geradengleichung y=mx+b ist es völlig schnurz, welche Koordinaten gewählt werden. Bis auf den Fall, dass delta x = 0 ist (Gerade senkrecht zur x-Achse) sollte es kein Problem geben!

    Spoiler anzeigen
    [autoit]

    #include <GDIPlus.au3>
    #include <GuiConstants.au3>

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

    Opt("GuionEventmode",1)

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

    _GDIPlus_Startup()

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

    $Width = 800
    $Height = 600

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

    $hWnd = GUICreate("Test",$Width,$Height)

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

    GUISetOnEvent($GUI_EVENT_CLOSE,"_Exit")

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

    GUISetState(@SW_SHOW)

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

    Global $hPen = _GDIPlus_PenCreate(0xFFFF0000,5)

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

    Global $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hWnd)

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

    Global $hBitmap = _GDIPlus_BitmapCreateFromGraphics($Width, $Height, $hGraphics)
    Global $hBackbuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)

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

    Global $hFGBitmap = _GDIPlus_BitmapCreateFromGraphics($Width,$Height, $hGraphics)
    Global $hFGBackbuffer = _GDIPlus_ImageGetGraphicsContext($hFGBitmap)

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

    ;koordinaten der ecken
    $x0=0;links
    $y0=$Height
    $x1=$width;rechts
    $y1=$Height
    $step=5 ;schrittweite der punkte

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

    While 1
    $Mouse = GUIGetCursorInfo($hWnd)

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

    _GDIPlus_GraphicsClear($hFGBackbuffer,0xFFFFFFFF)
    ;~ If $Mouse[2] = 1 Then
    ;links
    $m=($mouse[1]-$y0)/($mouse[0]-$x0)
    $b=$mouse[1]-$m*$mouse[0]
    for $x=$x0 to $mouse[0] step $step
    $y=$m*$x+$b;y-koordinate
    _GDIPlus_GraphicsDrawEllipse($hGraphics, $X, $Y, 2, 2, $hPen)
    next

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

    ;rechts
    $m=($mouse[1]-$y1)/($mouse[0]-$x1)
    $b=$mouse[1]-$m*$mouse[0]
    for $x=$x1 to $mouse[0] step -$step
    $y=$m*$x+$b;y-koordinate
    _GDIPlus_GraphicsDrawEllipse($hGraphics, $X, $Y, 2, 2, $hPen)
    next

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

    ;~ _GDIPlus_GraphicsDrawLine($hFGBackbuffer,0,$Height,$Mouse[0],$Mouse[1],$hPen)
    ;~ _GDIPlus_GraphicsDrawLine($hFGBackbuffer,$Width,$Height,$Mouse[0],$Mouse[1],$hPen)

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

    ;~ EndIf

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

    _GDIPlus_GraphicsDrawImageRect($hBackbuffer,$hFGBitmap,0,0,$Width,$Height)
    _GDIPlus_GraphicsDrawImageRect($hGraphics,$hBitmap,0,0,$Width,$Height)
    WEnd

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

    Func _Exit()
    _GDIPlus_Shutdown()
    Exit
    EndFunc

    [/autoit]
  • Bitmap Daten direkt aus Arbeitsspeicher auslesen

    • Andy
    • 21. Dezember 2010 um 10:23

    Hi zusammen,
    dass der Lock/Unlock ziemlich viel Zeit verbraucht, hatte ich schon bei anderen Aufgaben bemerkt. Leider ist mir bisher keine andere Variante untergekommen, um den Pointer auf die Bitmapdaten zu bekommen. Ich hatte schon daran gedacht, das "Handle" auseinanderzuklabustern. Ein Handle ist ja nichts weiter als ein Zeiger auf einen Speicherbereich mit Informationen. Irgendwo in diesem Speicherbereich muss zwangsläufig auch die Adresse der Bitmap stehen. Wenn da jemand bissl Zeit in reverse engeneering investieren würde, wäre das sehr zu begrüssen :D
    name22
    hast du schon versucht, die Bitmaps zu blitten? Das ist idR ziemlich schnell, mit etwas Glück unterstützt der Treiber der Graka das Blitten.

  • PushTheButton, ermöglicht Mausklick auf sonst nicht erreichbare Grafiken UPDATE 1.36

    • Andy
    • 20. Dezember 2010 um 06:33

    naja, die beiden verwendeten Prospeed-Funktionen sind derart simpel, die kann ich bei Bedarf in 10-20 Zeilen Asm unterbringen.
    Ggf sogar in eine mini-Dll packen. Da geht was :D
    Wobei die Geschwindigkeit auch mit "native" AutoItcode ausreichend sein sollte, jedenfalls für "normale" Anwendungen :D

  • Interessante Kodierung in der Autoit-Memory

    • Andy
    • 20. Dezember 2010 um 06:23
    Zitat

    au man, was ist denn mit euch los ? oder macht ihr alles späße ?

    Völliger Ernst das alles ist, junger Padawan!

    Zitat

    und entdecke dass es einen "echten" kompiler für AutoIt Skripte gibt der automatisch alle Variablen richtig deklariert und castet und eine richtig "echte" asm-Exe daraus macht. xD

    :D Naja, eine "richtige" Exe hat man doch heute schon. Das Argument der Größe lasse ich nur in absoluten Ausnahmefällen gelten, wenn das so wichtig wäre, gäbe es wesentlich mehr *.COM-Dateien :love:

    Zitat

    C++ Code.
    Der wird dann Kompiliert.

    Kompilieren kann man jeden Code, das ist nicht das Ding! Aber so zu kompilieren, dass es JEDER Anforderung gerecht wird, ist das Problem! Genaue Berechnung oder schnelle Berechnung bissl schnell oder ungenaue Berechnung und ganz schnell?
    C++ ist da ein hervorragendes Beispiel! Da wird lauthals die Portabilität hervorgehoben, aber wenn es "wirklich" mal drauf ankommt, kommt man nicht drumherum vom "Standard" abzuweichen, und auf für die jeweilige Plattform optimierte Libs einzusetzen. Und/oder hunderte Compilerschalter vorzusehen, die auch noch grösstenteils voneinander abhängig sind und jeweils andere Ergebnisse produzieren...

    Da bleibe ich lieber bei meinem AutoIt-Spaghetticode, undeklarierten Variablen unbestimmten Typs und "eingeschränkter" Geschwindigkeit, die übrigens in 99% aller Fälle völlig ausreiched ist. Ich bin Techniker, kein Programmierer. Das Ergebnis zählt. Und Leistung = Arbeit pro Zeit. In 15 Minuten ein "Script" incl benutzbarer Oberfläche erstellen zu können, welches mir und meinen Mitarbeitern die Arbeit erleichtert, ist m.E. mehr Wert als "Portabilität".

    Zitat

    Was auch gehen müsste was Java (auch wenn ich es persönlich nicht mag ) uns vorgemacht hat:
    Einen Installierbaren Interpreter der wesentlich schneller interpretieren kann als der Jetzige von AutoIt.

    Zieh mal 2000 Programmierer von Sun ab, in ca 10-15 Jahren hast du dann auch ein "schnelles" AutoIt :rofl:
    Nein, mal im Ernst, Java ist der Weg, und auch an der Idee von .Net ist was dran. Anders ist wirkliche Portabilität nicht machbar. Und das ist gut so! Aber Moment, irgendeiner hat doch was von Dateigrösse gesagt ;) ....

  • Interessante Kodierung in der Autoit-Memory

    • Andy
    • 19. Dezember 2010 um 17:43
    Zitat

    Andy: Man, jetzt hast du die ganze Verschwörungstheorie widerlegt.

    nöööö, das war doch nur ein kleiner Stupser in die Richtung, wie man dieses Logo aus dem "Memory" (sic) extrahieren und anzeigen könnte.
    Kürzestes Script gewinnt! 8o

  • Interessante Kodierung in der Autoit-Memory

    • Andy
    • 19. Dezember 2010 um 16:03

    ....oder einfach nur das(die) Logo-Icons in einem 16(32)-Bit-Farbformat.... :thumbup:
    Irgendwo müssen diese Dinger ja herkommen, oder hat sich bisher noch keiner gefragt, woher das Icon kommt, dass nach einem herzhaften Hieb auf F5 unten in der Taskleiste steht? 8o

    Bitmap-Format FTW

  • PushTheButton, ermöglicht Mausklick auf sonst nicht erreichbare Grafiken UPDATE 1.36

    • Andy
    • 19. Dezember 2010 um 15:51

    Hallo,
    wahrscheinlich gibt es ein mir nicht bekanntes Problem mit der Prospeed.dll (welches System?).Ggf funktioniert diese nicht auf 64Bitsystemen.
    Du kannst aber auch mit etwas Verzicht auf Geschwindigkeit die prospeed.dll im Verzeichnis löschen. Dann läuft reiner AutoItcode, auch unter 64Bit.

  • PushTheButton, ermöglicht Mausklick auf sonst nicht erreichbare Grafiken UPDATE 1.36

    • Andy
    • 18. Dezember 2010 um 09:34

    Hi,

    Zitat

    Hast du schon das Scrollen innerhalb von Browsern realisiert?!?

    In den ersten hier geposteten Versionen war es noch enthalten, ich hatte es rausgenommen weil ich es a) den Browsergame-Fernsteuerungen nicht allzuleicht machen wollte ;) , und b) die Abfrage "Seitenende" nicht besonders zuverlässig in allen Fällen funktionierte (bei allen Browsern).

    Zitat

    Weil bei meiner XP Maschiene muss ich immer manuell innberhalb der Seite einen Scroller nach unten verschieben bevor der zu klickende Button sichtbar wird.

    Simple Lösung: ein SEND pgdn, nachdem das Browserfenster mit der neuen Seite geöffnet wurde 8)
    Ich hatte schon mit div. Scroll-udf´s herumexperimentiert, wie gesagt, Browser sind da manchmal bissl eigen...besonders mit der Rückmeldung, ob das pgdn ausgeführt wurde. Man könnte natürlich abfragen, ob sich der Seiteninhalt geändert hat ;) .

    Allerdings sind meine Anwendungen noch nicht zeitkritisch, solange das Programm schneller ist als jeder Mensch der im 3-Schichtbetrieb 8h lang auf den Monitor stiert, habe ich keinen Handlungsbedarf.

    Zitat

    Und ist es so richtig das ich immer '_GDIPlus_Startup' und '_GDIPlus_Shutdown' Manuell ausführen muss,

    Die Beispiele sollten alle laufen, ich habe hier schon lange nicht mehr geupdatet, der "Bedarf" scheint nicht sehr gross zu sein, wenn man nicht die gängigen "bösen" Begriffe in den Postings hier im Forum spammt :rofl:

  • Suche nach leicht variierendem Text

    • Andy
    • 16. Dezember 2010 um 14:36

    Hallo Webfish,

    Zitat

    Umsatz Januar war 12.000

    ist es richtig, dass du den fetten Teil des Textes suchst?
    Wenn das so sein sollte, gibt es maximal 12 mögliche Suchstrings, nämlich die Monatsnamen.
    Schau dir für diesen Fall mal das Programm PushTheButton an. Damit wäre es z.B.möglich, die 12 Texte "Umsatz war Januar","Umsatz war Februar" usw. von der Website einmalig "abzufotografieren", und diese gespeicherten Bilder dann automatisch auf der Website suchen zu lassen.
    Die Suche gestaltet sich relativ zügig, die 12 Monatanamen sind auf einer Website incl. automatischem Scrollen im Browser in weniger als einer Sekunde gefunden.

    /EDIT/ sry, hatte überlesen, dass der Text schon vorliegt

  • Neuling brauch Hilfe beim programmieren seiner Uhr.

    • Andy
    • 15. Dezember 2010 um 15:08

    kurzes Beispiel, in der Console werden die Millisekunden ausgegeben

    Spoiler anzeigen
    [autoit]

    #include<date.au3>
    #include <GUIConstantsEx.au3>
    ;timertest

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

    global $t=timerinit(),$sec=0

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

    $hgui=guicreate("timer",200,50)
    $label=GUICtrlCreateLabel("",20,20,200,30)
    GUISetState()

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

    adlibregister("Millisekunde",1) ;theoretisch jede Millisekunde aufrufen

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

    while GUIGetMsg()<>-3
    wend

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

    func Millisekunde();praktischer Aufruf alle x Millisekunden
    $time=_nowtime()
    consolewrite($time&" : "&int(timerdiff($t))&@crlf)
    GUICtrlSetData($label,$time&" : "&int(timerdiff($t)))
    if stringright($time,1)<>$sec Then
    $t=timerinit()
    $sec=stringright($time,1)
    endif
    endfunc

    [/autoit]
  • Neuling brauch Hilfe beim programmieren seiner Uhr.

    • Andy
    • 15. Dezember 2010 um 10:24

    Hallo!

    Zitat

    Ich versuche so eine Uhr wo immer 1000 mikrosekunden dazu gerechnet werden.
    Genau das ist das wo für ich hilfe brauch. Ich verstehe nicht wie man die Aktuellezeit in Mikrosekunden umrechnet.

    Um die Mikrosekunden zu errechnen, teilt man einfach die ermittelten Sekunden durch 1000000.
    Die Frage ist allerdings, ob du es schaffst, jede Mikrosekunde auch anzeigen zu lassen!
    Also einen Timer, der jede Sekunde in 1000000 Teile teilt und diese dann innerhalb dieser Sekunde hochzählt.
    Viel Spass dabei!
    Das Problem dabei ist, dass das Betriebssystem dir dein Programm regelmäßig unterbricht, um auch andere Programme "gleichzeitig" laufen zu lassen. Diese Unterbrechung wirft natürlich alles an genauer Berechnung im Mikrosekundenbereich über den Haufen.
    Eine weitere Möglichkeit wäre, die Prozessor-Takte seit dem Rechnerstart abzufragen. Mit einer (internen) Umrechnung ist das genau das, was

    [autoit]

    Timerinit() Timerdiff()

    [/autoit]

    machen. Aber einzelne Mikrosekunden einzufangen wirst du nicht schaffen....

    1000 Mikrosekunden sind 1 Millisekunde, da sollte das wenigstens Ansatzweise möglich sein....

  • ImageSearch und der unsichtbare Background

    • Andy
    • 14. Dezember 2010 um 23:19

    Um das abschliessend auch meinerseits mal klarzustellen, die Frage lautete:"Kann man bei ImageSearch auch Bilder mit unsichtbarem Background benutzen?"
    Genau diese Frage wurde bereits gefühlte 12 Millionen Mal sowohl in diesem Forum, als auch im "bösen" Botforum, im englischen und im französischen Forum gestellt und dort auch beantwortet.
    Aus diesem Grund auch mein Hinweis mit der erlesenen Gesellschaft in der du dich befindest. Anderen geht es genauso!
    Natürlich ist mir klar, dass jemand bevor er hier einen Thread erstellt, zunächst die Suchfunktion der Foren und auch die Tante Google bemüht. Ich gehe also davon aus, dass du geflissentlich sämtliche dort gefundenen Hinweise und Lösungsvorschläge einfach ignorierst.

    Somit wäre eigentlich die passende Antwort auf "Kann man bei ImageSearch auch Bilder mit unsichtbarem Background benutzen?", ein einfaches "JA!" gewesen. Wäre damit dein Problem gelöst gewesen?! Offensichtlich nicht.

  • n-te Ziffer von Pi berechnen nach dem Bailey - Borwein - Plouffe-Verfahren

    • Andy
    • 14. Dezember 2010 um 23:01

    Kurzes Beispiel, wie exterm SSE die Geschwindigkeit beeinflussen kann!

    Spoiler anzeigen
    [autoit]

    ;Übersetzung FORTRAN => AutoIt by Andy
    ;Verfahren: http://www.unet.univie.ac.at/~a8727063/Science/BBP/
    ;
    ;Beispiele in FORTRAN;
    ;http://www.unet.univie.ac.at/~a8727063/Science/BBP/bbp.f90 bzw.
    ;http://www.unet.univie.ac.at/~a8727063/Science/BBP/bbpI2R4.f90
    ;
    ;errechnet die n-te Dezimalstelle von PI als HEX-Ziffer
    ;vgl. Tabelle der Ziffern bis 5000
    ;http://books.google.de/books?id=mchJC…tabelle&f=false

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

    #include<assembleit.au3>
    #include <Array.au3>

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

    Dim $arrC[4] = [4, -2, -1, -1]
    Dim $arr1[4]
    Dim $arr2[4]
    Dim $arr3[4]
    Dim $arr4[4]

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

    Global $time, $k

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

    $log2 = Log(2)
    $log16 = Log(2.0) * 4

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

    $err = 5 * 10 ^ - 32
    $nmax = Int((Sqrt(2 ^ 63) - 5) / 8)

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

    ;ohne _MemVirtualAlloc() kein align!
    ;align 16 in der dllstruct() funktioniert NICHT zuverlässig!
    $pRemoteCode = _MemVirtualAlloc(0, 512, $MEM_COMMIT, $PAGE_EXECUTE_READWRITE)
    $struct = DllStructCreate("" & _ ;adresse in der struct
    "float arr1[4];" & _ ;edi+00 xmm7=4,4,4,4
    "float arr2[4];" & _ ;edi+16 xmm6=1,1,1,1
    "float arr3[4];" & _ ;edi+32 xmm3=0,0,0,0
    "float arr4[4];" & _ ;edi+48
    "float arr5[4];" & _ ;edi+64 xmm5=1,4,5,6
    "float nullfuenf;" & _ ;edi+80
    "float log2" & _ ;edi+84
    "int", $pRemoteCode) ;edi+88 speicherplatz div zwischenwerte
    $ptr = DllStructGetPtr($struct)
    For $i = 1 To 4
    DllStructSetData($struct, 1, 4.0, $i);xmm7=4,4,4,4
    DllStructSetData($struct, 2, 1.0, $i);xmm6=1,1,1,1
    DllStructSetData($struct, 3, 0.0, $i);xmm3=0,0,0,0
    Next
    DllStructSetData($struct, 5, 1.0, 1);xmm5=1
    DllStructSetData($struct, 5, 4.0, 2);xmm5=1,4
    DllStructSetData($struct, 5, 5.0, 3);xmm5=1,4,5
    DllStructSetData($struct, 5, 6.0, 4);xmm5=1,4,5,6

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

    DllStructSetData($struct, 6, 0.5, 1);0.5
    DllStructSetData($struct, 7, $log2, 1);log2

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

    Func _pi_hex()
    _("use32")
    _("finit") ;copro -init
    _("mov edi,[esp+4]") ;startadresse struct holen

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

    _("movaps xmm7,[edi+00]") ;arr1=4,4,4,4
    _("movaps xmm6,[edi+16]") ;arr2=1,1,1,1
    _("movaps xmm3,[edi+32]") ;arr3
    _("movaps xmm5,[edi+64]") ;arr5=1,4,5,6

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

    _("mov ebx,-1") ;zähler K
    _("_for_k:")
    _("add ebx,1")

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

    _("cmp ebx,[esp+8]") ;vgl k mit N
    _("ja _ende") ;wenn fertig, ende

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

    _("mov edx,[esp+8]") ;l=n
    _("sub edx,ebx") ;l=n-k

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

    _("movaps xmm1,xmm7") ;arr1=4,4,4,4
    _("movaps xmm2,xmm6") ;arr2=1,1,1,1
    ;arr4=1+k+8 , 4+k*8 , 5+k*8 , 6+k*8
    _("mov eax,ebx") ;k
    _("shl eax,3") ;k*8 20
    _("mov [edi+48],eax") ;arr4=0 , k*8 , 0 , 0
    _("mov [edi+56],eax") ;arr4=0 , k*8 , 0 , k*8
    _("movsldup xmm4,[edi+48]") ;arr4=k*8 , k*8 , k*8 , k*8
    _("cvtdq2ps xmm4,xmm4") ;arr4 float( aus allen 4 integer)
    _("addps xmm4,xmm5") ;arr4=1+k*8,4+k*8,5+k*8,6+k*8

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

    _("cmp edx,0") ;ist L=0?
    _("je _arr3") ;ja, dann arr3:
    _("")
    ;int(log(L+0.5)/log2) ;folgende zeilen stark kürzbar
    _("mov [edi+88],edx") ;L
    _("emms") ;fpu und sse zusammen braucht emms!
    _("fld dword[edi+80]") ;st0=0.5
    _("fld dword[edi+84]") ;st0=log2 st1=0.5
    _("fldln2") ;st0=ln2 st1=log2 st2=0.5
    _("fild dword[edi+88]") ;st0=L st1=1 st2=log2 st3=0.5
    _("fadd st0,st3") ;st0=L+0.5 st1=1 st2=log2 st3=0.5
    _("fyl2x") ;st0=ln2*log_2(L+0.5) st1=log2 st2=0.5 32550
    _("fdiv st0,st1") ;st0=(ln2*log_2(L+0.5)/log2) st1=log2 st2=0.5
    _("fisttp dword[edi+88]") ;st0=log2 st1=0.5
    _("fucompp") ;fpu-stack cleanen

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

    _("mov esi,-1")
    _("_for_i:")
    _("add esi,1")
    _("cmp esi,[edi+88]") ;ist i=int(log(L+0.5)/log2) ?
    _("ja _arr3")
    _("")
    ;arr1=mod(arr1^2,arr4) für alle 4 floats

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

    _("mulps xmm1,xmm1") ;arr1^2
    _("movaps xmm0,xmm1") ;arr1^2
    ;;berechnet mod=rest=a-int(a/b)*b
    _("divps xmm0,xmm4") ;a/b
    _("cvttps2dq xmm0,xmm0") ;int(a/b)
    _("cvtdq2ps xmm0,xmm0") ;float(int(a/b))
    _("mulps xmm0,xmm4") ;int(a/b)*b
    _("subps xmm1,xmm0") ;arr1=mod(arr1^2,arr4) für alle 4 floats ;
    _("")
    _("bt edx,esi") ;bit_test(L,I)
    _("jnc _for_i")
    _("")
    ;arr2=mod(arr2*arr1,arr4)
    _("mulps xmm2,xmm1") ;arr2*arr1
    _("movaps xmm0,xmm2") ;arr2*arr1
    ;;berechnet rest=a-int(a/b)*b
    _("divps xmm0,xmm4") ;a/b
    _("cvttps2dq xmm0,xmm0") ;int(a/b)
    _("cvtdq2ps xmm0,xmm0") ;float(int(a/b))
    _("mulps xmm0,xmm4") ;int(a/b)*b
    _("subps xmm2,xmm0") ;arr2=mod(arr2*arr1,arr4) für alle 4 floats

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

    _("jmp _for_i")

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

    _("_arr3:")
    _("movaps xmm0,xmm2") ;arr2
    _("divps xmm0,xmm4") ;arr2/arr4
    _("addps xmm3,xmm0") ;arr3+arr2/arr4
    _("movaps xmm0,xmm3") ;arr3+arr2/arr4
    ;;berechnet rest=a-int(a/b)*b
    _("divps xmm0,xmm6") ;a/b
    _("cvttps2dq xmm0,xmm0") ;int(a/b)
    _("cvtdq2ps xmm0,xmm0") ;float(int(a/b))
    _("mulps xmm0,xmm6") ;int(a/b)*b
    _("subps xmm3,xmm0") ;arr3=mod(arr3+arr2/arr4,arr6) für alle 4 floats
    _("jmp _for_k")

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

    _("_ende:")
    _("movaps [edi],xmm3") ;xmm3 ins erste feld der struct schreiben
    _("movaps [edi+48],xmm4");xmm3 ins erste feld der struct schreiben
    _("mov eax,edx") ;L return
    _("ret")
    _("")

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

    EndFunc ;==>_pi_hex

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

    While 1
    $n = InputBox("n-te Stelle von PI", "Gesuchte Ziffer eingeben max=" & $nmax)
    If $n <= 0 Or $n > $nmax Then Exit
    For $i = 1 To 4 ;struct füllen für den Assemblerteil
    DllStructSetData($struct, 1, 4.0, $i);xmm7=4,4,4,4
    DllStructSetData($struct, 2, 1.0, $i);xmm6=1,1,1,1
    DllStructSetData($struct, 3, 0.0, $i);xmm3=0,0,0,0
    Next

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

    ;der Assemblerteil ersetzt die Hauptschleife For K=0 to N
    ;folgende 2 Zeilen gehören an den Anfang des Scripts

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

    Global $tCodeBuffer = DllStructCreate("byte[213]") ;reserve Memory for opcodes
    DllStructSetData($tCodeBuffer, 1, "0x9BDBE38B7C24040F283F0F2877100F285F200F286F40BBFFFFFFFF83C3013B5C24080F87A30000008B54240829DA0F28CF0F28D689D8C1E003894730894738F30F1267300F5BE40F58E583FA00745B8957580F77D94750D94754D9EDDB4758D8C3D9F1D8F1DB4F58DAE9BEFFFFFFFF83C6013B775877330F59C90F28C10F5EC4F30F5BC00F5BC00F59C40F5CC80FA3F273DD0F59D10F28C20F5EC4F30F5BC00F5BC00F59C40F5CD0EBC50F28C20F5EC40F58D80F28C30F5EC6F30F5BC00F5BC00F59C60F5CD8E950FFFFFF0F291F0F29673089D0C3") ;write opcodes into memory

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

    $flag = 1 ;wenn 0, dann AssembleIt()

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

    If $flag Then ;CallWindowProcW
    $t = TimerInit()
    $ret = DllCall("user32.dll", "int", "CallWindowProcW", "ptr", DllStructGetPtr($tCodeBuffer), "ptr", $ptr, "int", $n, "int", 0, "int", 0)
    $m = TimerDiff($t)
    $l = $ret[0]
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $m = ' & $m & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
    Else
    ;$_assembleit_flag=0 ;um opcodes aus dem Assemblercode zu erstellen
    $t = TimerInit()
    $l = _AssembleIt("int", "_pi_hex", "ptr", $ptr, "int", $n)
    $m = TimerDiff($t)
    ;$l = $ret[0]
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $m = ' & $m & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
    EndIf

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

    ;Auswertung:
    For $i = 1 To 4 ;array aus der struct füllen
    $arr3[$i - 1] = DllStructGetData($struct, 1, $i)
    $arr4[$i - 1] = DllStructGetData($struct, 4, $i)
    Next

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

    $fsum = _modulo(_dot_product($arrC, $arr3), 1.0)

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

    Dim $asum[4]
    $asum[0] = $arrC[0] / ($arr4[0] + 8)
    $asum[1] = $arrC[1] / ($arr4[1] + 8)
    $asum[2] = $arrC[2] / ($arr4[2] + 8)
    $asum[3] = $arrC[3] / ($arr4[3] + 8)

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

    $cor = _sum($asum) / 16
    $ester = $k * $err
    $string = ""
    For $i = 2 To Int(-Log($cor) / $log16)
    If $i = $l Then $string &= "( "
    $fsum = 16 * Mod($fsum, 1.0)
    $string &= Hex(Int($fsum), 1) & " "
    Next
    If $i > $l And StringInStr($string, "(") Then $string &= ")"

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

    MsgBox(0, $n + 1 & " -te hex-ziffer von Pi =", Hex(Int(16 * _Modulo(_dot_product($arrC, $arr3), 1.0)), 1) & @CRLF & @CRLF & "nächste Ziffern (incl.) = " & $string)

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

    WEnd

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

    Func _akt()
    ConsoleWrite('timerdiff($time) = ' & Int((TimerDiff($time) + 1) / 1000) & " k= " & $k & @CRLF) ;### Debug Console
    EndFunc ;==>_akt

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

    Func _dot_product($a, $b)
    $vec = 0
    For $i = 0 To UBound($a) - 1
    $vec += $a[$i] * $b[$i]
    Next

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

    Return $vec
    EndFunc ;==>_dot_product

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

    Func _btest($a, $pos) ;bittest liefert TRUE, wenn das ($pos-te Bit von $a) = 1 ist
    ;http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gfortran/BTEST.html
    $bit = BitAND(2 ^ 31 - 1, 2 ^ $pos)
    If BitAND($a, $bit) Then
    Return True
    Else
    Return False
    EndIf

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

    EndFunc ;==>_btest

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

    Func _modulo($a, $b) ;ir1 - floor(ir1/ir2)*ir2
    ;http://de.wikibooks.org/wiki/Fortran:_…nktionen#Modulo
    Return $a - Floor($a / $b) * $b
    EndFunc ;==>_modulo

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

    Func _sum($e)
    $sum = 0
    For $i = 0 To UBound($e) - 1
    $sum += $e[$i]
    Next
    Return $sum
    EndFunc ;==>_sum

    [/autoit]


    Leider gibt es einen kleinen Pferdefuss, den ich bisher noch nicht lokalisieren konnte.
    Die hex-Ziffern werden leider nur bis zur ca. 550. Stelle richtig berechnet. Ab der 550. Stelle schleicht sich ein minimaler Fehler ein, der dazu führt, dass die folgenden Ergebnisse falsch werden.
    Ob das schon mit dem einfachen float-Format (32bit) zu tun hat, werde ich untersuchen.

    Jedenfalls ist die Geschwindigkeit sagenhaft, da ein komplettes $Array[4] in einem XMM-Register Platz hat und so alle Berechnungen für jeden Teilnehmer im Array durchgeführt werden.
    bsp Multiplikation zweier Arrays $a[4] und $b[4]:
    $a[0]=$a[0]*$b[0]
    $a[1]=$a[1]*$b[1]
    $a[2]=$a[2]*$b[2]
    $a[3]=$a[3]*$b[3]
    wird zu
    mulps xmm0,xmm1 ;jeweils gefüllt mit 4 floats
    und das wird in einer Handvoll Takte berechnet.

    Die millionste Stelle wird vom Script so in weit unter einer Sekunde ermittelt! Wobei man fairerweise zugeben muss, dass ab der ca. 5000. Stelle die Genauigkeit der floats sowieso nicht mehr ausreichend ist. Vielleicht weite ich das Script ja noch auf 64Bit Genauigkeit aus.....schaumamal^^

  • ImageSearch und der unsichtbare Background

    • Andy
    • 14. Dezember 2010 um 16:34

    Man merkt mal wieder deutlich das geistige Defizit bei der Problembeschreibung! Aber tröste dich, du befindest dich in erlesenster Gesellschaft!

    Um mal den "Apparat", der sich idR zwischen den Ohren befinden sollte, bissl anzutreiben:
    Wer zwingt dich denn, mehr an Daten (Pixel) abzufragen, als du eigentlich brauchst?

    Um mal bei deinem Beispielicon Trashbin mit transparentem "Hintergrund" zu bleiben, wo ist das Problem nur die Pixel zu suchen, die NICHT transparent sind?
    Bei mehrteiligen, weil durch transparente Flächen unterbrochenen Suchmasken, macht man halt mehrere "kleine" Abfragen!
    Das bedeutet natürlich Aufwand und vor allem Knowhow!

    Mit PushTheButton (such mal danach hier im Forum) finde ich im täglichen Einsatz sogar bewegte Bilder mit transparentem Hintergrund. Imagesearch kann das mit Sicherheit auch!
    Auf eine C&P-"Lösung" musst du allerdings lange warten....

Spenden

Jeder Euro hilft uns, Euch zu helfen.

Download

AutoIt Tutorial
AutoIt Buch
Onlinehilfe
AutoIt Entwickler
  1. Datenschutzerklärung
  2. Impressum
  3. Shoutbox-Archiv
Community-Software: WoltLab Suite™