Hallo zusammen, ich betreibe ein ILI9341 an einem STM32F446RE. Bei dieser Kombination ist es ja klar, dass ich keinen Framebuffer im RAM halten kann. Ich nutze vorwiegend den 16-Bit RGB565-Farbmodus. Auslesen geht bei diesem Display-Typ nur als 24-Bit-RGB. Ich habe ein Grafikelement (man könnte es mit einem klassischen Sprite vergleichen), bei dem ich den Hintergrund gegenpuffern muss/will, um nicht den kompletten Hintergrund jedes Mal neu aufbauen zu müssen. Also - Display-Bereich in 24 Bit-Farben auslesen, - umrechnen in 16-Bit RGB565 und puffern. - übermalen. Und später - gepufferten Bereich wieder zurückschreiben. Das Problem: Das Display selbst macht die Umrechnung von RGB565 in RGB24 ein bisschen anders als ich die Umrechnung in die Gegenrichtung. Wie genau kann ich nicht dem Datenblatt entnehmen. Das Ergebnis ist, dass der zurückgeschriebene Bereich eine leicht andere Farbe als vorher hat. Nur ist der komplette Hintergrund einer Palette aus 31 Farben entnommen. Fände ich die (indizierte) Farbe, die am dichtesten dran liegt, könnte ich daraus die exakte Farbe, wie sie vorher hineingeschrieben wurde, rekonstruieren. Allerdings fehlt mir die geeignete Metrik, die "nächste" Farbe zu finden. der naive Ansatz wäre, die Farben auf jeweils 24 Bit zu bringen, voneinander komponentenweise abzuziehen und das Ergebnis zu quadrieren. Die Summe der Quadrate sollte in 16 Bit passen, lässt sich also für jede Farbe speichern. Der Farbindex mit der kleinsten Quadratsumme ist die ähnlichste Farbe. Gibt es eine einfachere Metrik, um ähnliche Farben zu finden? Lässt sich evtl. irgendwie eine Fehlerschranke etc. definieren, um bei einer nach Häufigkeit sortierten Palette die Suche schon frühzeitig abbrechen zu können, ohne für jedes Pixel alle Fehler komplett auszurechnen?
Walter T. schrieb: > Fände ich die (indizierte) Farbe, die am dichtesten dran liegt, könnte > ich daraus die exakte Farbe, wie sie vorher hineingeschrieben wurde, > rekonstruieren. Du kannst keine Information wiederherstellen die bei der Umwandlung gelöscht wurde. Man kann ja auch aus einem Betrag in ganzen Euro nicht den Centbetrag wiederherstellen. Georg
Okay, manchmal reicht es, das Problem zu formulieren und dann eine Pause zu machen. Wenn das Display die Umrechnung 16Bit -> 24Bit an jeder Stelle gleich macht, kann ich die Farbpalette durch Schreiben und Zurücklesen komplett konvertieren. Dann brauche ich nur noch auf Gleichheit zu prüfen. Die Frage ist also nur noch, ob die Prämisse stimmt, oder ob da Korrekturfaktoren drin sind, um den gefühlten Kontrast zu erhöhen. Georg schrieb: > Du kannst keine Information wiederherstellen die bei der Umwandlung > gelöscht wurde. Ich will aber in die andere Richtung rekonstruieren (aus einer Liste exakt bekannter Beträge den passenden auswählen, der am besten zum gerundeten Betrag passt).
:
Bearbeitet durch User
Walter T. schrieb: > Das Problem: Das Display selbst macht die Umrechnung von RGB565 in RGB24 > ein bisschen anders als ich die Umrechnung in die Gegenrichtung. Das ist ja sehr unschön. Aber vermutlich nicht so schwierig zu analysieren. Sehr wahrscheinlich wird in eine Richtung abgeschnitten und in die andere Richtung (auf-)gerundet. Irgendsowas. Sollte sich rausfinden (und dann natürlich entsprechend kompensieren) lassen. Ist eigentlich ziemlich simpel: du schnappst dir eine der Grundfarben schreibst alle möglichen Werte dafür in jeweils ein Pixel, liest dann alle diese Pixel wieder aus und vergleichst die Ergebnisse mit dem, was du reingeschrieben hast (binär natürlich). Da sollte man sehr leicht das Schema erkennen können. > Allerdings fehlt mir die geeignete Metrik, die "nächste" Farbe zu > finden. der naive Ansatz wäre, die Farben auf jeweils 24 Bit zu bringen, > voneinander komponentenweise abzuziehen und das Ergebnis zu quadrieren. Ja, das geht. Ist aber ziemlich teuer. Und dabei nichtmal wirklich gut, denn es berücksichtigt die menschliche Wahrnehmung nicht. > Gibt es eine einfachere Metrik, um ähnliche Farben zu finden? Wirklich "einfacher" (im Sinne von: weniger rechenzeitaufwendig) leider nicht, aber immerhin besser auf die menschliche Wahrnehmung angepasst. > Lässt sich > evtl. irgendwie eine Fehlerschranke etc. definieren, um bei einer nach > Häufigkeit sortierten Palette die Suche schon frühzeitig abbrechen zu > können, ohne für jedes Pixel alle Fehler komplett auszurechnen? Man kann die Sache bitweise erledigen. D.h.: zuerst beschäftigt man sich nur mit den höchstwertigen Bits jeder Farbkomponente und steigt dann nach Signifikanz ab. Damit kann man erstens den Suchraum in jeder Iteration ausdünnen und zweitens die möglichen Zielfarben geeignet vorsortieren. Letztlich läuft es auf einen trinären Baum hinaus.
c-hater schrieb: > Das ist ja sehr unschön. Aber vermutlich nicht so schwierig zu > analysieren Das hängt allerdings an der gleichen Prämisse, dass die Zuordnung 16Bit -> 24 Bit eindeutig ist. Im Moment sieht es so aus, als müsse ich diese fallenlassen - ich suche aber noch nach Fehlern in meinem Aufbau. Anscheinend hängt die zurückgelesene Farbe eines Pixels von den Nachbarpixeln ab.
Laut Datenblatt kann der ILI9341 eh nur RGB666. Für die RGB565 nach RGB666 Wandlung gibts ne Lookup-Table (RGBSET-Cmd). Eine Wandlung nach RGB888 beim Lesen macht wohl dein Treiber - der Chip liefert die nicht.
foobar schrieb: > Eine Wandlung nach > RGB888 beim Lesen macht wohl dein Treiber - der Chip liefert die nicht. Ich habe nie behauptet, dass das RGB888 ist. Ich lese nur 24 Bit zurück und es ist linksbündig. Aber vielleicht ist das sogar des Rätsels Lösung, dass die letzten 2 Bit einfach in der Luft hängen und hier der Bus frei herumklingelt. Muß ich gleich mal gucken. foobar schrieb: > Für die RGB565 nach > RGB666 Wandlung gibts ne Lookup-Table (RGBSET-Cmd). Ich habe die Tabelle auch gefunden - aber ich verstehe sie nicht. Sind das irgendwelche Polynome?
Walter T. schrieb: > Anscheinend hängt die zurückgelesene Farbe eines Pixels von den > Nachbarpixeln ab. Das ist ja ganz fies. Aber durchaus denkbar, bedeuted sogar, dass sich die Display-Entwickler richtig Gedanken gemacht haben. Da steckt dann nämlich sehr wahrscheinlich ein Dither-Algorithmus dahinter. Tja, dann bist du tatsächlich bei deinem Ansatz aus dem OT als bestmöglicher Lösung (mit den möglichen Optimierungen) Die einzige Alternative ist: Zu jedem gezeichneten Blob musst du den Background, den es überdeckt, im Original verwalten. Das kostet natürlich Speicher, aber immerhin sehr viel weniger Speicher als ein vollständiger Framebuffer...
ielleicht habe ich auch einfach einen dummen Implementierungsfehler (Kapitel 7.6.1) drin. Ich gucke gerade.
> Ich lese nur 24 Bit zurück und es ist linksbündig. Bei den seriellen Modi sind da die unteren 2 Bits jeder Farbkomponente "don't care". > Ich habe die Tabelle auch gefunden - aber ich verstehe sie nicht. Ist einfach eine Tabelle für jede Grundfarbe 5/6 Bit -> 6 Bit. red[0..31] --> 0..63 green[0..63] --> 0..63 blue[0..31] --> 0..63 > Nur ist der komplette Hintergrund einer Palette aus 31 Farben Wenn du deine eigene Palette und die des Chips abstimmst, könntest du (mit ein paar Einschränkungen bei der Farbauswahl) die evtl so aufbauen, dass z.B. die unteren 5 Bit des ausgelesenen Blaus gerade dein Paletten-Index ist.
Das Problem dürfte die Gamma-Kurve sein (die bei der Initialisierung festgelegt wird) Beim Schreiben wird die berücksichtigt - beim lesen nicht.
Walter T. schrieb: > Ich > nutze vorwiegend den 16-Bit RGB565-Farbmodus. Auslesen geht bei diesem > Display-Typ nur als 24-Bit-RGB. Hmm... nun meine ich, daß so ein Grafikchip an der eigentlichen Farbe nicht herumändert, sondern lediglich aus den gelieferten 15 Bit Farbwerten eine Belegung in 24 Bit macht, indem die niedrigsten Bit entweder mit 0 aufgefüllt werden oder die höchsten Bits dorthin kopiert werden, um beim hellsten Farbwert auch auf die maximale Displayhelligkeit zu kommen. Aber das ist alles immer gleich, also wenn du zuvor dein Icon oder deinen Hintergrund in 565 dort hineingeschrieben hast, dann wird das auch nach Auslesen und Zurückschreiben genau so wieder passieren. Mein Verdacht ist, daß du in deinem Treiber einen Denkfehler hast. Bevor du nun dich ergehst in Ähnlichkeitsberechnungen, schau dir deinen Code für das Rücklesen und Reduzieren von 24 auf 16 Bit nochmal genau an. W.S.
W.S. schrieb: > Mein Verdacht ist, daß du in deinem Treiber einen Denkfehler hast. Das hat er hier: Beitrag "Re: Farbähnlichkeit - Abstand im Farbraum" Bereits als Möglichkeit eingeräumt. Ansonsten wurde alles, was du gesagt hast, bereits zuvor als Möglichkeit aufgezeigt. Nunja, es wurde bereits alles gesagt, bloß noch nicht von jedem...
Okay. Das ist peinlich. Das Problem war eine kalte Lötstelle. Die Fehlersuche war ein Krimi - aber ein sehr langweiliger. Die Farbabweichungen stellten sich als zu hoher SPI-Takt heraus - wiederum bedingt durch eine kalte Lötstelle in der MISO-Leitung, so dass das Display die Leitungskapazität nicht mehr treiben konnte. Damit wurde - leider sehr reproduzierbar - die High-Bits immer etwas verschmiert, dass etwas mehr 1en empfangen als gesendet wurden. Das wiederum äußerte sich darin, dass die kräftigen Farben absolut korrekt aussahen, die anderen Farben aber tendenziell etwas zu hell. Darauf gekommen bin ich, weil beim Gegentesten mit einem TFT-Modul mit 8080-Interface die Farbe immer bis auf winzigste Abweichungen stimmte, während die Abweichungen mit dem SPI-Modul deutlich größer waren. Die winzigen Abweichungen letztendlich ließen sich beseitigen, indem bei Rot und Blau jetzt immer aufgerundet wird, wenn das LSB gesetzt ist, anstelle abgeschnitten. Mit dem SPI-Takt bin ich jetzt auch etwas heruntergegangen. Das Fehlerbild war zwar harmlos, aber man braucht ja nicht alles auf Kante genäht. Was es mit der RGBset-Tabelle auf sich hat, interessiert mich aber immer noch.
:
Bearbeitet durch User
Walter T. schrieb: > Was es mit der RGBset-Tabelle auf sich hat, interessiert mich aber immer > noch. Du treibst das Display mit 16-bit RGB 5-6-5, darstellen kann es aber nur 18-bit RGB 6-6-6. Die Lookup-Tabelle bestimmt, wie die 16-Bit "Input"-Farben auf die 18-Bit "Display"-Farben umgesetzt werden. Da scheint mir nichts Geheimnisvolles dran.
:
Bearbeitet durch User
Markus F. schrieb: > Da scheint mir nichts Geheimnisvolles dran. Wie werden sie denn umgesetzt? Ich sehe nur Indizes.
Walter T. schrieb: > Markus F. schrieb: >> Da scheint mir nichts Geheimnisvolles dran. > > Wie werden sie denn umgesetzt? Ich sehe nur Indizes. Die Lookup-Tabelle beschreibst Du mit dem "Color Set 2Dh"-Kommando. Danach wird jeder eingehende 5-6-5 R, G, B-Wert durch den Wert in der Tabelle ersetzt, bevor er ins Display-Memory geschrieben wird.
Ich sehe in der Tabelle keinen Wert. Ich sehe nur Indizes. R005, R004, R003, R002, R001. Was sind das für Werte? Und was haben die mit 00000 zu tun?
00000 sind die fünf R-Bits des 5-6-5 RGB-Wertes, den Du reinsteckst. Ans Display gehen dann die 6 Bits (R005 bis R000), die Du in die Tabelle als Ersetzungswert geschrieben hast. Kommst Du (z.B.) mit einem R-Wert von 21 (Binär 10101) ums Eck, wird stattdessen der 6-Bit Ersatzwert des Tabelleneintrags 22 (R215...R210) ins Display geschrieben.
P.S.: Die Problematik der Vorgehensweise ist nachvollziehbar, die des Aufbaus ist es nicht. Vielleicht doktort der TO ja am falschen Ende rum, weil ihn am anderen Ende ein Wackelkontakt zum Narren hält. Das ist Alles nicht greifbar und erzählen kann man viel.
Als Grundschüler dachte ich immer, schreiben sei schwieriger als lesen. Heute weiß ich, dass es andersherum ist.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.