108 votes

Comment calculer par programme le rapport de contraste entre deux couleurs ?

C'est assez simple, il suffit de prendre le jaune et le blanc :

back_color = {r:255,g:255,b:255}; //white
text_color = {r:255,g:255,b:0}; //yellow

Quelle loi physique, sur la Terre de Dieu des constantes universelles, explique que le texte jaune ne puisse pas être lu sur un fond blanc alors que le texte bleu le peut ?

Pour les besoins de mon widget personnalisable, j'ai essayé tous les modèles de couleurs possibles pour lesquels j'ai trouvé des fonctions de conversion ; on ne peut pas non plus dire que le vert peut être sur du blanc et que le jaune ne le peut pas, en se basant uniquement sur des comparaisons numériques.

J'ai regardé Adsense (qui est créé par le Bouddha de l'Internet) et devinez ce qu'ils ont fait, ils ont créé des préréglages et des cellules de couleur pour calculer la distance. Je ne peux pas faire ça. Mes utilisateurs ont le droit de choisir les combinaisons les plus inesthétiques et les plus inflammatoires pour la rétine, tant que le texte reste lisible.

147voto

kirilloid Points 7139

Selon Wikipedia, pour convertir la luminance en niveaux de gris, "il faut obtenir les valeurs du rouge, du vert et du bleu" et les mélanger dans les proportions suivantes : R:30% G:59% B:11%

Par conséquent, le blanc aura une luminance de 100 % et le jaune de 89 %. Dans le même temps, le vert a une luminance aussi faible que 59 %. 11 %, c'est presque quatre fois moins que la différence de 41 % !

Et même le citron vert ( #00ff00 ) n'est pas adapté à la lecture d'un grand nombre de textes.

Pour un bon contraste, la luminosité des couleurs doit différer d'au moins 50 %. Et cette luminosité doit être mesurée en convertissant les couleurs en niveaux de gris.

Mise à jour : J'ai récemment trouvé un outil complet pour cela sur le web qui, dans l'ordre, utilise la formule de document w3 Les valeurs seuils peuvent être tirées de #1.4 Voici une implémentation pour cette chose plus avancée.

const RED = 0.2126;
const GREEN = 0.7152;
const BLUE = 0.0722;

const GAMMA = 2.4;

function luminance(r, g, b) {
  var a = [r, g, b].map((v) => {
    v /= 255;
    return v <= 0.03928
      ? v / 12.92
      : Math.pow((v + 0.055) / 1.055, GAMMA);
  });
  return a[0] * RED + a[1] * GREEN + a[2] * BLUE;
}

function contrast(rgb1, rgb2) {
  var lum1 = luminance(...rgb1);
  var lum2 = luminance(...rgb2);
  var brightest = Math.max(lum1, lum2);
  var darkest = Math.min(lum1, lum2);
  return (brightest + 0.05) / (darkest + 0.05);
}

console.log(contrast([255, 255, 255], [255, 255, 0])); // 1.074 for yellow
console.log(contrast([255, 255, 255], [0, 0, 255])); // 8.592 for blue

// note: minimal recommended contrast ratio is 4.5, or 3 for larger font-sizes

Pour plus d'informations, consultez le site Documentation WCAG 2.0 sur la manière de calculer cette valeur.

34voto

nightcracker Points 34498

Il existe plusieurs façons de calculer le contraste, mais la formule suivante est la plus courante :

brightness = (299*R + 587*G + 114*B) / 1000

Vous faites cela pour les deux couleurs, puis vous prenez la différence. Cela donne évidemment un contraste beaucoup plus important pour le bleu sur le blanc que pour le jaune sur le blanc.

3voto

Artem Bochkarev Points 143
const getLuminanace = (values) => {
  const rgb = values.map((v) => {
    const val = v / 255;
    return val <= 0.03928 ? val / 12.92 : ((val + 0.055) / 1.055) ** 2.4;
  });
  return Number((0.2126 * rgb[0] + 0.7152 * rgb[1] + 0.0722 * rgb[2]).toFixed(3));
};

const getContrastRatio = (colorA, colorB) => {
  const lumA = getLuminanace(colorA);
  const lumB = getLuminanace(colorB);

  return (Math.max(lumA, lumB) + 0.05) / (Math.min(lumA, lumB) + 0.05);
};

// usage:
const back_color = [255,255,255]; //white
const text_color = [255,255,0]; //yellow

getContrastRatio(back_color, text_color); // 1.0736196319018405

2voto

user1495594 Points 31

J'ai récemment trouvé la réponse sur cette page, et j'ai utilisé le code pour créer un script pour Adobe Illustrator afin de calculer le rapport de contraste.

Voici le résultat : http://screencast.com/t/utT481Ut

Certaines des notations abrégées du script ci-dessus me déroutaient et ne fonctionnaient pas dans Adobe extend script. C'est pourquoi j'ai pensé qu'il serait bon de partager mon amélioration/interprétation du code que kirilloid a partagé.

function luminance(r, g, b) {
    var colorArray = [r, g, b];
    var colorFactor;
    var i;
    for (i = 0; i < colorArray.length; i++) {
        colorFactor = colorArray[i] / 255;
        if (colorFactor <= 0.03928) {
            colorFactor = colorFactor / 12.92;
        } else {
            colorFactor = Math.pow(((colorFactor + 0.055) / 1.055), 2.4);
        }
        colorArray[i] = colorFactor;
    }
    return (colorArray[0] * 0.2126 + colorArray[1] * 0.7152 + colorArray[2] * 0.0722) + 0.05;
}

Et bien sûr, vous devez appeler cette fonction

dans une boucle for, je récupère toutes les couleurs de mon objet illustrator

//just a snippet here to demonstrate the notation
var selection = app.activeDocument.selection;
for (i = 0; i < selection.length; i++) {
   red[i] = selection[i].fillColor.red;
   //I left out the rest,because it would become to long
}

//this can then be used to calculate the contrast ratio.
var foreGround = luminance(red[0], green[0], blue[0]);
var background = luminance(red[1], green[1], blue[1]);
luminanceValue = foreGround / background;
luminanceValue = round(luminanceValue, 2);

//for rounding the numbers I use this function:
function round(number, decimals) {
   return +(Math.round(number + "e+" + decimals) + "e-" + decimals);
}

Plus d'informations sur le rapport de contraste : http://webaim.org/resources/contrastchecker/

2voto

Zoro Points 181

Basé sur la réponse du kirilloïde :

Service angulaire qui calcule le contraste et la luminescence en passant la valeur hexagonale :

.service('ColorContrast', [function() {
var self = this;

/**
 * Return iluminance value (base for getting the contrast)
 */
self.calculateIlluminance = function(hexColor) {
    return calculateIluminance(hexColor);
};

/**
 * Calculate contrast value to white
 */
self.contrastToWhite = function(hexColor){
    var whiteIlluminance = 1;
    var illuminance = calculateIlluminance(hexColor);
    return whiteIlluminance / illuminance;
};

/**
* Bool if there is enough contrast to white
*/
self.isContrastOkToWhite = function(hexColor){
    return self.contrastToWhite(hexColor) > 4.5;
};

/**
 * Convert HEX color to RGB
 */
var hex2Rgb = function(hex) {
    var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
    return result ? {
        r: parseInt(result[1], 16),
        g: parseInt(result[2], 16),
        b: parseInt(result[3], 16)
    } : null;
};

/**
 * Calculate iluminance
 */
var calculateIlluminance = function(hexColor) {
    var rgbColor = hex2Rgb(hexColor);
    var r = rgbColor.r, g = rgbColor.g, b = rgbColor.b;
    var a = [r, g, b].map(function(v) {
        v /= 255;
        return (v <= 0.03928) ?
            v / 12.92 :
            Math.pow(((v + 0.055) / 1.055), 2.4);
    });
    return a[0] * 0.2126 + a[1] * 0.7152 + a[2] * 0.0722;
};

}]);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X