Ответ 1
как насчет этого?
private static Color GetReadableForeColor(Color c)
{
return (((c.R + c.B + c.G) / 3) > 128) ? Color.Black : Color.White;
}
Что-то вроде вычисления среднего значения компонентов rgb, а затем решить, следует ли использовать черный или белый?
Нужно ли мне преобразовывать RGB в HSV на первом шаге, потому что RGB не всегда выглядит тем, что видят человеческие глаза?
Я использую С#
как насчет этого?
private static Color GetReadableForeColor(Color c)
{
return (((c.R + c.B + c.G) / 3) > 128) ? Color.Black : Color.White;
}
Так получилось, что мне недавно понадобилась эта функция для проекта.
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, с черным или белым наложением.
Структура Color
поддерживает преобразование в HSB изначально.
if (Color.GetBrightness() > 0.5f) {
// win
}
Возможно, вы захотите также добавить компонент насыщения, учитывая, что насыщение также способствует очевидной "легкости".
Вы можете сделать простой расчет в зависимости от глубины цвета, если у вас есть цветной формат #FFFFFF, вы можете просто добавить значения RGB и рассчитать, находятся ли они на полпути.
Максимальный размер в этом случае равен 255 (F x F = 256), поэтому просто проверьте, находится ли он под этим порогом:
var colorCode = ((R + B + G) < 255*3) ? "#FFFFFF" : "#000000";
Если цвет ниже, он темнее... используется на белом фоне. Если он выше, он светлее... используйте черный фон. Это не идеально, но идея для начала.
Если я правильно понимаю, один подход может состоять в том, чтобы получить изображение рабочего стола на рабочем столе, проверить в какой-то усадьбе, какой цвет, а затем изменить цвет вашего приложения на основе этого.
Там есть статья на 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".
Проблемы: может быть медленной процедурой, вы можете захотеть отобрать только некоторые пиксели (скажем, каждый десятый и т.д.), чтобы сэкономить время. В более общем смысле, это похоже на довольно хакерскую штуку. Вытягивание пользовательских файлов во время работы и беспорядок с ними едва ли чист, и это обеспечивает потенциальную безопасность и стабильность. Что делать, если изображение искажено или повреждено и т.д.
Лично я бы предложил просто дать пользователю выбор цвета/темы/кожи, или, тем более, пусть он их настраивает!