Android / Java: определение, будет ли цвет текста сливаться с фоном? - PullRequest
6 голосов
/ 16 октября 2011

Я внедряю функцию «тегирования» в своем приложении, и один из способов, позволяющих отображать теги, состоит в том, чтобы установить для текста цвет, выбранный пользователем для каждого. Мое приложение имеет три темы с фонами: белый, черный и блокнот, как коричневый (они могут измениться / расти в будущем). Я хочу иметь возможность отображать тег в его родном цвете, если он легко контрастирует с фоном, и просто использовать цвет текста по умолчанию для каждой темы.

Я написал вспомогательную функцию, которая поможет мне определить, будет ли текст замаскирован, но он не на 100% корректен (я хочу, чтобы он определил, будут ли маскироваться цвета на основе всех трех компонентов hsv, и сейчас сравнение насыщенности недопустимо). Код ниже.

    public static boolean colorWillBeMasked(int color, Application app){

      float[] hsv = new float[3];
      Color.colorToHSV(color, hsv);
      //note 0, black 1, white 2
      int theme = app.api.getThemeView();
      System.out.println("h=" +hsv[0]+ ", s=" +hsv[1]+ ", v=" +hsv[2]+", theme="+theme);

      if(android.R.color.transparent == color) return true;
      // color is dark
      if(hsv[2] <= .2){
          if(theme == 1) return true;
      }
      // color is light
      else if(hsv[2] >= .8) {
          if(theme == 2) return true;
      }
      return false;
   }

При вызове этой функции с синим, красным, прозрачным, черным, желтым и зеленым цветом результат будет следующим (соответственно):

  • ч = 0,0, с = 1,0, v = 1,0, тема = 1
  • ч = 229,41177, с = 1,0, v = 1,0, тема = 1
  • h = 267,6923, s = 1,0, v = 0,050980393, тема = 1
  • h = 0,0, s = 0,0, v = 0,0, тема = 1
  • ч = 59,52941, с = 1,0, v = 1,0, тема = 1
  • ч = 111,29411, с = 1,0, v = 1,0, тема = 1

Мой вопрос: на основе оттенка, насыщенности и значения, как вы можете определить, будет ли текст, окрашенный определенным образом, отображаться на белом фоне по сравнению с черным фоном или будет ли он замаскирован? Пожалуйста, возьмите мой алгоритм и улучшите его или помогите мне создать новый.

Заранее спасибо.

1 Ответ

4 голосов
/ 17 сентября 2014

Решение, которое я придумал:

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

public static boolean colorWillBeMasked(int color, Application app){
    if(android.R.color.transparent == color) return true;

    int[] rgb = {Color.red(color), Color.green(color), Color.blue(color)};

    int brightness =
        (int)Math.sqrt(
              rgb[0] * rgb[0] * .241 + 
              rgb[1] * rgb[1] * .691 + 
              rgb[2] * rgb[2] * .068);

    System.out.println("COLOR: " + color + ", BRIGHT: " + brightness);
    //note 0,black 1,classic 2
    int theme = app.api.getThemeView();

    // color is dark
    if(brightness <= 40){
        if(theme == 1) return true;
    }
    // color is light
    else if (brightness >= 215){
        if(theme == 2) return true;
    }
    return false;
}
...