160 votes

Comment vérifier si une couleur hexadécimale est "trop noire"?

Je essaie d'évaluer l'obscurité d'une couleur choisie par un sélecteur de couleur pour voir si elle est "trop noire", et dans ce cas, la fixer à blanc. Je pensais que je pourrais utiliser les premiers caractères de la valeur hexadécimale pour y arriver. Cela fonctionne, mais cela change aussi certaines couleurs légitimement "claires".

J'ai le code suivant:

if (lightcolor.substring(0, 3) == "#00" || lightcolor.substring(0, 3) == "#010") {
  lightcolor = "#FFFFFF";
  color = lightcolor;
}

Il doit y avoir un moyen plus efficace avec les mathématiques hexadécimales pour savoir qu'une couleur a dépassé un certain niveau d'obscurité ? Comme si lightcolor + "une valeur hexadécimale quelconque" <= "une valeur hexadécimale quelconque" alors la fixer à blanc.

J'ai ajouté tinyColor, qui pourrait être utile pour cela, mais je n'en suis pas sûr.

1 votes

Avez-vous essayé de mettre en place un sélecteur de couleurs et de vérifier les valeurs ? J'ai remarqué que lorsque R, G et B sont tous inférieurs à ~70, cela devient sombre. Ce n'est peut-être pas la manière correcte, mais c'en est une.

1 votes

Comme vous utilisez déjà tinyColor, transformez la couleur en HSL et regardez le composant L. 1 = blanc, 0 = noir

4 votes

@Andreas La luminosité HSL ne prend pas en compte la perception humaine. Une valeur L de 0,5 aura une luminosité perçue différente pour différentes teintes.

300voto

Alnitak Points 143355

Vous devez extraire individuellement les trois composantes RGB, puis utiliser une formule standard pour convertir les valeurs RGB résultantes en leur luminosité perçue.

En supposant une couleur de six caractères :

var c = c.substring(1);      // supprimer #
var rgb = parseInt(c, 16);   // convertir rrggbb en décimal
var r = (rgb >> 16) & 0xff;  // extraire le rouge
var g = (rgb >>  8) & 0xff;  // extraire le vert
var b = (rgb >>  0) & 0xff;  // extraire le bleu

var luma = 0.2126 * r + 0.7152 * g + 0.0722 * b; // selon l'ITU-R BT.709

if (luma < 40) {
    // choisir une couleur différente
}

MODIFICATION

Depuis mai 2014, tinycolor possède maintenant une fonction getBrightness(), même si elle utilise les facteurs de pondération CCIR601 au lieu de ceux de l'ITU-R mentionnés ci-dessus.

MODIFICATION

La plage de valeurs de luminosité résultante va de 0 à 255, où 0 est le plus sombre et 255 est le plus clair. Les valeurs supérieures à 128 sont considérées comme claires par tinycolor. (honteusement copié des commentaires de @pau.moreno et @Alnitak)

20 votes

Je n'ai pas vu de bonne manipulation de bits en javascript depuis longtemps. des trucs sympas. fr.wikipedia.org/wiki/Rec._709#Coefficients_de_luminance

2 votes

Bon code, mais après avoir testé, je suggère var luma = (r + g + b)/3; if (luma < 128) { // sera plus utile. }

3 votes

@TerryLin Pourquoi? Les coefficients donnés sont les valeurs ITU standard qui tiennent compte du fait que le vert est perçu plus brillamment que le rouge (et ensuite le bleu).

6voto

David Nguyen Points 286

Il y a une distinction importante ici entre la luminance et la luminosité. La luminance, en fin de compte, est une mesure de la quantité d'énergie qui traverse une certaine zone et ignore complètement comment nos systèmes perceptuels perçoivent cette énergie. La luminosité, en revanche, est une mesure de comment nous percevons cette énergie et prend en compte la relation entre la luminance et notre système perceptuel. (Pour prêter à confusion, il y a un terme appelé luminance relative, qui semble être utilisé de manière synonyme avec des termes de luminosité. Cela m'a bien perturbé).

Pour être précis, vous cherchez "luminosité" ou "valeur" ou "luminance relative" comme d'autres l'ont suggéré. Vous pouvez calculer cela de plusieurs manières différentes (c'est une caractéristique humaine!) http://en.wikipedia.org/wiki/HSL_and_HSV#Lightness

  1. Prenez le maximum de R, G et B.
  2. Prenez la moyenne du maximum et du minimum de R, G et B.
  3. Prenez la moyenne des trois.
  4. Utilisez une moyenne pondérée comme d'autres l'ont suggéré ici.

0 votes

Selon ce que je sais, seule le calcul du luma décrit sur la page Wikipedia est un modèle basé sur la perception.

2 votes

Il est bon de souligner la distinction entre l'énergie lumineuse physique et la luminosité perçue, mais je pense que vous avez plutôt embrouillé les choses. Le paragraphe de l'article Wikipedia auquel vous avez fait référence comporte un quatrième point, qui indique qu'« une alternative plus pertinente d'un point de vue perceptif consiste à utiliser la luminance, Y, en tant que dimension de luminosité » (soulignement de ma part) puis il donne la formule présentée dans les réponses d'Alnitak et de Robin. En d'autres termes, la méthode que vous avez omise et déconseillée est celle qui correspond le mieux à la perception humaine.

0 votes

@JohnY oui, c'est ce que j'essayais de dire - il a omis le seul qui correspond effectivement au reste de sa réponse.

6voto

Robin Points 10884

Vous pouvez calculer la luminance:

La luminance est donc un indicateur de la luminosité apparente de la surface.

Il est donc judicieux de choisir si le texte doit être blanc ou noir.

var getRGB = function(b){
    var a;
    if(b&&b.constructor==Array&&b.length==3)return b;
    if(a=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(b))return[parseInt(a[1]),parseInt(a[2]),parseInt(a[3])];
    if(a=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(b))return[parseFloat(a[1])*2.55,parseFloat(a[2])*2.55,parseFloat(a[3])*2.55];
    if(a=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(b))return[parseInt(a[1],16),parseInt(a[2],16),parseInt(a[3],
16)];
    if(a=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(b))return[parseInt(a[1]+a[1],16),parseInt(a[2]+a[2],16),parseInt(a[3]+a[3],16)];
    return (typeof (colors) != "undefined")?colors[jQuery.trim(b).toLowerCase()]:null
};

var luminance_get = function(color) {
    var rgb = getRGB(color);
    if (!rgb) return null;
        return 0.2126 * rgb[0] + 0.7152 * rgb[1] + 0.0722 * rgb[2];
}

La méthode ci-dessus vous permet de passer la couleur sous différents formats, mais l'algorithme se trouve principalement dans luminance_get.

Quand je l'ai utilisé, j'ai défini la couleur en noir si la luminance était supérieure à 180, sinon en blanc.

2voto

Halcyon Points 31203

Savez-vous comment fonctionnent les codes couleur?

Voici un outil pratique : http://www.javascripter.net/faq/rgbtohex.htm

Essentiellement, le format est le suivant :

#RRGGBBRR est une valeur entre 00 et ff indiquant l'indice de rouge, G est pour vert et B est bleu, et comme vous le savez rouge + vert + bleu = blanc.

Donc la couleur : #00FF00 est verte claire. Vérifier uniquement les deux premiers caractères ne suffit pas, vous devez regarder tous.

2voto

Ohad Points 787

Une solution possible serait de convertir votre couleur de RGB en HSB. HSB signifie teinte, saturation et luminosité (également connu sous le nom de HSV, où V signifie valeur). Ensuite, vous avez juste un paramètre à vérifier : la luminosité.

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