RGB nach CMYK

Auf dieser Seite geht es um die Konvertierung von RGB Farbwerten zu CMYK Werten. Der Übergang von RGB zu CMYK ist deshalb so knifflig, weil wir von der Welt des Lichts (Monitor) in die Welt der Materie (Druckerschwärze) wechseln.

Der entscheidende Unterschied ist, wer die Farbe erzeugt:

Warum subtrahieren wir also?

Man nennt es subtraktiv, weil die Tinte dem weißen Licht, das vom Papier reflektiert wird, etwas wegnimmt.

Wenn du also im RGB-Modell sagst "Ich habe kein Rot mehr" , dann sagt das CMYK-Modell: "Okay, dann muss ich Cyan-Tinte drucken, um das Rot im reflektierten Licht zu schlucken."

Die mathematische Formel cyan=1 - r ist also nichts anderes als die Übersetzung von "Wie viel Licht ist da?" zu "Wie viel Licht muss ich durch Tinte weglöschen?" .

Warum rechnen wir in der Formel "eins minus RGB-Wert" ? Es ist quasi die Umrechnung von der Anwesenheit des Lichts zur Anwesenheit der Tinte.

 

200
100
0

Farbe Zähler (1 - cc - k) Nenner (1 - k) Ergebnis (CMYK %)
Cyan - - -
Magenta - -
Yellow - -
Key (Schwarz) k = 1 - max(r, g, b) -

cc = Komplementärfarbe (cyan ➟ rot) (magenta ➟ grün) (yellow ➟ blau)

 

Die Logik der Umrechnung

Um von RGB (0-255) zu CMYK (0-1) zu kommen, gehen wir in vier Schritten vor:

  1. Normalisierung: Wir teilen R, G und B durch 255, um Werte zwischen 0 und 1 zu erhalten.

  2. Schwarz-Extraktion K: Wir schauen, welche der drei Farben am stärksten vertreten ist. Das "Fehlen" von Farbe definiert unser Schwarz.

    • Formel: K = 1 - max(R', G', B')

  3. Buntfarben-Berechnung (C, M, Y): Wir ziehen den Schwarzanteil vom Komplementärwert ab.

    • Formel für Cyan: C = (1 - R - K) / (1 - K)

  4. Sonderfall Weiß: Wenn alle RGB-Werte 255 sind, wäre die Division durch Null. Das fangen wir ab.

Umsetzung in JavaScript

Hier ist eine saubere Funktion, die einen Hex-Wert nimmt und ein CMYK-Objekt zurückgibt:

        function hexToCMYK(hex) {
        // 1. Hex zu RGB umrechnen
        let r = parseInt(hex.substring(1, 3), 16) / 255;
        let g = parseInt(hex.substring(3, 5), 16) / 255;
        let b = parseInt(hex.substring(5, 7), 16) / 255;

        // 2. K (Schwarz) berechnen
        // Schwarz ist das Gegenteil des hellsten Kanals
        let k = 1 - Math.max(r, g, b);

        // Spezialfall: Reines Schwarz
        if (k === 1) {
        return { c: 0, m: 0, y: 0, k: 100 };
        }

        // 3. C, M, Y berechnen (und in Prozent umwandeln)
        let c = Math.round((1 - r - k) / (1 - k) * 100);
        let m = Math.round((1 - g - k) / (1 - k) * 100);
        let y = Math.round((1 - b - k) / (1 - k) * 100);
        let kPerc = Math.round(k * 100);

        return { c, m, y, k: kPerc };
        }

        // Beispielaufruf:
        // let cmyk = hexToCMYK("#ffcc00");
        // console.log(cmyk); -> { c: 0, m: 20, y: 100, k: 0 }
      

Das Geheimnis des "K" (Key/Schwarz)

In der Theorie ergibt Cyan + Magenta + Gelb ein tiefes Schwarz. In der Realität ergibt das bei Druckfarben aber eher ein schmutziges Dunkelbraun. Deshalb fügt man im Druck echtes schwarzes Pigment hinzu (Key).

Der Trick bei der Umrechnung: Schwarz ist einfach der Anteil an "Nicht-Farbe".

Schwarz orientiert sich am niedrigsten RGB-Wert (bzw. dem "Abstand" des höchsten Werts zu 100%). K (Schwarz) bestimmt sich daraus, wie weit der hellste RGB-Punkt von der vollen Leuchtkraft entfernt ist. (K = 1 - hellster Kanal).

Das "Braune Suppe" Problem

Wenn wir im Druck versuchen würden, ein dunkles Grau nur aus Cyan, Magenta und Gelb zu mischen, bräuchten wir von allem sehr viel. Da die Pigmente nicht perfekt sind, reflektieren sie immer noch ein bisschen Restlicht – das Ergebnis sieht matschig oder bräunlich aus.

Die K-Logik (Schwarz) löst das so:

Anstatt drei teure Farben übereinander zu drucken, um Dunkelheit zu erzeugen, nimmt man die "gemeinsame Dunkelheit" aller drei Kanäle raus und ersetzt sie durch die billige und "echte" schwarze Tinte (K). Die Formel k = 1 - max(R,G,B) zeigt also den prozentualen Bereich an, in dem alle 3 Farben durch schwarz ersetzt werden können.

Was passiert da mathematisch genau?

Stell dir vor, du hast ein helles Grau in RGB: rgb(200, 200, 200).

Gehen wir das Ganze Schritt für Schritt durch, damit die Logik dahinter klar wird.

1. Das Grundprinzip: Komplementärfarben

In der Farbenlehre sind Cyan und Rot Gegenspieler.

2. Das Problem mit dem Schwarz (K)

Das Problem ist: Wir haben ja schon einen Teil der Farbe "ausgelagert", nämlich in den Schwarz-Kanal (K).

Wir haben K so berechnet: K = 1 - max(R, G, B).

Das bedeutet, K nimmt bereits den dunklen Anteil weg, den alle drei Farben (RGB) gemeinsam haben.

3. Die Formel im Detail: (1 - r - k) / (1 - k)

Schauen wir uns den Zähler und den Nenner getrennt an:

Der Zähler: (1 - r - k)

Hier berechnen wir, wie viel Cyan eigentlich übrig bleiben müsste, nachdem wir das Rot und das bereits abgezogene Schwarz berücksichtigt haben.

Der Nenner: / (1 - k) (Die Skalierung)

Das ist der wichtigste Teil. Wenn wir Schwarz (K) hinzufügen, wird der gesamte Farbraum "kleiner". Wir müssen das Ergebnis normalisieren.

Ohne diese Division würde die Farbe immer schwächer und grauer werden, je dunkler das Bild ist. Wir teilen durch den "Restplatz", der nach Abzug von Schwarz noch im Farbtopf übrig ist.

Was würde passieren wenn man nicht teilen würde.

Dunkles Lila: r=0.5, g=0.2, b=0.5

  1. Schwarz berechnen: k = 1 - max(0.5, 0.2, 0.5) = 0.5

  2. Magenta (M) berechnen:

    • Zähler: (1 - g - k) ➟ (1 - 0.2 - 0.5) = 0.3

    • Nenner: (1 - k) ➟ (1 - 0.5) = 0.5

    • Division: 0.3 / 0.5 = 0.6 (also 60%)

 

Wenn wir nur subtrahieren würden (1 - g - k), kämen wir im Lila Beispiel auf 0.3.

Das Schwarz k=0.5 würde die Farbe so stark unterdrücken, dass das Lila im Druck viel zu blass und grau wäre.

Die Division durch (1-k) wirkt wie ein Verstärker:

Sie rechnet die Farbe wieder "hoch", damit das Verhältnis zwischen Cyan, Magenta und Gelb trotz der schwarzen Tinte korrekt bleibt. Man normiert die Buntfarben auf den Bereich, der nach Abzug von Schwarz noch übrig ist.

Zusammenfassend: