GDI+ Bitmap.SetPixel

  • Ich hab gerade nicht viel Zeit, deswegen in Kurzfassung:
    Folgendes Problem, in meinem Code habe ich folgende Zeile, wie im MSDN-Beispiel (http://msdn.microsoft.com/en-us/library/…28VS.85%29.aspx:(
    Status r=bmp.SetPixel(x,y,Color(255,0,0,0));
    Aber r wird zu "InvalidParameter", deswegen bräuchte ich eure Hilfe.
    Ich werde später noch den ganzen Code anhängen.
    Aufruf ohne Parameter (erster Aufruf):
    Status r=bmp.SetPixel(0,0,Color(255,0,0,0));

    EDIT:
    Code angehängt, wer sich über das LockBits wundert, das war mein erster Versuch, aber mitten im Bild gibt es einen Fehler beim Pixel auslesen... Deswegen versuch ich's jetzt erstmal mit SetPixel

  • Hi,
    wenn ich deinen Code richtig interpretiere, holst du dir doch schon per bmp.LockBits() einen Pointer auf die Bitmapdaten bzw Pixel. Wieso willst du dann noch mit dem (wesentlich langsameren) SetPixel()/Getpixel() arbeiten anstatt die 4 Byte direkt in den Speicher zu schreiben bzw zu lesen?
    Weiterhin bin ich nicht sicher, ob du so ein *.PNG benutzen kannst?!Funktioniert das mit einem *.BMP bzw *.JPG?

  • EDIT:
    Code angehängt, wer sich über das LockBits wundert, das war mein erster Versuch, aber mitten im Bild gibt es einen Fehler beim Pixel auslesen... Deswegen versuch ich's jetzt erstmal mit SetPixel


    Oh mann, danke, dass es an soetwas liegt hätte ich nie gedacht, er hat schließlich erfolgreich das Bild geladen
    Danke.. :D (Habs mit *.bmp jetzt)

    EDIT:
    Jetzt noch das LockBits-Problem (das ist geblieben).
    Immer bei x=108 und y=75 hat er in der Funktion GetPxl folgenden Fehler:
    Unbehandelte Ausnahme bei 0x00412dba in Bilderkennung.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0x00aad000.
    Außerdem zeigt er eine Warnung an, die ich nicht deuten kann, für mich bedeutet es nur, dass ich etwas anders verwende:
    Zeile: int flag=ImageLockMode::ImageLockModeUserInputBuf;
    Warnung: "warning C4482: Nicht dem Standard entsprechende Erweiterung: Enumeration "Gdiplus::ImageLockMode" wird im qualifizierten Namen verwendet".

    Bitte um Hilfe und Danke für Hilfe :)

    EDIT:
    Anderes Bild genommen:
    X: 104, Y:78, Fehler: Unbehandelte Ausnahme bei 0x00412dba in Bilderkennung.exe: 0xC0000005: Zugriffsverletzung beim Lesen an Position 0x00aff000.
    Bildgröße: 468x311

  • Hi,
    108x75x4Bpp = 32448 das liegt ziemlich nah an an 32768(2^15). Ggf musst du mehr Speicher freigeben, oder es werden immer nur bestimmte Speicherbereiche ge"lock"t. Da scheint irgendein Buffer zu klein zu sein....
    Hab aber ehrlich gesagt keine Ahnung^^
    Aber wenn du es hinbekommen hast, sag mal Bescheid wg der Geschwindigkeit, ich hatte für das ASM-Tut die AutoItfunktion

    [autoit]

    _ColorConvertRGBtoHSL()

    [/autoit]

    in Assembler geschrieben, sogar anstatt mit (langsamen) Floats in Integer^^

    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

    Einmal editiert, zuletzt von Andy (6. Oktober 2010 um 23:27)

  • Also ich mach es jetzt ersteinmal mit SetPixel, das klappt ja jetzt, RGBtoHSL braucht bei mir keine ganze Millisekunde @2GHz. Kleiner als ms kann ich noch nicht messen, habe aber schon etwas gefunden womit das gehen soll

    EDIT:
    Nächstes Problem bei der Bilderkennung:
    Run-Time Check Failure #2 - Stack around the variable 'colors' was corrupted.
    kommt am Funktionsende von Funktion Kernauswertung(kern,&bmp,w,h);
    (siehe Code, Anhang)
    BYTE colors[3][3];

    Anmerkung zum Code:
    algo ist leider nicht immer <= 255.

    Danke im Vorraus

  • Zitat

    Kleiner als ms kann ich noch nicht messen,

    in C++ solltest du eigentlich auch direkten Zugriff haben auf rdtsc, der gibt die anzahl derTAKTzyklen zurück seit dem letzen Rechnerstart. http://msdn.microsoft.com/en-us/library/twchhe95.aspx
    also pdeudocode:

    Code
    ticks_start=_rdtsc
    C-code
    ticks=_rdtsc-ticksstart   ;anzahl der takte, die deine Funktion verbraten hat


    das sollte als Genauigkeit ausreichen fürs optimieren^^

  • hehe, langsam sollte ich mich vielleicht mal überwinden, auch mal eine Zeile C zu schreiben....wenigstens eine^^

    wg deinem Problem, ich vermute, dass es einen Überlauf gibt (exception) wenn du das Byte (colors) mit einem Wert von wegen mir 178 mit -2 (kern) multiplizierst....das ergibt mehr als 255 und daher ein Überlauf. Ich könnte mir gut vorstellen, dass es ein Compilerflag gibt, um das abzufangen...wenn das überhaupt den Fehler auslöst....
    0xB2 * 0xFFFFFFFE = 0xFFFFFE9C
    178 * -2 = -356 = 0xFFFFFE9C ....= 4294966940 ......shit happens^^
    /Edit/ sry, hab gerade gesehen ALGO ist INT, dann könnte es ja klappen, lass dir mal die algos als liste ausgeben bis der error kommt, im zweifelsfall MOD 255 oder algo direkt als byte dimensionieren

    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

    5 Mal editiert, zuletzt von Andy (8. Oktober 2010 um 20:19)

  • algo ist leider wirklich manchmal höher ^^ (das stört aber nur in der Zeile darunter)
    Das Problem ist nur, dass der Fehler am Ende der Funktion kommt, also nachdem alles fertig ist. Ich schätze eher dass es also eher wieder was mit Array löschen zu Tun hat. GDI+ macht mir ja ohne exit(0); auch am Ende von main() Probleme

  • Das habe ich schonmal, gibt dann InvalidParameter zurück! Es gibt ja nur Write und Read, die Kombination funktioniert nicht.
    EDIT:
    Write alleine klappt auch nicht, nur Read und UserInput

    Einmal editiert, zuletzt von TheShadowAE (12. Oktober 2010 um 15:50)

  • Bei mir sieht das so aus:
    Nach einem RGB2HSV bekomme ich vom linken Teil des Orginalbildes aus deinem Link das hier:
    autoit.de/wcf/attachment/11523/
    Und nach 2x Sobel-Matrix (senkrecht und waagrecht) :
    autoit.de/wcf/attachment/11524/
    Wozu brauchst du die Kantenerkennung?

  • Ich wollte mal ein bisschen gucken wie das ist im Internet mit der Bild- und Texterkennung, da hab ich das Tutorial gefunden und das war ja eigentlich recht leicht, dachte ich mir, die RGBtoHSV Funktion war als Pseudocode schon drin. Naja leider war es dann doch nicht so leicht. In C++ ist irgendwie alles viel schwerer. Ich wollte also mal ein bisschen reinschnuppern, weiter als Kantenerkennung geht das Tut. ja nicht, also viel weiter würde ich dann auch erstmsl nicht kommen. Aber ich dachte immer das wär viiieeell komplizierter soetwas.

    Woher hast du denn deine HSV Funktion genommen? Von Autoit übersetzt? Werde ich jetzt auch einmal versuchen und dann gucke ich mal was mit der Kantenerkennung los ist, ich glaube nämlich ich weiß was da faul ist

    2 Mal editiert, zuletzt von TheShadowAE (17. Oktober 2010 um 11:51)

  • Zitat

    Woher hast du denn deine HSV Funktion genommen? Von Autoit übersetzt?

    Ja, ich hatte für das Assemblertut eine Funktion gesucht, die man "einfach" 1:1 in Assembler übersetzen kann. Eigentlich war ich ziemlich begeistert, da nur relativ einfache Rechnerei umzusetzen war. Allerdings wurde die Umsetzung doch relativ umfangreich, so dass ich mich entschlossen habe, das Beispiel nicht im Tut zu verwenden.
    Übrigens hatte ich den ursprünglich mit Float-Zahlen werkelnden Algorithmus komplett in Integer umgesetzt! Zuerst in AutoIt, dann in Assembler. In AutoIt war natürlich kaum ein Geschwindigkeitszuwachs bemerkbar, in Assembler allerdings war der Schub gewaltig, unoptimiert (war ja fürs Tut geplant) schon Faktor 4! Ich denke, auch C++-Programmierer hätten von diesem Wink mit dem Zaunpfahl profitiert.

    Da auch die anschliessende Matrixmultiplikation extrem gut zu parallelisieren ist, habe ich "multithreating" - AutoIt benutzt. Prog@ndy hatte zu diesem Thema mal einiges gezeigt, aber mit AutoItcode kommt man nicht weiter, da AutoIt nicht threadsicher ist. Das ist der weitere Vorteil von Assembler, man weiss ziemlich genau, was der Prozessor (bzw ASM-code) macht oder auch nicht macht. Daher ist es kein Problem 3-4 Threads mit aufwendigen Berechnungen gleichzeitig zu starten und dann auf Ergebnisse zu warten. Leider bringt Multithreathing nicht sonderlich viel, solange die Threads nur auf einem Core laufen ^^. Allerdings ist es schon beeindruckend, wenn das AutoItscript 4 Threads anstösst und sofort mit dem Programmcode weitermacht. Für hochkomplexe und langwierige Berechnungen lohnt sich das sicher!

    Zitat

    Aber ich dachte immer das wär viiieeell komplizierter soetwas.

    Learning by doing! Bleib am Ball, du lernst jeden Tag etwas dazu!

    /edit/ Integerversion

    Spoiler anzeigen
    [autoit]


    ;hier nun die Variante, die intern nur mit Integerzahlen arbeitet, in AutoIt bringt das kaum Geschwindigkeitsgewinn, in Assembler um so mehr!
    Func int_ColorConvertRGBtoHSL($avArray) ;integerversion
    ;die Variablen werden als Integer übergeben

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

    ;die Variablen werden NICHT durch die Konstante $__COLORCONSTANTS_RGBMAX =255 geteilt
    local $nR = int(Number($avArray[0]))
    local $nG = int(Number($avArray[1]))
    local $nB = int(Number($avArray[2]))

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

    local $nMax = $nB
    If $nMax < $nG Then $nMax = $nG
    If $nMax < $nR Then $nMax = $nR

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

    local $nMin = $nR
    If $nMin > $nG Then $nMin = $nG
    If $nMin > $nB Then $nMin = $nB

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

    local $nMinMaxDiff = ($nMax - $nMin)
    local $nMinMaxSum = ($nMax + $nMin)

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

    ; Lightness
    ;Bis hierhin alles wie gehabt
    ;Wenn man nun ausschliesslich den Rechenweg für die Ermittlung von $nL in der Orginalfunktion anschaut, stellt man fest, dass
    ;$nL = ($nMinMaxDiff / $__COLORCONSTANTS_RGBMAX) / 2 * $__COLORCONSTANTS_HSLMAX
    ;Konstanten einsetzen führt zu $nL = ($nMinMaxDiff / 255) /2 * 240
    ;Zwei DIV-Befehle sind im Assembler sehr "teuer" d.h. kosten sehr viel Zeit, schön wäre es, das DIV durch eine Multiplikation
    ;ersetzen zu können und eine Division durch ein extrem schnelles shiften von Bits zu ersetzen.
    ;Ein BitShift nach rechts ist Division durch 2, wir müssen also die Gleichung nur so erweitern, daß durch eine Potenz von 2 geteilt wird.
    ;$nL = ($nMinMaxDiff / 255) * 120 :erweitern mit 2^16 (hohe Potenz von 2) führt zu
    ; 2^16 * $nL = ($nMinMaxDiff / 255) * 120 * 2^16 :zusammenfassen auf der rechten Seite fuhrt zu 2^16/255*120=30840.47 welches zur nächsten Ganzzahl aufgerundet wird, also 30841 um den Rundungsfehler bei Integer auszugleichen
    ; 2^16 * $nL = $nMinMaxDiff * 30841
    ; $nL = $nMinMaxDiff * 30841 / 2^16
    ;Geteilt durch 2^16 entspricht einem BitShift nach rechts von 16, das führt der Prozessor in EINEM Takt durch, die Division würde ca 40-80 Takte dauern!

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

    local $nL=$nMinMaxSum*30841/65536 ;(shr 16) führt zum gleichen Ergebnis wie /2^16
    ;also kann man schreiben
    ;$nL=BitShift($nMinMaxSum*30841,16) ;diese zeile kann man fast genau so in Assembler übernehmen
    $avArray[2] = $nL ;und abspeichern im Array

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

    ; Grayscale
    $nH = 0
    $nS = 0
    ;Die Formeln etwas ausmultiplizieren führt zu
    If $nMinMaxDiff <> 0 Then
    ; Saturation
    If $nL < 120 Then
    local $nS = int($nMinMaxDiff *240 / $nMinMaxSum)
    Else
    local $nS = int($nMinMaxDiff *240/ (510-$nMinMaxSum))
    EndIf
    $avArray[1] = $nS

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

    ; Hue
    Switch $nMax
    Case $nR
    local $nH = int(($nG - $nB)*40 / $nMinMaxDiff)
    If $nH < 0 Then $nH += 239 ;Rundungsfehler ausgleichen

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

    case $nG
    local $nH = int(($nB - $nR)*40/ $nMinMaxDiff) ;+80
    If $nH < 0 Then
    $nH += 79 ;Rundungsfehler ausgleichen
    else
    $nH += 80
    endif
    case $nB
    local $nH = int(($nR - $nG)*40 / $nMinMaxDiff) ;+160
    If $nH < 0 Then
    $nH += 159 ;Rundungsfehler ausgleichen
    else
    $nH += 160
    endif
    EndSwitch

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

    If $nH > 240 Then $nH -= 240
    EndIf
    $avArray[0] = int($nH)

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

    Return $avArray
    ;die Funktion ist nun vollständig im Integerzahlenraum, man muss keine Fliesskommazahlen verarbeiten!
    ;Darurch können die sehr einfachen Assemblerbefehle benutzt werden!
    EndFunc ;==>_ColorConvertRGBtoHSL

    [/autoit]

    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

    Einmal editiert, zuletzt von Andy (17. Oktober 2010 um 12:21)

  • So danke, aber hier jetzt nochmal die Bilder, wieder anders als deine.
    Oh ich sehe gerade, die Kernauswertung funktioniert noch nicht also nur das HSVbild:
    autoit.de/wcf/attachment/11528/

    EDIT: Achja, der Code natürlich noch:

    Spoiler anzeigen
  • Danke nochmal, und 2 Fragen noch:
    Warum unterscheiden sich meine Bildervon Andys (hautpsächlich an Andy :) )?
    Was kann ich mit soeinem Kantenbild jetzt anstellen? (vielleicht kennt ihr weitere Tutoriale)

    EDIT:
    Einen Fehler der Kernverarbeitung hab ich noch gefunden, also die erste Frage nur, warum sich das HSL/HSV Bild unterscheidet

    EDIT:
    Fehler beseitigt, ist aber immernoch anders

    2 Mal editiert, zuletzt von TheShadowAE (18. Oktober 2010 um 17:42)