Сделайте цвет переднего плана черным или белым в зависимости от фона

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

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

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

Ответ 1

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

private static Color GetReadableForeColor(Color c)
{
    return (((c.R + c.B + c.G) / 3) > 128) ? Color.Black : Color.White;
}

Ответ 2

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

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; это предпочтение.


Обновление:. Согласно Darel Rex Finley на его сайт:

Значения, которые я придумал, играя с 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, с черным или белым наложением.

Белый и черный на красном

Ответ 3

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

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

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

Ответ 4

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

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

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

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

Ответ 5

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

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

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

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

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

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

// 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".

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

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