Mindestenssechszeichen...keine Panik!

Halbrunde Farben

16. Juli 2019 von Yhoko
Farben sind für Programmierer immer irgendwie problematisch, denn es sind an sich keine Zahlen. Computer können aber nur mit Zahlen, also muss man die Farben irgendwie umwandeln. Das wohl berühmteste Farbmodell "RGB" dürfte dabei jedem ein Begriff sein, der schon irgendwie mit Farben am Computer zu tun hatte. Das Prinzip ist simpel; man stellt jeden der drei Farbaspekte (Rot, Grün, Blau) mit einem Byte (von 0 bis 255) dar und aus der Kombination ergeben sich alle möglichen Bildschirmfarben. Himmelblau ist beispielsweise als "R34 G113 B179" definiert (gemäss RAL Palette).

Nun ist es recht mühsam und platzverbrauchend, Farben immer auf diese Weise anzugeben. Man könnte die Buchstaben weglassen, da die Reihenfolge klar ist, aber "34 113 179" ist immer noch recht umständlich einzugeben. Viel praktischer ist es, wenn man für jeden Farbaspekt immer 1 oder 2 Buchstaben eintragen kann – und hier leistet das Hexadezimalsystem (kurz: Hex) einmal mehr gute Dienste. Statt von 0 bis 255 stellt man damit die Farbwerte von 00 bis FF dar und siehe da, nun sind alle Zahlen "gleich breit". Aus dem Himmelblau wird nun "#2271B3" und das ist wirklich vergleichsweise kompakt (die # stellt man davor, damit klar ist, dass es sich um eine Hex-Zahl handelt). Jeder, der schon mit HTML/CSS gearbeitet hat, dürfte diese Schreibweise gut kennen. Ich persönlich bevorzuge sogar meistens die Abkürzungsmethode mit 3 Ziffern: "#27A" (der Browser verdoppelt dabei alle Ziffern, das Beispiel entspricht also "#2277AA" und ist immerhin nah dran am Himmelblau).

Ein drittes, ebenfalls weit verbreitetes System kommt aus der Grafik-Programmierung und scheint zunächst auch nur eine alternative Darstellung zu sein: Statt von 0 bis 255 verwendet man einfach die (Bruch-)Werte von 0 bis 1 und nennt das ganze "normalisiert". Das Himmelblau von oben wird damit zu "0.008 0.153 0.106" und macht damit erstmal keine gute Figur: viele Zahlen, Dezimalpunkte und wer kann sich unter den Fliesskommazahlen schon gross etwas vorstellen? Technisch hat dies jedoch viele Vorteile und Entwickler lieben normalisierte "von 0 bis 1" Werte; man kann diese z.B. problemlos miteinander multiplizieren und überblenden. Ausserdem sind die Abstufungen mit Kommazahlen beliebig fein, während im klassischen RGB-Modus nur ganze Zahlen vorkommen (klar könnte man auch da so etwas wie "Rot 12.7003" angeben, aber spätestens im Hex-Modus klappt das nicht mehr).

Nun kommen wir zum eigentlichen Problem: Farben halbieren.

RGB-Farbwerte kann man also mit Ganzzahlen von 0 – 255 oder Kommazahlen von 0.0 – 1.0 darstellen. Aber wie halbiert man diese? Normalisiert ist das ziemlich leicht, die Hälfte von 1.0 ist 0.5, Fall erledigt. Aber bei der RGB-Darstellung? Die Hälfte von 255 ist 127.5 und das ist ein Problem, denn hier sind ja nur Ganzzahlen erlaubt. Nehmen wir also 127 oder 128?
Nun, an sich sind es ja 256 Abstufungen, man stelle sich diese als Klaviertasten vor. Ganz links befindet sich 0 und ganz rechts 255. Die Tasten haben eine gewisse Breite, weil es sich um Ganzzahlen handelt – selbst wenn man bei 0.5 drückt, erwischt man dennoch die Taste 0. Sogar bei 0.9 ist es immer noch die 0, erst ab 1.0 kommt die 1 und die wiederum reicht bis fast zur 2.0. Ganz am Ende bei 255 ist es dasselbe, sowohl 255.0 als auch 255.9 oder 255.99999 sind dort untergebracht. Im Grunde geht der Farbwert also bis (unendlich knapp) zur 256, und wenn man das halbiert erhält man eine Zahl unendlich dicht vor 128, sagen wir 127.99999. Nun wird deutlich, dass 127 als Mitte deutlich schlechter passt als 128 – wäre das also korrekter? Woher kommt überhaupt diese neue Erkenntnis?

Die Auflösung liegt in der Rundungsfunktion, denn im obigen Gedankengang habe ich stillschweigend immer abgerundet. Vergrössert betrachtet reicht die erste Klaviertaste 0 von 0.0 bis fast 1.0, aber das geht auch anders. Man kann die Zahlen genau in der Mitte der Taste festlegen, dann reicht die Taste 0 plötzlich von -0.5 bis fast 0.5 und gerundet wird beides zu 0, das klappt also. Bei der letzten Taste haben wir entsprechend links den Wert 254.5 und rechts fast 255.5, was beides auf 255 gerundet wird. Mit dieser Betrachtungsweise liegt die Mitte erneut bei 127.5 und das wird bekanntlich zu 128 aufgerundet (Hex: #80).

Diese unendlich kleine Rundung führt zu einer wesentlichen Diskrepanz zwischen RGB-Schreibweise und normalisierten Farben. Während nämlich 0.5 verdoppelt wieder genau 1.0 gibt, kommt man im RGB-Modus von 128 auf 256 (was 1 zu viel ist) oder allenfalls mit 127 auf 254 (was 1 zu wenig wäre).

Halbe Farben sind also doch nicht ganz rund, obwohl sie gerundet werden.
Themen: TechnikErklärung

Kommentar

Sirea / 24.07.2019
Interessanter Artikel. Danke für die Aufklärung!

Kommentar schreiben

Name:
E-Mail:
Beitragstext: