Сделать цвет переднего плана черным или белым в зависимости от фона - PullRequest
34 голосов
/ 11 февраля 2010

Что-то вроде расчета среднего значения компонентов rgb и затем принятия решения, использовать ли черный или белый?

Нужно ли конвертировать RGB в HSV на первом этапе, потому что RGB не всегда то, что видят человеческие глаза?

Я использую C #

Ответы [ 5 ]

66 голосов
/ 11 февраля 2010

Так получилось, что недавно мне понадобилась эта функция для проекта.

private int PerceivedBrightness(Color c)
{
    return (int)Math.Sqrt(
    c.R * c.R * .241 +
    c.G * c.G * .691 +
    c.B * c.B * .068);
}

Эта формула, которую я нашел в Интернете на Nbd Tech , касалась воспринимаемых цветов и формулы преобразования цветов. Сайт дает много полезной информации.

Вот как использовать это, чтобы выбрать черный или белый:

var foreColor = (PerceivedBrightness(backColor) > 130 ? Color.Black : Color.White);

Вы можете использовать значение, отличное от 130, в качестве отсечки; это предпочтение.

<ч />

Обновление: По словам Дарела Рекса Финли на его сайт :

Значения, которые я придумал, играя в Photoshop, на самом деле были .241, .691 и .068, но с тех пор мне сообщили, что значения .299, .587 и .114 более точные.

Данная спецификация следует Рекомендации МСЭ-R BT.601 (или для краткости Рекомендация 601). Сайт, о котором я упоминал выше, Nbd Tech , еще не обновлялся для отражения этого.

Исходя из этого, вот обновленный метод (спасибо DTI-Matt за комментарий) :

private int PerceivedBrightness(Color c)
{
    return (int)Math.Sqrt(
    c.R * c.R * .299 +
    c.G * c.G * .587 +
    c.B * c.B * .114);
}

Примечание о предпочтении порога:

Цвета с воспринимаемой яркостью вблизи середины (например, 120-140) будут более субъективными. Например, это спорно ли красные (FF0000), который оценивает до 139, понятнее с черным или белой накладкой.

White and Black on Red

6 голосов
/ 11 февраля 2010

что насчет этого?

private static Color GetReadableForeColor(Color c)
{
    return (((c.R + c.B + c.G) / 3) > 128) ? Color.Black : Color.White;
}
5 голосов
/ 25 февраля 2010

Структура Color изначально поддерживает преобразование в HSB.

if (Color.GetBrightness() > 0.5f) {
  // win
}

Возможно, вы также захотите добавить компонент насыщенности, учитывая, что насыщение также вносит вклад в кажущуюся «легкость».

0 голосов
/ 11 февраля 2010

Если я правильно понимаю, один из подходов может заключаться в том, чтобы заполучить изображение рабочего стола, проверить в каком-нибудь поместье его цвет, а затем изменить цвет приложения на его основе.

На geekpedia есть статья *1004* о том, как получить текущие обои для рабочего стола (и множество обращений к Google), но основная предпосылка заключается в получении значения реестра текущих обоев:

RegistryKey rkWallPaper = Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop", false);
string WallpaperPath = rkWallPaper.GetValue("WallPaper").ToString();

Вы можете использовать этот путь, чтобы открыть изображение. После этого вы можете получить множество свойств, таких как размеры и цвета отдельных пикселей в RGB.

Чтобы определить, «белый» или «черный», у вас есть много вариантов.

Одной из идей было бы получить цвет каждого пикселя в RGB, усреднить значения (чтобы получить значение в оттенках серого), а затем усреднить значение в оттенках серого для каждого пикселя по изображению. Если получится> 128, тогда можно будет считать «белым». Если <128, то «черный». По сути, вы решаете, с какой стороны от средней серой разделительной линии интенсивность пикселей изображения усредняется. </p>

// Psudo code - can't check the C# spec atm.
foreach(Pixel p in image)
{
    // get average of colour components.
    double greyScale = (p.Red + p.Green + p.Blue) / 3;
    totalIntensity += greyScale;
}

double averageImageIntensity = totalIntensity / image.NumPixels;

if(totalIntensity > 128) // image could be considered to be "white"
else // image could be considered "black".

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

Лично я бы предложил просто предоставить пользователю выбор цвета / темы / кожи, или, что еще лучше, позволить ему настроить его!

0 голосов
/ 11 февраля 2010

Вы можете сделать простой расчет в зависимости от глубины цвета, если, скажем, у вас есть цветовой формат #FFFFFF, вы можете просто добавить значения RGB и рассчитать, если они находятся на полпути.

Максимум в этом случае составляет 255 (F x F = 256) на каждый, поэтому просто проверьте, находится ли он ниже этого порога:

var colorCode = ((R + B + G) < 255*3) ? "#FFFFFF" : "#000000";

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

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