【问题标题】:Given a background color, how to get a foreground color that makes it readable on that background color?给定背景颜色,如何获得使其在该背景颜色上可读的前景色?
【发布时间】:2011-03-08 04:08:54
【问题描述】:

给定背景色,如何获得使其在该背景色上可读的前景色?

我的意思是在程序中自动计算前景色。

或者简化问题,如果前景色从白/黑中选择,在程序中如何选择?

【问题讨论】:

标签: user-interface colors


【解决方案1】:

根据上面的答案,我想出了一个 C# 实现,您可能希望根据您的要求调整 alpha 的逻辑。

public static class ColorExtension
{
    public static Color GetReadableColor(this Color color) => color.GetLuminance() > 140 || color.A != 255 ? Color.Black : Color.White;
    public static double GetLuminance(this Color color) => (0.2126 * color.R) + (0.7151 * color.G) + (0.0721 * color.B);
}

【讨论】:

    【解决方案2】:

    PyQt5 版本 Michael Zuschlag 的回答:

    import sys
    from PyQt5.QtGui import QColor
    class MostReadableColor():
        def getLuminance(self, color):
        """ get color luminance.
        
        Convert color RGB values to gamma adjusted normalized rgb values
        then combine them using sRGB constants (rounded to 4 places).
        """
            r, g, b, a = QColor(color).getRgb()
            l = ((r/255)**2.2)*0.2126 + ((g/255)**2.2)*0.7151 + \
                ((b/255)**2.2)*0.0721
            return(l)
    
        def getContrastRation(self, color1, color2):
            l1 = self.getLuminance(color1)
            l2 = self.getLuminance(color2)
            cr = (l1 + .05)/(l2+.05) if l1 > l2 else (l2+.05)/(l1 + .05)
            return(cr)
         
        def getMostReadable(self, color):
            cr = []
            for c in QColor.colorNames():
                if c == 'transparent':
                    continue
                cr.append([self.getContrastRation(color, c), c])
            sorted_cr = sorted(cr, reverse=True)  
            return(sorted_cr[0][1])    
        
    def main():
        if len(sys.argv) != 2:
            print("usage: MostReadableColor color_name (ex: 'red')")
        else:   
            mrc = MostReadableColor()
            best_contrast_color = mrc.getMostReadable(sys.argv[1])
            print(f"{best_contrast_color}")
        
    if __name__ == "__main__":
        main()
    

    【讨论】:

      【解决方案3】:

      Pascal / Delphi 版本:

      var
        red,green,blue : Integer;
        luminance : double;
      
      // convert hexa-decimal values to RGB
      red := (_BackgroundColor) and $FF;
      green := (_BackgroundColor shr 8) and $FF;
      blue := (_BackgroundColor shr 16) and $FF;
      
      luminance := (0.2126 * red) + (0.7152 * green) + (0.0722 * blue);
      
      if luminance < 140 then
        Result := TColors.White
      else
        Result := TColors.Black;
      

      【讨论】:

        【解决方案4】:

        如果这仍然对某人有用,这是基于上述答案的 Dart 实现

        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);
        }
        

        【讨论】:

          【解决方案5】:

          这是我在 Java 和 Javascript 中都做过的一个。它松散地基于this javascript 中的一个。我从here 中获取了亮度公式。我眼中的阈值甜蜜点约为 140。

          Java 版本:

          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 版本:

          在 javascript 中,前端的东西也是一样的。 RGB转换取自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";
          }
          

          【讨论】:

          • 谢谢,正是我需要的。其他问题中的另一种解决方案和这个问题的公认答案,在计算光度之前对 rgb 进行归一化对我不起作用,但这是完美的。
          • 感谢您提供即用型代码!欣赏!
          【解决方案6】:

          这里有一些实际的 (ruby) 代码可以真正完成提升:

          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"
          

          【讨论】:

            【解决方案7】:

            最安全的选择是遵守万维网联盟 (W3C) 的 Web 内容可访问性指南 2.0,该指南指定了亮度 contrast ratio of 4.5:1 for regular text (12 pt or smaller), and 3.0:1 for large text。对比度定义为:

            [Y(b) + 0.05] / [Y(d) + 0.05]

            其中 Y(b) 是较亮颜色的亮度(亮度),Y(d) 是较暗颜色的亮度。

            您首先将每种颜色的 RGB 值转换为经过伽马调整的归一化 rgb 值,从而计算亮度 Y:

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

            然后使用 sRGB 常量组合它们(四舍五入):

            Y = 0.2126*r + 0.7151*g + 0.0721*b

            这使白色的 Y 为 1,黑色的 Y 为 0,因此可能的最大对比度为 (1.05/ 0.05) = 21(在舍入误差内)。

            或者let JuicyStudio do the math给你。

            此计算假设在相对昏暗的房间(或用户可以根据需要调暗的房间)中的标准性能监视器。这足以满足家庭或办公室使用,但我不知道它是否适合移动应用程序或其他户外使用的设备。

            【讨论】:

              【解决方案8】:

              您可以计算反色,但您会冒着在颜色空间的“中间”降低对比度的风险。

              【讨论】:

                【解决方案9】:
                • 计算亮度(参见HSL
                • 如果亮度低于 50%,请使用白色。否则,请使用黑色。

                使用颜色作为前景色很困难,因为您必须考虑对比度和色盲。

                【讨论】:

                • 我看了一些rgb_to_hsl的sn-p代码,亮度是用MAX(r, g, b)/255计算的,好像还不够选择。
                • 太棒了。 d3.rgb().hsl 很简单
                猜你喜欢
                • 2019-09-29
                • 1970-01-01
                • 2013-01-06
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2016-04-07
                • 1970-01-01
                相关资源
                最近更新 更多