Given a background color, how to get a foreground color that makes it readable on that background color?

后端 未结 6 690
有刺的猬
有刺的猬 2020-12-02 13:41

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

相关标签:
6条回答
  • 2020-12-02 14:02

    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";
    }
    
    0 讨论(0)
  • 2020-12-02 14:08
    • Calculate the lightness (see HSL)
    • If the lightness is less than 50%, use white. Otherwise, use black.

    Using colors as foreground color is difficult, because you have to take contrast and color blindness into account.

    0 讨论(0)
  • 2020-12-02 14:11

    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);
    }
    
    0 讨论(0)
  • 2020-12-02 14:14

    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:

    • r = (R/255)^2.2
    • b = (B/255)^2.2
    • g = (G/255)^2.2

    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.

    0 讨论(0)
  • 2020-12-02 14:18

    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"
    
    0 讨论(0)
  • 2020-12-02 14:21

    You could compute the inverse colour, but you run the risk of contrast diminishing "in the middle" of the colour space.

    0 讨论(0)
提交回复
热议问题