24Bit RGB zu 16Bit wandeln

Gast #1696579
Lesenswert?

Hallo Leute,

ich möchte eine 24Bit RGB Wert in 16bit für ein TFT wandeln. Natürlich 
funktioniert das schon mit der einfachen Variante die unteren Bits 
einfach zu streichen, dies entspricht meiner Meinung nach nicht der 
ganzen Warheit.

Als Beispiel

R G B Wert =   11111111 00000011 00000111

dies wäre ja umgewandelt einfach nur rot. Wenn ich nun eine 24Bit Bitmap 
(Foto) so ausgebe, sieht man das natürlich schon an gewissen stellen im 
Bild.

Hat jemand von euch eine bessere Idee die Umwandlung besser 
durchzuführen?

Gruß

Th.
Persönliche Seite #1696595
Lesenswert?

Mal angenommen die Darstellung ist 5:6:5 für RGB und du willst den 
Grünwert; den könntest runden, zB:
1
G6 = G8 + 2            // aufrunden: + 2**1
2
if (G6 > 255) G6 = 255 // evtl. Überlauf abschneiden
3
G6 = G6 >> 2           // grün hat 6 bits (8-2)

irgendwo gibt's aber immer Informationsverlust, der vor allem bei 
blassen Farben und an der Grauachse auffallen wird.
Persönliche Seite #1696602
Lesenswert?

Thorsten schrieb:
> Natürlich
> funktioniert das schon mit der einfachen Variante die unteren Bits
> einfach zu streichen, dies entspricht meiner Meinung nach nicht der
> ganzen Warheit.

> Als Beispiel
> R G B Wert =   11111111 00000011 00000111
> dies wäre ja umgewandelt einfach nur rot

nah, nicht den ganzen 24bit RGB nehmen und "beschneiden" sondern die 
jeweiligen farbwerte von 8 auf 5 bzw 6 bit aufrunden.
#1696623
Lesenswert?

Thorsten schrieb:

> dies wäre ja umgewandelt einfach nur rot. Wenn ich nun eine 24Bit Bitmap
> (Foto) so ausgebe, sieht man das natürlich schon an gewissen stellen im
> Bild.

Stimmt. Da wirst Du auch mit keiner Technik der Welt gegen ankommen. Die 
Anzahl der Farben ist nun mal begrenzt. Und wenn Du einen Gradienten im 
Bild hast, dann sind Stufen dort drin.
Du könntest es dithern ...


Falk Brunner schrieb:
> aufrunden

Geht nicht.

Aus 11111111 würde dann z.B. 00000 werden (führende 1 abgeschnitten).
Eine Skalierung fällt auch aus, da dann die Farben verfälscht werden.
Ohne Rundung ist das Bild dann im Schnitt eben einfach ein halbes LSB 
dunkler. Auch volle Helligkeit ist fast ein ganzes LSB 'dunkler'
Den Unterschied zwischen

11111000 11111100 11111000
und
11111111 11111111 11111111

wirst Du einfach nicht darstellen können ...
(hier müsstest Du ja dann auch abrunden ...)

Ich denke, einfach die Bits abzuschneiden ist schon die richtige Lösung.
Gewisse Farben kann das Display einfach nicht darstellen, damit wirst Du 
leben müssen.


Gruß

Jobst
Gast #1696631
Lesenswert?

Hi,

das es nicht ohne Verluste geht ist klar. Wie aber machen es denn die 
"Profis"? Wenn ich beispielsweise dieses Foto nehm:

http://www.architekten24.de/mediadb/news/2012/dockland_2.jpg

und wandel es mit Gimp in eine 16Bit RGB Bitmap um, sieht es am PC noch 
super aus.

Wie würde das denn mit dem Runden aussehen? Momentan sieht meine 
Funktion so aus:

uint16 convert_to_16bit(uint8 red, uint8 green, uint8 blue)
{
return ((red>>3)<<11)+((green>>2)<<5)+(blue>>3);
}

Gruß

Th.
#1696665
Lesenswert?

Thorsten schrieb:
> R G B Wert =   11111111 00000011 00000111
>
> dies wäre ja umgewandelt einfach nur rot. Wenn ich nun eine 24Bit Bitmap
> (Foto) so ausgebe, sieht man das natürlich schon an gewissen stellen im
> Bild.

(Auf)Runden.
Rot und Blau bekommen 5, Grün 6 Bit.
Mein Vorschlag: Das 3. Bit des alten 8-Bit-wertes wird das LSB des neuen 
Wertes.
Alt         Neu
0000 0100 = 00001
0000 0011 = 00000
0000 0111 = 00001
Denn: Die letzten 3 Bits des 8-Bit-Farbwertes können 7 Werte darstellen, 
will man das auf 5 Bit eindampfen kann man nur noch auf einen Wert 
diskriminieren.
Das 3-letzte Bit ist mehr wert als die verbleiben zwei zusammen, die 
muss man also garnicht erst ansehen um zu wissen ob auf oder abgerundet 
wird.
Analog das ganze beim Grünwert, nur ein Bit verschoben.
Einfach das spezielle Bit als neues LSB des eingedampfen Farbwertes 
übernehmen, so kriegt man das ohne viel Rechenzeit umgerechnet.
#1696690
Lesenswert?

A. K. schrieb:
> Jobst M. schrieb:
>
>> Dann macht das doch mal mit diesen Werten:
>
> Dass man beim Bitwegkürzen Information verliert kommt dir sicherlich
> völlig unerwartet.

Nein, das genaue Gegenteil versuche ich die ganze Zeit klar zu machen.

Mal eine anderer Ansatz: Stellt Euch vor, das Ganze müsste auf 1 Bit pro 
Farbe gekürzt werden. Wie würdet Ihr runden? Oder doch einfach nur alle 
Werte ab 128 auf 1 setzen und darunter auf 0?


Falk: Wo kommen die Punkte in 'dockland_16_bit_rounding.png' her?


Gruß

Jobst
#1696698
Lesenswert?

Jobst M. schrieb:

> Nein, das genaue Gegenteil versuche ich die ganze Zeit klar zu machen.

Der Treppeneffekt ist völlig unabhängig davon ob man rundet oder 
abschneidet. Die Nähe zum Original ist es jedoch nicht. Bei Rundung 
beträgt der Fehler maximal 0,5 LSB, beim Abschneiden 1 LSB.

Ist die Nähe zum Original nicht massgeblich, beispielsweise weil das 
Ausgabemedium sowieso nicht farbkalibriert ist, dann hat Rundung nur 
noch den Vorteil, Artefakte an den Grenzwerten automatisch zu vermeiden. 
Das geht aber auch einfacher.
#1696711
Lesenswert?

A. K. schrieb:
> Jobst M. schrieb:
>
>> Nein, das genaue Gegenteil versuche ich die ganze Zeit klar zu machen.
>
> Der Treppeneffekt ist völlig unabhängig davon ob man rundet oder
> abschneidet. Die Nähe zum Original ist es jedoch nicht. Bei Rundung
> beträgt der Fehler maximal 0,5 LSB, beim Abschneiden 1 LSB.

Korrekt - ist also ein Helligkeitsunterschied von 0,5 LSB
Problem der Rundung ist aber, daß die hellste Stufe 1,5LSB überstreicht.

Farbbluten wird man sowieso nicht vermeiden können.


Gruß

Jobst

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren