GDI: Nur Pixel einer Farbe wiedergeben

  • Hallo zusammen,

    was gdi betrifft bin ich noch blutiger Anfänger und könnte etwas starthilfe gebrauchen. Ich möchte gern ein gespeichertes Bild mittels gdi widergeben. Es soll jedoch nicht das ganze Bild sondern nur Pixel einer bestimmten Farbe wiedergegeben werden.
    Ein Beispiel:

    Ein Bild enthält einen schwarzen Text. Nun soll das Bild geladen werden und lediglich der schwarze Text soll mittels gdi gezeichnet werden (Rest des Bildes enthält kein schwarz).

    Laden eines Bildes, einen Bereich Clonen und das ganze Bild darstellen ist kein Problem nur bei der Darstellung von Pixeln einer bestimmten Farbe komm ich nicht weiter. Gibt es da eine einfache und vorallem schnelle Methode? Alternativ würde mir auch eine art Pixelchecksum von Pixeln einer Farbe weiterhelfen. Pixelgetcolor ist mir diesbezüglich aber einfach zu langsam!

    Besten Dank :)

  • Probiere es mal damit:

    Spoiler anzeigen
    [autoit]


    #include <GDIPlus.au3>

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

    _GDIPlus_Startup()
    Global Const $IMAGE_BITMAP = 0
    Global Const $STM_SETIMAGE = 0x0172

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

    Global $hImage = _GDIPlus_ImageLoadFromFile(StringReplace(@AutoItExe, "autoit3.exe", "Examples\GUI\logo4.gif"))
    Global Const $iW = _GDIPlus_ImageGetWidth($hImage)
    Global Const $iH = _GDIPlus_ImageGetHeight($hImage)

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

    Global Const $hBmpCtxt = _GDIPlus_ImageGetGraphicsContext($hImage)

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

    _GDIPlus_GraphicsDrawString($hBmpCtxt, "TEST", 10, $iH / 6, "Arial", $iH / 2)
    Global $hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)

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

    Global Const $hGUI = GUICreate("Vorher", $iW, $iH)
    Global Const $idPic = GUICtrlCreatePic("", 0, 0, $iW, $iH)
    _WinAPI_DeleteObject(GUICtrlSendMsg($idPic, $STM_SETIMAGE, $IMAGE_BITMAP, $hHBitmap))
    GUISetState()

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

    Do
    Until GUIGetMsg() = -3

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

    _GDIPlus_BitmapMask($hImage, "0xFF000000")

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

    _WinAPI_DeleteObject($hHBitmap)

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

    $hHBitmap = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hImage)
    _WinAPI_DeleteObject(GUICtrlSendMsg($idPic, $STM_SETIMAGE, $IMAGE_BITMAP, $hHBitmap))
    WinSetTitle($hGUI, "", "Nachher")

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

    Do
    Until GUIGetMsg() = -3

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

    _WinAPI_DeleteObject($hHBitmap)
    _GDIPlus_ImageDispose($hImage)
    _GDIPlus_GraphicsDispose($hBmpCtxt)
    GUIDelete()
    Exit

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

    Func _GDIPlus_BitmapMask(ByRef $hBitmap, $sColor, $iMaskColor = 0xFFFFFFFF)
    Local $iX, $iY, $aResult
    For $iY = 0 To $iH
    For $iX = 0 To $iW
    $aResult = DllCall($ghGDIPDll, "uint", "GdipBitmapGetPixel", "handle", $hBitmap, "int", $iX, "int", $iY, "uint*", 0)
    If $aResult[4] <> $sColor Then DllCall($ghGDIPDll, "uint", "GdipBitmapSetPixel", "handle", $hBitmap, "int", $iX, "int", $iY, "uint", $iMaskColor)
    Next
    Next
    EndFunc

    [/autoit]

    Ist nicht die schnellste Lösung... Eigentlich was für ASM :D

    Gruß,
    UEZ

    Auch am Arsch geht ein Weg vorbei...

    ¯\_(ツ)_/¯

    Einmal editiert, zuletzt von UEZ (24. Oktober 2012 um 14:50)

  • Huhu,

    Zitat

    Ist nicht die schnellste Lösung... Eigentlich was für ASM

    Schlawiner^^

    Geht aber auch einfacher...
    BitBlt() mit Maske der gesuchten Pixelfarbe und Parameter $SRCAND

  • Super vielen dank für die Antworten, ich konnte es aus Zeitgründen noch nicht testen. _WinAPI_BitBlt() hab ich mir durchgelesen und irgendwie versteh ich es nicht ganz. Sorry das ich da nochmal nachfrage aber statt was baue ich das dann ein? Wie gesagt blutiger gdi Anfänger auf dieser Seite :rolleyes: .

  • Hi,

    Zitat

    _WinAPI_BitBlt() hab ich mir durchgelesen und irgendwie versteh ich es nicht ganz.

    _WinAPI_BitBlt() verschiebt einen Speicherbereich in einen anderen, mit den Parametern wie z.B. $SRCAND werden Quelle (Source) und Ziel (Destination) - Inhalte des Speichers miteinander verknüpft.
    "Normalerweise" verwendet man BitBlt() als schnelle und einfache Möglichkeit, Grafiken oder Bilder (oder Teile davon) darzustellen.
    Dabei arbeitet BitBlt() mit (Anzeige-)Geräten, sog. Devices. Das können Bildschirme, Drucker usw. sein. Benötigt wird ein DeviceContext, also im Groben eine Beschreibung des Gerätes.
    Diesen Context erhält man in AutoIt entweder über

    [autoit]

    $hDC = _GDIPlus_GraphicsGetDC($hGraphic) ;DC holen aus dem GDI-Grafikobjekt
    ;oder
    $hDC = _WinAPI_GetDC($hGui) ;DC holen aus dem Fensterhandle

    [/autoit]

    Einfaches Beispiel:
    Es werden 3 Fenster erstellt. In die ersten beiden Fenster wird jeweils ein Teil des aktuellen Desktops "geblittet". Als Parameter dient SRCCOPY, es wird also kopiert.
    Im dritten Fenster wird nun die Verknüpfung von Source (Fenster1) und Destination(Fenster2) anhand der verschiedenen Parameter gezeigt.

    Spoiler anzeigen
    [autoit]

    #include <WinAPI.au3>
    #include <WindowsConstants.au3>

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

    ;Parameter fürs blitten
    Dim $iRop[20]
    $iRop[0] = $BLACKNESS ;- Füllt das Ziel-Rechteck mit der Farbe, die mit dem Paletten-Index 0 verknüpft ist
    $iRop[1] = $CAPTUREBLT ;- Inkludiert jegliche Fenster, die das eigene Fenster überlagern in das resultierende Bild
    $iRop[2] = $DSTINVERT ;- Invertiert die Farben des Ziel-Rechtecks (umkehren)
    $iRop[3] = $MERGECOPY ;- Mischt die Farben des Quell-Rechtecks mit dem in hDest aktuell gewähltem Füllmuster (Brush), unterVerwendung des AND Operators.
    $iRop[4] = $MERGEPAINT ;- Mischt die invertierten Farben des Quell-Rechtecks mit den Farben des Ziel-Rechtecks unter Verwendung des OR Operators.
    $iRop[5] = $NOMIRRORBITMAP ;- Verhindert das spiegeln der Bitmap
    $iRop[6] = $NOTSRCCOPY ;- Kopiert das invertierte Quell-Rechteck ins Ziel-Rechteck
    $iRop[7] = $NOTSRCERASE ;- Kombiniert die Farben des Quell- und Ziel-Rechtecks unter Verwendung des OR Operators undinvertiert dann die daraus resultierenden Farben.
    $iRop[8] = $PATCOPY ;- Kopiert das in hdcDest gewählte Füllmuster in die Ziel-Bitmap
    $iRop[9] = $PATINVERT ;- Kombiniert die Farben des Quell-Rechtecks mit dem in hDest aktuell gewähltem Füllmuster, mit den Farben desZiel-Rechtecks unter Verwendung des XOR Operators.
    $iRop[10] = $PATPAINT ;- Kombiniert die Farben des in hDest aktuell gewähltem Füllmusters, mit den Farben des invertiertem Quell-Rechtecks unter Verwendung des OR Operators. Das Resultat dieser Operation wird wiederum mit den Farbendes Ziel-Rechtecks kombiniert, unter Verwendung des OR Operators.
    $iRop[11] = $SRCAND ;- Kombiniert die Farben des Quell- und Ziel-Rechtecks unter Verwendung des AND Operators
    $iRop[12] = $SRCCOPY ;- Kopiert das Quell-Rechteck direkt ins Ziel-Rechteck
    $iRop[13] = $SRCERASE ;- Kombiniert die invertierten Farben des Ziel-Rechtecks mit den Farben des Quell-Rechtecks unter Verwendung des AND Operators.
    $iRop[14] = $SRCINVERT ;- Kombiniert die Farben des Quell- und Ziel-Rechtecks unter Verwendung des XOR Operators
    $iRop[15] = $SRCPAINT ;- Kombiniert die Farben des Quell- und Ziel-Rechtecks unter Verwendung des OR Operators
    $iRop[16] = $WHITENESS ;- Füllt das Ziel-Rechteck mit der Farbe, die mit dem Index 1 in der PhysikalischenPalette verknüpft ist.

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

    ;3 Fenster erstellen und anzeigen
    $hGUI_source = GUICreate("SOURCE", 300, 300, 400, 400)
    GUISetState()
    $hGUI_dest = GUICreate("DESTINATION", 300, 300, 710, 400)
    GUISetState()
    $hGUI_bitblt = GUICreate("BitBlt() Para: ", 300, 300, 1020, 400)
    GUISetState()

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

    ;DC der Fenster und des Desktops holen
    $hDC_source = _WinAPI_GetDC($hGUI_source)
    $hDC_dest = _WinAPI_GetDC($hGUI_dest)
    $hDC_bitblt = _WinAPI_GetDC($hGUI_bitblt)
    $hDC_screen = _WinAPI_GetDC(0) ;desktop

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

    ;Teile des Desktops in die Fenster blitten
    _WinAPI_BitBlt($hDC_source, 0, 0, 300, 300, $hDC_screen, 0, 0, $SRCCOPY) ;obere linke Ecke vom Desktop nach SOURCE
    _WinAPI_BitBlt($hDC_dest, 0, 0, 300, 300, $hDC_screen, 0, @DesktopHeight - 300, $SRCCOPY) ;untere linke Ecke vom Desktop nach DESTINATION

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

    For $i = 0 To 16 ;alle Parameter anwenden
    _WinAPI_BitBlt($hDC_bitblt, 0, 0, 300, 300, $hDC_dest, 0, 0, $SRCCOPY) ;Destination ins BitBlt-Fenster kopieren
    _WinAPI_BitBlt($hDC_bitblt, 0, 0, 300, 300, $hDC_source, 0, 0, $iRop[$i]);BitBlt-Fenster verknüpfen mit Source
    WinSetTitle($hGUI_bitblt, "", "BitBlt() Para: $iRop[" & $i & "]");Arrayindex Verknüpfung anzeigen
    Sleep(2000) ;warten....^^
    Next

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

    Do ;solange, bis eines der Fenster geschlossen wird
    Until GUIGetMsg() = -3

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

    ;aufräumen
    _WinAPI_ReleaseDC($hGUI_bitblt, $hDC_bitblt)
    _WinAPI_ReleaseDC($hGUI_source, $hDC_source)
    _WinAPI_ReleaseDC($hGUI_dest, $hDC_dest)
    _WinAPI_DeleteDC($hDC_bitblt)
    _WinAPI_DeleteDC($hDC_source)
    _WinAPI_DeleteDC($hDC_dest)

    [/autoit]


    Möchte man nur alle Pixel einer bestimmten Farbe darstellen, dann verknüpft man das Ursprungsbild mit einem Bild mit ausschliesslich dieser Farbe und Verknüpft es per SRCAND. Dann werden nur "gleiche Farben" dargestellt, also die gesuchten Pixel.
    Als Anwendung könnte man z.B.einen Farbfilter (vgl. Farbsehtest) erstellen, oder ein "Wasserzeichen" in einem Bild sichtbar machen oder Geheimschrift in einem Bilkd sichtbar machen oder oder oder^^

    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 (25. Oktober 2012 um 21:02)