86 Stimmen

Wie findet man eine gut aussehende Schriftfarbe, wenn die Hintergrundfarbe bekannt ist?

Es scheint so viele Farbrad-, Farbwähler- und Farbabgleichs-Webanwendungen zu geben, bei denen man eine Farbe angibt und die dann ein paar andere Farben finden, die in Kombination ein harmonisches Layout ergeben. Die meisten von ihnen konzentrieren sich jedoch nur auf Hintergrundfarben und jeder Text, der auf die jeweilige Hintergrundfarbe gedruckt wird (wenn überhaupt Text in der Vorschau gedruckt wird), ist entweder schwarz oder weiß.

Mein Problem ist ein anderes. Ich kenne die Hintergrundfarbe, die ich für einen Textbereich verwenden möchte. Was ich brauche, ist Hilfe bei der Auswahl einiger Farben (je mehr, desto besser), die ich als Schriftfarben auf diesem Hintergrund verwenden kann. Das Wichtigste ist, dass die Farbe dafür sorgt, dass die Schrift lesbar ist (der Kontrast darf nicht zu niedrig sein, aber auch nicht zu hoch, damit die Augen nicht überanstrengt werden) und natürlich, dass die Kombination aus Vorder- und Hintergrund einfach gut aussieht.

Kennt jemand eine solche Anwendung? Ich ziehe eine Webanwendung allem vor, was ich herunterladen muss. Danke!

39voto

Aaron Digulla Punkte 308693

Wenn Sie einen Algorithmus brauchen, versuchen Sie es hiermit: Konvertieren Sie die Farbe vom RGB-Raum in den HSV-Raum (Hue, Saturation, Value). Wenn Ihr UI-Framework dies nicht leisten kann, lesen Sie diesen Artikel: http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV

Der Farbton liegt im Bereich [0,360]. Um die "entgegengesetzte" Farbe zu finden (siehe Farbrad), addieren Sie einfach 180 Grad:

h = (h + 180) % 360;

Für Sättigung und Wert invertieren Sie sie:

l = 1.0 - l;
v = 1.0 - v;

Zurück zu RGB konvertieren. So sollten Sie immer einen hohen Kontrast erhalten, auch wenn die meisten Kombinationen hässlich aussehen werden.

Wenn Sie den "hässlichen" Teil vermeiden wollen, erstellen Sie eine Tabelle mit mehreren "guten" Kombinationen und finden Sie diejenige mit dem geringsten Unterschied

def q(x):
    return x*x
def diff(col1, col2):
    return math.sqrt(q(col1.r-col2.r) + q(col1.g-col2.g) + q(col1.b-col2.b))

und verwenden Sie diese.

4voto

Mecki Punkte 113876

Okay, das ist immer noch nicht die bestmögliche Lösung, aber ein guter Ansatzpunkt. Ich habe eine kleine Java-Anwendung geschrieben, die das Kontrastverhältnis zweier Farben berechnet und nur Farben mit einem Verhältnis von 5:1 oder besser verarbeitet - dieses Verhältnis und die Formel, die ich verwende, wurden vom W3C veröffentlicht und werden wahrscheinlich die aktuelle Empfehlung ersetzen (die ich für sehr begrenzt halte). Es wird eine Datei im aktuellen Arbeitsverzeichnis mit dem Namen "chosen-font-colors.html" erstellt, mit der Hintergrundfarbe Ihrer Wahl und einer Textzeile in jeder Farbe, die diesen W3C-Test bestanden hat. Er erwartet ein einziges Argument, nämlich die Hintergrundfarbe.

Sie können es z.B. so aufrufen

java FontColorChooser 33FFB4

dann öffnen Sie einfach die generierte HTML-Datei in einem Browser Ihrer Wahl und wählen Sie eine Farbe aus der Liste. Alle angegebenen Farben haben den W3C-Test für diese Hintergrundfarbe bestanden. Sie können den Abschneidefaktor ändern, indem Sie 5 durch eine Zahl Ihrer Wahl ersetzen (niedrigere Zahlen erlauben schwächere Kontraste, z. B. 3 stellt nur sicher, dass der Kontrast 3:1 beträgt, 10 stellt sicher, dass er mindestens 10:1 beträgt), und Sie können den Abschneidefaktor auch ändern, um zu hohe Kontraste zu vermeiden (indem Sie sicherstellen, dass er kleiner als eine bestimmte Zahl ist), z. B. indem Sie

|| cDiff > 18.0

in der if-Klausel stellt sicher, dass der Kontrast nicht zu extrem ist, da zu extreme Kontraste die Augen belasten können. Hier ist der Code und viel Spaß beim Herumspielen :-)

import java.io.*;

/* For text being readable, it must have a good contrast difference. Why?
 * Your eye has receptors for brightness and receptors for each of the colors
 * red, green and blue. However, it has much more receptors for brightness
 * than for color. If you only change the color, but both colors have the
 * same contrast, your eye must distinguish fore- and background by the
 * color only and this stresses the brain a lot over the time, because it
 * can only use the very small amount of signals it gets from the color
 * receptors, since the breightness receptors won't note a difference.
 * Actually contrast is so much more important than color that you don't
 * have to change the color at all. E.g. light red on dark red reads nicely
 * even though both are the same color, red.
 */

public class FontColorChooser {
    int bred;
    int bgreen;
    int bblue;

    public FontColorChooser(String hexColor) throws NumberFormatException {
        int i;

        i = Integer.parseInt(hexColor, 16);
        bred = (i >> 16);
        bgreen = (i >> 8) & 0xFF;
        bblue = i & 0xFF;
    }

    public static void main(String[] args) {
        FontColorChooser fcc;

        if (args.length == 0) {
            System.out.println("Missing argument!");
            System.out.println(
                "The first argument must be the background" +
                "color in hex notation."
            );
            System.out.println(
                "E.g. \"FFFFFF\" for white or \"000000\" for black."
            );
            return;
        }
        try {
            fcc = new FontColorChooser(args[0]);
        } catch (Exception e) {
            System.out.println(
                args[0] + " is no valid hex color!"
            );
            return;
        }
        try {
            fcc.start();
        } catch (IOException e) {
            System.out.println("Failed to write output file!");
        }
    }

    public void start() throws IOException {
        int r;
        int b;
        int g;
        OutputStreamWriter out;

        out = new OutputStreamWriter(
            new FileOutputStream("chosen-font-colors.html"),
            "UTF-8"
        );

        // simple, not W3C comform (most browsers won't care), HTML header
        out.write("<html><head><title>\n");
        out.write("</title><style type=\"text/css\">\n");
        out.write("body { background-color:#");
        out.write(rgb2hex(bred, bgreen, bblue));
        out.write("; }\n</style></head>\n<body>\n");

        // try 4096 colors
        for (r = 0; r <= 15; r++) {
            for (g = 0; g <= 15; g++) {
                for (b = 0; b <= 15; b++) {
                    int red;
                    int blue;
                    int green;
                    double cDiff;

                    // brightness increasse like this: 00, 11,22, ..., ff
                    red = (r << 4) | r;
                    blue = (b << 4) | b;
                    green = (g << 4) | g;

                    cDiff = contrastDiff(
                        red, green, blue,
                        bred, bgreen, bblue
                    );
                    if (cDiff < 5.0) continue;
                    writeDiv(red, green, blue, out);
                }
            }
        }

        // finalize HTML document
        out.write("</body></html>");

        out.close();
    }

    private void writeDiv(int r, int g, int b, OutputStreamWriter out)
        throws IOException
    {
        String hex;

        hex = rgb2hex(r, g, b);
        out.write("<div style=\"color:#" + hex + "\">");
        out.write("This is a sample text for color " + hex + "</div>\n");
    }

    private double contrastDiff(
        int r1, int g1, int b1, int r2, int g2, int b2
    ) {
        double l1;
        double l2;

        l1 = ( 
            0.2126 * Math.pow((double)r1/255.0, 2.2) +
            0.7152 * Math.pow((double)g1/255.0, 2.2) +
            0.0722 * Math.pow((double)b1/255.0, 2.2) +
            0.05
        );
        l2 = ( 
            0.2126 * Math.pow((double)r2/255.0, 2.2) +
            0.7152 * Math.pow((double)g2/255.0, 2.2) +
            0.0722 * Math.pow((double)b2/255.0, 2.2) +
            0.05
        );

        return (l1 > l2) ? (l1 / l2) : (l2 / l1);
    }

    private String rgb2hex(int r, int g, int b) {
        String rs = Integer.toHexString(r);
        String gs = Integer.toHexString(g);
        String bs = Integer.toHexString(b);
        if (rs.length() == 1) rs = "0" + rs;
        if (gs.length() == 1) gs = "0" + gs;
        if (bs.length() == 1) bs = "0" + bs;
        return (rs + gs + bs);
    }
}

2voto

MusiGenesis Punkte 72729

Das ist eine interessante Frage, aber ich glaube nicht, dass dies wirklich möglich ist. Ob zwei Farben als Hintergrund- und Vordergrundfarben "passen" oder nicht, hängt von der Displaytechnologie und den physiologischen Eigenschaften des menschlichen Sehvermögens ab, vor allem aber vom persönlichen Geschmack, der durch Erfahrung geprägt ist. Ein kurzer Durchlauf durch MySpace zeigt ziemlich deutlich, dass nicht alle Menschen Farben auf die gleiche Weise wahrnehmen. Ich glaube nicht, dass dieses Problem algorithmisch gelöst werden kann, auch wenn es vielleicht irgendwo eine riesige Datenbank mit akzeptablen passenden Farben gibt.

2voto

D'Arcy Rittich Punkte 159655

Ich habe etwas Ähnliches aus einem anderen Grund implementiert - das war ein Code, der dem Endbenutzer mitteilt, ob die von ihm ausgewählte Vorder- und Hintergrundfarbe zu unlesbarem Text führen würde. Dazu habe ich nicht die RGB-Werte untersucht, sondern den Farbwert in HSL/HSV umgewandelt und dann durch Experimentieren herausgefunden, wo der Grenzwert für die Lesbarkeit liegt, wenn ich die fg- und bg-Werte vergleiche. Das ist etwas, das Sie vielleicht in Betracht ziehen wollen/müssen.

2voto

Flávio Batista Punkte 31

In einer kürzlich von mir erstellten Anwendung habe ich die invertierten Farben verwendet. Mit den r,g und b Werten in der Hand, einfach berechnen (in diesem Beispiel, der Farbbereich variiert von 0 bis 255):

r = 127-(r-127) and so on.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X