Как программно рассчитать коэффициент контрастности между двумя цветами?
Довольно прямо, возьмите желтый и белый:
back_color = {r:255,g:255,b:255}; //white
text_color = {r:255,g:255,b:0}; //yellow
Какой закон физики на Земле Бога универсальных констант делает тот факт, что желтый текст не может быть прочитан на белом фоне, но синий текст может?
Для моего настраиваемого виджета я попробовал все возможные цветовые модели, для которых я нашел функции преобразования; ни один из них не может сказать, что зеленый цвет может быть на белом и желтом не может, основываясь только на численных сравнениях.
Я посмотрел на Adsense (который создается Budda всего Интернета) и догадывался, что они сделали, они делали дистанционные вычисления пресетов и цветных ячеек. Я не могу этого сделать. Мои пользователи имеют право выбирать даже самые сетчато-воспалительные, неэстетичные комбинации, если текст еще может быть прочитан.
Ответы
Ответ 1
Согласно Википедии, при преобразовании в полутоновое представление яркости "нужно получить значения красного, зеленого и синего" и смешать их в следующей пропорции: R: 30% G: 59% B: 11%
Поэтому белый будет иметь 100% яркость, а желтый - 89%. В то же время зеленый цвет достигает 59%. 11% почти в четыре раза ниже, чем разница в 41%!
И даже известь (#00ff00
) не подходит для чтения большого количества текстов.
IMHO для яркости контрастных цветов должна отличаться по меньшей мере на 50%. И эту яркость следует измерять как преобразованную в оттенки серого.
upd: недавно найдено всеобъемлющий инструмент для этого в Интернете
который для использования формулы из w3 document
Пороговые значения могут быть взяты из # 1.4
Вот реализация этой более продвинутой вещи.
function luminanace(r, g, 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;
}
function contrast(rgb1, rgb2) {
return (luminanace(rgb1[0], rgb1[1], rgb1[2]) + 0.05)
/ (luminanace(rgb2[0], rgb2[1], rgb2[2]) + 0.05);
}
contrast([255, 255, 255], [255, 255, 0]); // 1.074 for yellow
contrast([255, 255, 255], [0, 0, 255]); // 8.592 for blue
// minimal recommended contrast ratio is 4.5, or 3 for larger font-sizes
Ответ 2
Существуют различные способы вычисления контраста, но общий способ заключается в следующем:
brightness = (299*R + 587*G + 114*B) / 1000
Вы делаете это для обоих цветов, и тогда вы понимаете разницу. Это, очевидно, дает гораздо больший контраст для синего на белом, чем желтый на белом.
Ответ 3
Недавно я наткнулся на ответ на этой странице, и я использовал код, чтобы сделать script для Adobe Illustrator, чтобы рассчитать коэффициент контрастности.
Здесь вы можете увидеть результат: http://screencast.com/t/utT481Ut
Некоторые из сокращенных обозначений script выше, где меня путают и где не работают в Adobe, расширяются script. Поэтому я подумал, что было бы неплохо поделиться моим улучшением/интерпретацией кода, который разделял кириллоид.
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;
}
И, конечно, вам нужно вызвать эту функцию
в цикле for я получаю все цвета от моего объекта иллюстратора
//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);
}
Дополнительная информация о коэффициенте контрастности: http://webaim.org/resources/contrastchecker/
Ответ 4
module.exports = function colorcontrast (hex) {
var color = {};
color.contrast = function(rgb) {
// check if we are receiving an element or element background-color
if (rgb instanceof jQuery) {
// get element background-color
rgb = rgb.css('background-color');
} else if (typeof rgb !== 'string') {
return;
}
// Strip everything except the integers eg. "rgb(" and ")" and " "
rgb = rgb.split(/\(([^)]+)\)/)[1].replace(/ /g, '');
// map RGB values to variables
var r = parseInt(rgb.split(',')[0], 10),
g = parseInt(rgb.split(',')[1], 10),
b = parseInt(rgb.split(',')[2], 10),
a;
// if RGBA, map alpha to variable (not currently in use)
if (rgb.split(',')[3] !== null) {
a = parseInt(rgb.split(',')[3], 10);
}
// calculate contrast of color (standard grayscale algorithmic formula)
var contrast = (Math.round(r * 299) + Math.round(g * 587) + Math.round(b * 114)) / 1000;
return (contrast >= 128) ? 'black' : 'white';
};
// Return public interface
return color;
};
Ответ 5
Основываясь на кириллоидном ответе:
Angular Служба, которая будет вычислять контраст и люминесценцию, передавая шестнадцатеричное значение:
.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;
};
}]);