Palette eines Bildes gegen eine andere Tauschen

  • VB6

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von Mad Andy.

    Palette eines Bildes gegen eine andere Tauschen

    Hallo Leute,

    ich hab im Internet und auch bei euch im Forum gesucht, bin aber leider noch net fündig geworden.
    Folgendes hab ich vor, mittels BitBlt hab ich einen einen bestimmten Ausschnit aus einer PictureBox ausgeschnitten und bearbeitet und dann wieder in eine andere Picturebox eingefügt. Jetzt würde ich gerne noch die Palette des Ausschnitts mit einer andern Palette tauschen, ich meine sowas im zusammenhang mit der BitBlt Funktion gelesen zu haben, aber ich haben bis jetzt noch nicht herausgefunden wie das geht. Könnte mir da bitte jemand weiter helfen ?
    Ne, es geht um das Bild in der Picturebox. Angenommen in der Picturebox ist ein roter Kreis in einem weisen Kasten und ich möchte, dass die Farbe Rot ausgetauscht wird und das soll nachher direkt mit mehreren Farben geschehen
    Hi!

    Ich kenne den Palettentausch nur im Zusammenhang mit indizierten Farben und Hardwarebeschleunigung. Ich will nicht von vorne herein ausschließen, dass es möglich ist, jedoch legt selbst wenn du nur 256 indizierte Farben am Monitor hättest Windows für die Grafikkarte die Farbpalette bei normalen Programmen fest (sonst könnte man ja schnell mehr als 256 Farben zusammenbekommen).

    Der einzige Weg, den ich kenne wäre GetPixel und SetPixel, was ziemlich lahm ist :(
    Grundsätzlich musst du mal wissen:
    Alles grafische in Windows läuft über DCs = Device Contexts (von denen du in VB oft nix mitbekommst). Der Inhalt von Pictureboxes, Formen, etc. werden auf diese DCs gezeichnet. Diese DCs sind eben an Windows bzw. dessen Einstellungen gebunden (Farbtiefe, Farbtabelle), solange du nicht mit 2D- oder 3D-Beschleunigung "rein renderst".

    Es gibt 2 Wege sich über diese Einstellungen hinwegzusetzen:
    1. Mit 2D- oder 3D-Beschleunigung 256Farben-Surfaces (Bilder im Videospeicher) erstellen und die Farbtabelle von denen ändern. Hier rendert die Grafikkarte mit der gewünschten Tabelle auf's DC.
    2. Du manipulierst die Grafikeinstellungen, sodass Windows im 256Farben-Modus läuft und manipulierst dann die Farbtabelle der Grafikkarte, womit ALLE FARBEN, SYSTEMWEIT anderst sind, falls das noch möglich ist.

    Das, was du ändern willst (solange du dich nicht auf das da oben berufst), sind also vermutlich keine Farbtabellen (die gibts ab 16bit ohne Beschleunigung imho nichtmehr), sondern die Farbwerte von Pixeln mit der Farbe X. Der einzige Weg, den ich kenne geht indem du jedes Pixel deines Tiles einzeln änderst (siehe Google: GetPixel- und SetPixel-Aufruf). Wenn dir das zu langsam ist, kannst du bei Tiles auch nur ein Tile umzeichnen und das öfters mit BitBlt (siehe wieder Google) auf der Form oder in einer weiteren Picturebox darstellen.


    Für Methode 1 weiß ich nicht, wie / ob das mit DirectX / OpenGL geht. Das hab ich aus nem Funktionsüberblick für SDL (2D-Beschleunigung).


    PS: Ich bin nicht felsenfest davon überzeugt, dass alle Aussagen da oben zu 100% Stimmen, jedoch ist das so das, was ich im Laufe der Zeit mitbekommen hab. Es ist aber auch durchaus Möglich, dass es eine schnellere Methode gibt um eine Farbe durch eine andere zu ersetzen!
    Vielen Danke für die ausführliche Erklärung, hat mir einiges an Erkenntnis gebracht. In naher Zukunft werd ich mich damit in Ruhe auseinandersetzen. Habe mitlerweile eine Lösung für mein Problem über einen anderen Weg gefunden.

    Greetz Aeonos
    Ich bins nochmal wegen dem gleichen Problem ^^, aber ich habe einen Lösungsansatz, komm aber leider nicht weiter.
    Meine Idee ist die Palette über GetDIBits auszulesen und mit SetDIBits nacher wieder verändert einzufügen.
    Der Code den ich mir gesammelt habe ist

    Visual Basic-Quellcode

    1. Public Type BITMAPINFOHEADER
    2. biSize As Long
    3. biWidth As Long
    4. biHeight As Long
    5. biPlanes As Integer
    6. biBitCount As Integer
    7. biCompression As Long
    8. biSizeImage As Long
    9. biXPelsPerMeter As Long
    10. biYPelsPerMeter As Long
    11. biClrUsed As Long
    12. biClrImportant As Long
    13. End Type
    14. Public Type BITMAPINFO
    15. bmiHeader As BITMAPINFOHEADER
    16. bmiColors As Long
    17. End Type
    18. Public Type BITMAPINFOPAL
    19. bmiHeader As BITMAPINFOHEADER
    20. bmiColors(255) As Integer
    21. End Type
    22. Public Declare Function GetDIBits Lib "gdi32" ( _
    23. ByVal aHDC As Long, ByVal hBitmap As Long, _
    24. ByVal nStartScan As Long, ByVal nNumScans As Long, _
    25. lpBits As Any, lpBI As BITMAPINFOPAL, ByVal wUsage As Long) _
    26. As Long
    27. Public Declare Function SetDIBits Lib "gdi32" ( _
    28. ByVal hDC As Long, ByVal hBitmap As Long, _
    29. ByVal nStartScan As Long, ByVal nNumScans As Long, _
    30. lpBits As Any, lpBI As BITMAPINFO, ByVal wUsage As Long) _
    31. As Long


    Ich kriegs jetzt aber nicht hin damit eine Farbe auszulesen zu ändern und wieder einzufügen, kann mir bitte
    einer zeigen wie das funktioniert.

    Vielen Dank schon mal im Vorraus ^^
    Hallo Aeonos,
    wenn die Bitmap so klein ist, kannst du eine Farbe einfach
    mit zwei Schleifen tauschen. Wenn's schnell gehen soll,
    die Bitmap mit TransparentBlt in eine Picturebox kopieren,
    wobei die Hintergrundfarbe die neue Farbe ist und als
    Transparenzfarbe die alte Farbe übergeben wird. Die von
    dir angesprochene Palette gibt es nur bei Bitmaps mit 256
    und weniger Farben. VB erzeugt Bitmaps immer in der
    eingestellten Farbauflösung, d.h. heute meist Truecolor-
    Bitmaps mit 16,7 Millionen Farben. Bitmaps mit geringerer
    Farbauflösung müssen über Apis explizit erzeugt werden.


    Gruss,

    Neptun
    Gruss,

    Neptun
    Hallo Neptun,
    das ist ein super Vorschlag, aber ich glaube, dass das nicht viel schneller gehen wird, da alle 16 Farben immer
    ausgetauscht werden und bei 1048576 Tiles, wenn ich da jede Farbe einzeln mit der Methode ansteuer wirds
    denk ich trotzdem nichts nutzen, deswegen such ich nach einer Methode alle Farben auf einmal zu tauschen
    und dachtet das wäre mit GetDIBits möglich. Weist du vllt wie ich das realisieren könnte ?
    Hi!

    1. funktioniert dein Code nur für Indizierte (256 Farben) Bitmaps. Musst also beim speichern aufpassen. Ich gehe mal davon aus, dass dir die 256 Farben reichen.
    2. Musst du die Bitmap per API laden, damit du ein Bitmap-Handle (hBitmap) bekommst.
    siehe CreateBitmapIndirect oder CreateBitmap
    3. Um die Bitmap in ein DC zu bekommen brauchst du SelectObject.
    Das DC erstellst du am besten vorm Blten und löscht es danach wieder. (hMemDC = CreateCompatibleDC(Picture1.hdc))
    4. Anschließend musst du in die Pictureboxen oder auf die Form Blten.
    5. Zum Schluss alle Ressourcen (eigene Bitmaps, DCs) per DeleteObject freigeben.