Given a background color, how to get a foreground color that makes it readable on that background color?
I mean computing that foreground color automatically in a pr
Here's one I did in both Java and Javascript. It's loosely based off this one in javascript. I took the Luminance formula from here. The sweet-spot of the threshold from my eye was about 140.
Java version:
public class Color {
private float CalculateLuminance(ArrayList<Integer> rgb){
return (float) (0.2126*rgb.get(0) + 0.7152*rgb.get(1) + 0.0722*rgb.get(2));
}
private ArrayList<Integer> HexToRBG(String colorStr) {
ArrayList<Integer> rbg = new ArrayList<Integer>();
rbg.add(Integer.valueOf( colorStr.substring( 1, 3 ), 16 ));
rbg.add(Integer.valueOf( colorStr.substring( 3, 5 ), 16 ));
rbg.add(Integer.valueOf( colorStr.substring( 5, 7 ), 16 ));
return rbg;
}
public String getInverseBW(String hex_color) {
float luminance = this.CalculateLuminance(this.HexToRBG(hex_color));
String inverse = (luminance < 140) ? "#fff" : "#000";
return inverse;
}
}
Javascript version:
Here's the same thing in javascript for your front-end things. RGB conversion taken from here:
hex_to_rgb: 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;
},
hex_inverse_bw: function(hex) {
rgb = this.hex_to_rgb(hex);
luminance = (0.2126*rgb["r"] + 0.7152*rgb["g"] + 0.0722*rgb["b"]);
return (luminance < 140) ? "#ffffff": "#000000";
}
Using colors as foreground color is difficult, because you have to take contrast and color blindness into account.
In case this could still be useful for someone, this is the Dart implementation based on the answers above
Color getInverseBW(Color color) {
double luminance = (0.2126 * color.red + 0.7152 * color.green + 0.0722 * color.blue);
return (luminance < 140) ? Color(0xffffffff) : Color(0xff000000);
}
The safest bet is to conform with the World Wide Web Consortium’s (W3C) Web Content Accessibility Guidelines 2.0, which specify a brightness contrast ratio of 4.5:1 for regular text (12 pt or smaller), and 3.0:1 for large text. Contrast ratio is defined as:
[Y(b) + 0.05] / [Y(d) + 0.05]
Where Y(b) is the brightness (luminance) of the brighter color and Y(d) is the brightness of the darker color.
You calculate luminance Y by first converting each of the color’s RGB values to gamma adjusted normalize rgb values:
Then combine them using sRGB constants (rounded to 4 places):
Y = 0.2126*r + 0.7151*g + 0.0721*b
This gives white a Y of 1 and black a Y of 0, so the maximum possible contrast is (1.05/ 0.05) = 21 (within rounding error).
Or let JuicyStudio do the math for you.
This calculation assumes a standard-performing monitor in a relatively dimly lit room (or a room that the user can make dim if she or he has to). That makes it adequate for home or office use, but I don’t know if it’s adequate for mobile apps or other devices that are used outdoors.
Here's some actual (ruby) code that'll actually do the lifting:
rgbval = "8A23C0".hex
r = rgbval >> 16
g = (rgbval & 65280) >> 8
b = rgbval & 255
brightness = r*0.299 + g*0.587 + b*0.114
return (brightness > 160) ? "#000" : "#fff"
You could compute the inverse colour, but you run the risk of contrast diminishing "in the middle" of the colour space.