【问题标题】:Reverse opposing colors反转相反的颜色
【发布时间】:2011-06-08 00:29:50
【问题描述】:

我有一个用户设置,他们可以在其中选择警报的颜色。警报是文本或按钮的背景颜色。但问题在于,如果他们选择深蓝色而我们有黑色字母,则对比度不够,您无法阅读。

我试图创建一个函数来获得相反的颜色,但还没有走得太远。

有这样的功能吗?

【问题讨论】:

标签: java android colors


【解决方案1】:

另一种将颜色转换为整数格式的通用解决方案是:

private int getComplementaryColor( int color) {
    int R = color & 255;
    int G = (color >> 8) & 255;
    int B = (color >> 16) & 255;
    int A = (color >> 24) & 255;
    R = 255 - R;
    G = 255 - G;
    B = 255 - B;
    return R + (G << 8) + ( B << 16) + ( A << 24);
}

【讨论】:

    【解决方案2】:

    正如 Sarwar Erfan 指出的那样,使用互补色。为此,您可以使用整数掩码(这会比分别反转 R、G、B 颜色分量更快)。

    int textColor = bgColor ^ 0x00ffffff;
    

    【讨论】:

      【解决方案3】:

      ColorUtils.calculateLuminance(int color) 可用于确定给定背景颜色是使用深色还是明亮的文本颜色。

      示例:

      if (ColorUtils.calculateLuminance(backgroundColor) <= 0.5) textColor = <bright>
      else textColor = <dark>
      

      可以通过实验选择阈值(本例中为0.5)以获得最佳视觉效果。

      Documentation

      【讨论】:

        【解决方案4】:

        对西蒙斯的回答稍作修改

        float[] hsv = new float[3];
        java.awt.Color.RGBtoHSB( bgColour.getRed(), bgColour.getGreen(), bgColour.getBlue(), hsv );
        hsv[2] = (hsv[2] + 180) % 360;
        java.awt.Color   invertedColour = java.awt.Color.getHSBColor( hsv[ 0 ], hsv[ 1 ], hsv[ 2 ] );
        

        【讨论】:

          【解决方案5】:
          import android.graphics.Color;
          import android.graphics.Paint;
          
          /**
           * Utilities for performing common color-related tasks.
           * @author Ryan Ware
           *
           */
          public class ColorUtils {
          
            public static int getComplimentColor(Paint paint) {
              return getComplimentColor(paint.getColor());
            }
          
            /**
             * Returns the complimentary (opposite) color.
             * @param color int RGB color to return the compliment of
             * @return int RGB of compliment color
             */
            public static int getComplimentColor(int color) {
              // get existing colors
              int alpha = Color.alpha(color);
              int red = Color.red(color);
              int blue = Color.blue(color);
              int green = Color.green(color);
          
              // find compliments
              red = (~red) & 0xff;
              blue = (~blue) & 0xff;
              green = (~green) & 0xff;
          
              return Color.argb(alpha, red, green, blue);
            }
          
            /**
             * Converts an int RGB color representation into a hexadecimal {@link String}.
             * @param argbColor int RGB color
             * @return {@link String} hexadecimal color representation
             */
            public static String getHexStringForARGB(int argbColor) {
              String hexString = "#";
              hexString += ARGBToHex(Color.alpha(argbColor));
              hexString += ARGBToHex(Color.red(argbColor));
              hexString += ARGBToHex(Color.green(argbColor));
              hexString += ARGBToHex(Color.blue(argbColor));
          
              return hexString;
            }
          
            /**
             * Converts an int R, G, or B value into a hexadecimal {@link String}.
             * @param rgbVal int R, G, or B value
             * @return {@link String} hexadecimal value
             */
            private static String ARGBToHex(int rgbVal) {
              String hexReference = "0123456789ABCDEF";
          
              rgbVal = Math.max(0,rgbVal);
              rgbVal = Math.min(rgbVal,255);
              rgbVal = Math.round(rgbVal);
          
              return String.valueOf( hexReference.charAt((rgbVal-rgbVal%16)/16) + "" + hexReference.charAt(rgbVal%16) );
            }
          }
          

          感谢:http://www.java2s.com/Code/Android/2D-Graphics/Returnsthecomplimentaryoppositecolor.htm

          【讨论】:

            【解决方案6】:

            整数解:

            public static int getContrastColor(int color) {
                    double y = (299 * Color.red(color) + 587 * Color.green(color) + 114 * Color.blue(color)) / 1000;
                    return y >= 128 ? Color.BLACK : Color.WHITE;
                }
            

            【讨论】:

            • 你能解释一下它是如何解决这个问题的吗?
            • "我试图创建一个函数来获得相反的颜色,但还没有走得太远。"所以这是一个函数 ^^ 它返回黑色或白色。
            • 回到第一个问题..如果它不能解决问题..然后删除它..或者用最新发现更新问题。
            • @brimborium 在你之前 3 年就已经发布了一个极其相似的回复。
            【解决方案7】:

            我建议基于 Marks 解决方案:

            public static int getComplementaryColor(int colorToInvert) {
                float[] hsv = new float[3];
                Color.RGBToHSV(Color.red(colorToInvert), Color.green(colorToInvert),
                        Color.blue(colorToInvert), hsv);
                hsv[0] = (hsv[0] + 180) % 360;
                return Color.HSVToColor(hsv);
            }
            

            此外,我现在创建了一个类似的方法,用于计算给定颜色的默认背景:

            public static int getContrastVersionForColor(int color) {
                float[] hsv = new float[3];
                Color.RGBToHSV(Color.red(color), Color.green(color), Color.blue(color),
                        hsv);
                if (hsv[2] < 0.5) {
                    hsv[2] = 0.7f;
                } else {
                    hsv[2] = 0.3f;
                }
                hsv[1] = hsv[1] * 0.2f;
                return Color.HSVToColor(hsv);
            }
            

            【讨论】:

            • getComplementaryColor 工作正常但不是 getContrastVersionForColor 你能解决吗?
            • 不起作用是什么意思?你不喜欢这个结果?您能否提供一个看起来不正确的颜色 int 值?我经常使用它,从来没有遇到过问题
            • 我非常喜欢这个解决方案。如果您不喜欢黑白 YIQ 方法,这是一个完美的选择。
            【解决方案8】:

            我发现对我来说最好的解决方案是将 RGB 值转换为 YIQ 值。由于我们只对亮度值(由 Y 表示)感兴趣,因此只需进行一项计算:Y = (299*R + 587*G + 114*B)/1000。 Java 代码如下所示:

            public static Color getContrastColor(Color color) {
              double y = (299 * color.getRed() + 587 * color.getGreen() + 114 * color.getBlue()) / 1000;
              return y >= 128 ? Color.black : Color.white;
            }
            

            您可以看到它只是根据原始颜色的亮度决定使用黑色还是白色。在我看来,结果非常好。权重 (299, 587, 114) 与眼睛对相应颜色的敏感度(或者更确切地说是视网膜的敏感度)成正比。

            【讨论】:

            • 谢谢。这可能无法涵盖所有​​情况,但非常适合我的用例(使文本在彩色背景上可读)
            • 你总是可以很好地阅读文本。缺点是文字会是黑色或白色,背景的颜色信息会“丢失”。
            • 在 JavaFx 中,y 值将介于 0 和 1 之间。所以此方法的最后一行应如下所示 return y &gt;= 0.5 ? Color.valueOf("#000000") : Color.valueOf("#ffffff");
            【解决方案9】:

            我觉得我成功了 :)

            函数如下:

            public static int OpposeColor(int ColorToInvert)
            {
                 int RGBMAX = 255;
            
                 float[] hsv = new float[3];
                 float H;
            
                 Log.i("HSV_H", "Start Color=" +  ColorToInvert);
            
                 Color.RGBToHSV( Color.red( ColorToInvert),  RGBMAX - Color.green( ColorToInvert), Color.blue(ColorToInvert), hsv);
            
                 Log.i("HSV_H", "Hue=" + hsv[0]);
                 Log.i("HSV_H", "Saturation=" + hsv[1]);
                 Log.i("HSV_H", "Value=" + hsv[2]);
            
                H = (float) (hsv[0] + 0.5);
            
                if (H > 1) H -= 1;
            
                Log.i("HSV_H", "Hue2=" + H);         
            
                Log.i("HSV_H", "Color=" +  Color.HSVToColor(hsv ));
            
                return Color.HSVToColor(hsv );
            
            
            }
            

            【讨论】:

            • 为什么是“RGBMAX -”?并且色调是 0 和 360 之间的值,而不是 0 和 1 我认为,我在下面发布了一个更新版本
            【解决方案10】:

            使用complementary color:

            算法很简单,从255中减去每个颜色分量得到新的颜色分量

            Color textColor = Color.rgb(255-Color.red(bgColor),
                                     255-Color.green(bgColor),
                                     255-Color.blue(bgColor));
            

            ----- 编辑(因为基于 RGB 的补码可能并不总是有效 --------

            这两个链接非常有帮助,而且很切题:

            http://www.splitbrain.org/blog/2008-09/18-calculating_color_contrast_with_php

            http://24ways.org/2010/calculating-color-contrast

            【讨论】:

            • 当用户选择颜色 128/128/128(或非常接近的颜色)时,这不是一个大问题吗。
            • 我在答案中包含了来自维基百科的链接。基于 RGB 的补码最容易理解。在这种情况下,基于 HSV 的补体将起作用。 @Shynhriir:是的.. 基于 RGB 的补码在这个范围内不起作用,你是绝对正确的
            • 如何将 Wiki 链接中的补色编码到 Android 中?
            • @Mark:这不是很难。之前写过自己的3d透视变换代码只是看了对应的理论。
            • 如果您是 Java 和 Android 新手,那就是 :) 不过我明白了...见上文
            【解决方案11】:

            文本是否必须是从背景颜色派生的颜色?如果它只是根据 r g b 强度在白色和黑色之间交替呢?这个想法是白色总是在低于一定强度的 r g b 值上可见,而黑色总是在其余部分可见。

            我没有可以分享的有效算法,但您可以尝试以下方式:

            int threshold = 50;
            if(r < threshold && g < threshold && b < threshold) {
              // set your font color to white
            } else {
              // set your font color to black
            }
            

            您可能需要稍微调整一下阈值才能获得好看的东西。您还可以根据 r g b 值占主导地位对字体进行一点着色。

            【讨论】:

              【解决方案12】:

              您可以计算每个颜色通道(红色、绿色和蓝色)之间的差异,并获得平均差异 - 然后在此基础上进行一些比较。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2013-07-24
                • 1970-01-01
                • 2021-09-23
                • 2011-06-05
                • 2013-06-26
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多