Обратные противоположные цвета - PullRequest
16 голосов
/ 12 января 2011

У меня есть пользовательские настройки, где они могут выбирать цвета предупреждений. Оповещение - это цвет фона текста или кнопки. Но проблема в том, что если они выбирают темно-синий цвет, а у нас черные буквы, то контраста недостаточно, и вы не можете его прочитать.

Я пытался создать функцию, чтобы получить противоположный цвет, но не зашел слишком далеко.

Есть ли такая функция?

Ответы [ 9 ]

23 голосов
/ 23 октября 2012

Я обнаружил, что лучшим решением для меня является преобразование значений 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) пропорциональны чувствительности глаз (или, скорее, чувствительности сетчатки) к соответствующему цвету.

23 голосов
/ 12 января 2011

Использование дополнительный цвет :

Алго прост, вычтите каждый компонент цвета из 255 для получения новых компонентов цвета

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

----- EDIT (поскольку дополнение на основе RGB может работать не всегда --------

Эти две ссылки очень полезны и по теме:

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

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

8 голосов
/ 15 декабря 2014

Основываясь на решении 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);
}
2 голосов
/ 06 декабря 2015

целочисленное решение:

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;
    }
2 голосов
/ 12 января 2011

Я получил это работает, я думаю:)

Вот функция:

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


}
1 голос
/ 18 января 2019

Небольшая модификация ответа Саймонса

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 ] );
1 голос
/ 12 января 2011

Должен ли текст быть цветом, полученным из цвета фона?Что если он просто чередуется между белым и черным в зависимости от интенсивности RGB?Идея в том, что белый всегда будет виден на значениях rgb ниже определенной интенсивности, а черный - на остальных.

У меня нет рабочего алгоритма, которым можно поделиться, но вы можете попробовать что-то вроде:

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

Возможно, вам придется немного поиграться с порогом, чтобы получить что-то красивое.Вы также можете немного подкрасить шрифт, основываясь на том, какое значение rgb является доминирующим.

0 голосов
/ 20 сентября 2018
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

0 голосов
/ 12 января 2011

Вы можете рассчитать разницу между каждым цветным каналом (красным, зеленым и синим) и получить среднюю разницу, а затем провести некоторое сравнение на основе этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...