web-dev-qa-db-fra.com

Comment trouver une bonne couleur de police si la couleur de fond est connue?

Il semble exister de nombreuses applications Web avec roue de couleurs, sélecteur de couleurs et adaptateurs de couleurs, dans lesquelles vous donnez une couleur et la, elles trouveront deux autres couleurs qui créeront une mise en page harmonique lorsqu'elles seront utilisées en combinaison. Cependant, la plupart d'entre eux se concentrent uniquement sur les couleurs d'arrière-plan et tout texte imprimé sur chaque couleur d'arrière-plan (si du texte est imprimé dans l'aperçu) est en noir ou en blanc.

Mon problème est différent Je connais la couleur de fond que je souhaite utiliser pour une zone de texte. Ce que j’ai besoin d’aide, c’est de choisir quelques couleurs (plus on est de fous, plus on rit), que je peux utiliser comme couleurs de police sur cet arrière-plan. Le plus important est que la couleur assure la lisibilité de la police (le contraste n’est pas trop bas, ni peut-être trop élevé pour éviter que les yeux ne soient stressés) et bien sûr que la combinaison de l’avant-plan et de l’arrière-plan est tout à fait juste.

Quelqu'un est au courant d'une telle application? Je préférerais une application Web à tout ce que je dois télécharger. Merci.

86
Mecki

Si vous avez besoin d’un algorithme, essayez ceci: Convertissez la couleur de l’espace RVB en espace HSV (Teinte, Saturation, Valeur). Si votre infrastructure d'interface utilisateur ne peut pas le faire, consultez cet article: http://en.wikipedia.org/wiki/HSL_and_HSV#Conversion_from_RGB_to_HSL_or_HSV

La teinte est dans [0,360). Pour trouver la couleur "opposée" (pensez à la roue de couleur), ajoutez simplement 180 degrés:

h = (h + 180) % 360;

Pour la saturation et la valeur, inversez-les:

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

Reconvertir en RVB. Cela devrait toujours vous donner un contraste élevé, même si la plupart des combinaisons auront l'air moche.

Si vous voulez éviter la partie "laide", construisez une table avec plusieurs "bonnes" combinaisons, trouvez celle qui présente le moins de différence

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))

et l'utiliser.

39
Aaron Digulla

D'accord, ce n'est toujours pas la meilleure solution possible, mais un bon point pour commencer. J'ai écrit un peu Java app qui calcule le rapport de contraste de deux couleurs et ne traite que les couleurs avec un rapport de 5: 1 ou supérieur - ce rapport et la formule que j'ai utilisés ont été publiés par le W3C et remplacera probablement la recommandation actuelle (que j’estime très limitée). Il crée un fichier dans le répertoire de travail actuel nommé "Choisi-font-couleurs.html", avec la couleur de fond de votre choix et une ligne de texte de chaque couleur. qui a passé ce test du W3C et attend un seul argument, la couleur de fond.

Par exemple. vous pouvez l'appeler comme ça

Java FontColorChooser 33FFB4

ensuite, ouvrez simplement le fichier HTML généré dans le navigateur de votre choix et choisissez une couleur dans la liste. Toutes les couleurs données ont réussi le test W3C pour cette couleur de fond. Vous pouvez changer le seuil en remplaçant 5 par le numéro de votre choix (les chiffres inférieurs permettent des contrastes plus faibles. Par exemple, 3 ne garantit que le contraste est de 3: 1, 10 garantit qu'il est au moins de 10: 1) et vous pouvez également coupé pour éviter des contrastes trop forts (en s’assurant qu’il soit inférieur à un certain nombre), p.ex. ajouter

|| cDiff > 18.0

si la clause if garantit que le contraste ne sera pas trop extrême, des contrastes trop extrêmes peuvent gêner vos yeux. Voici le code et amusez-vous un peu avec lui :-)

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);
    }
}
4
Mecki

J'ai implémenté quelque chose de similaire pour une raison différente: il s'agissait d'un code indiquant à l'utilisateur final si les couleurs de premier plan et d'arrière-plan qu'il avait sélectionnées entraîneraient un texte illisible. Pour ce faire, plutôt que d’examiner les valeurs RVB, j’ai converti la valeur de couleur en HSL/HSV, puis déterminé expérimentalement quelle était la limite de lecture pour la lisibilité lors de la comparaison des valeurs fg et bg. C'est quelque chose que vous voudrez peut-être/devra prendre en compte.

2
RedFilter

C'est une question intéressante, mais je ne pense pas que ce soit réellement possible. Que les deux couleurs "correspondent" ou non aux couleurs d'arrière-plan et de premier plan dépend de la technologie d'affichage et des caractéristiques physiologiques de la vision humaine, mais surtout des goûts personnels façonnés par l'expérience. Un survol rapide de MySpace montre assez clairement que tous les êtres humains ne perçoivent pas les couleurs de la même manière. Je ne pense pas que ce problème puisse être résolu de manière algorithmique, même s'il peut exister une énorme base de données contenant des couleurs identiques acceptables.

2
MusiGenesis

Dans une application récente que j'ai faite, j'ai utilisé les couleurs inversées. Avec les valeurs r, g et b en main, calculez simplement (dans cet exemple, la gamme de couleurs varie de 0 à 255):

r = 127-(r-127) and so on.
2
Flávio Batista

Cela peut paraître étrange de répondre à ma propre question, mais voici un autre sélecteur de couleurs vraiment cool que je n'avais jamais vu auparavant. Cela ne résout pas non plus mon problème: (((Cependant, je pense que c'est beaucoup plus cool pour ceux que je connais déjà).

--- (http://www.colorjack.com/

Sur la droite, sous Outils, sélectionnez "Color Sphere", une sphère très puissante et personnalisable (voyez ce que vous pouvez faire avec les fenêtres contextuelles en haut), "Color Galaxy", je ne suis toujours pas sûr de savoir comment cela fonctionne, mais cool et "Color Studio" c'est aussi Nice. En outre, il peut exporter vers tous types de formats (par exemple, Illustrator ou Photoshop, etc.)

Que diriez-vous de cela, j’y choisis ma couleur d’arrière-plan, je la laisse créer une couleur complémentaire (à partir de la première fenêtre contextuelle) - celle-ci devrait avoir le contraste le plus élevé et donc être la plus lisible, sélectionnez maintenant la couleur complémentaire comme couleur principale et choisissez la couleur neutre? Hmmm ... pas trop génial non plus, mais nous nous améliorons ;-)

1
Mecki

Personnellement, je ne pense pas que nous puissions trouver un algorithme pour calculer la couleur de texte la plus appariée en spécifiant la couleur de fond.

Je pense qu’à l’heure actuelle, l’artiste devrait avoir une liste de paires de couleurs qui présente une bonne qualité de lecture. Nous pouvons les ajouter à un tableau et définir l’une de ces paires au hasard comme notre thème de lecture ...

c'est très raisonnable, et nous n'obtiendrons pas de paires de couleurs laides ...

0
flypig

Avez-vous envisagé de laisser l'utilisateur de votre application choisir son propre jeu de couleurs? Sans faute, vous ne pourrez pas satisfaire tous vos utilisateurs avec votre sélection, mais vous pouvez leur permettre de trouver ce qui leur plaît.

0
billcoke

Semblable à la suggestion de @Aaron Digulla, sauf que je suggérerais un outil de conception graphique, sélectionnez la couleur de base, dans votre cas la couleur d'arrière-plan, puis ajustez la teinte, la saturation et la valeur. En utilisant cela, vous pouvez créer des nuances de couleur très facilement. Paint.Net est gratuit et je l'utilise tout le temps pour cela. Le logiciel payant l'utilisera également.

0
MotoWilliams