[英]From a list of colors, how can I get a light or dark color that is visible over each color simultaneously?
在我的應用程序中,我允許用戶最多選擇三種顏色用作“主題顏色”。 這些顏色在狀態欄下顯示為LinearGradientBrush
(如果選擇一種顏色,則顯示為SolidColorBrush
)。 我需要狀態欄前景色為淺色或深色(不一定只有黑色或白色)。 這將比僅確定應使用白色還是黑色要復雜得多,但是要包括深灰色(例如,如果用戶選擇主題使用白色和黑色,即是我目前的算法選擇黑色作為前景,這是不可見的)之類的顏色。他們選擇的黑色)。 另外, StatusBar.ForegroundColor
忽略Alpha通道,因此我不能只更改不透明度。 我怎樣才能做到這一點?
謝謝
對比色可以通過HSB顏色的反色來確定
僅適用於黑白,您可以使用
ForeColor = BackColor.GetBrightness() > 0.4 ? Color.Black : Color.White;
您可以根據顏色的R,G和B值計算顏色的亮度,然后根據該值選擇畫筆。 我使用以下轉換器選擇與綁定的背景色形成對比的前景色。
public class ColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
Color c = (Color)value;
int brightness = (int)(c.R * 0.30 + c.G * 0.59 + c.B * 0.11);
if (brightness < 127)
return App.Current.Resources["LightBrush"];
else
return App.Current.Resources["DarkBrush"];
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
我將其用於綁定到Colors類中所有已命名顏色的顏色選擇器。 如果您僅針對幾種主題色,則可以手工制作一張仍保持對比度的有色表,而不是將所有內容強制設置為黑白。
對於更多顏色,您可以嘗試從RGB轉換為HSL,在保持色相的同時修改亮度,然后再轉換回去,但這可能比它值得的麻煩更多,並且在往返旅行時可能會用盡色域並獲得較差的結果。
我玩了一些游戲,我認為我有一個完美的方法。 我從這個問題開始使用一種算法,然后將其與Matt Lacey和Rob Caplan的答案中的類似代碼混合,將其清理並修改為可使用的顏色列表。 我認為效果很好。
private static Color DetermineForegroundColor(List<Color> colors) {
double r = 0, g = 0, b = 0;
foreach (Color color in colors) {
r += color.R;
g += color.G;
b += color.B;
}
if (r > g && r > b) {
Debug.WriteLine("First condition matched ({0}, {1}, {2})", (byte)r, (byte)g, (byte)b);
return new Color() {
R = (byte)r,
G = (byte)r,
B = (byte)r
};
}
else if (g > r && g > b) {
Debug.WriteLine("Second condition matched ({0}, {1}, {2})", (byte)r, (byte)g, (byte)b);
return new Color() {
R = (byte)g,
G = (byte)g,
B = (byte)g
};
}
else if (b > r && b > g) {
Debug.WriteLine("Third condition matched ({0}, {1}, {2})", (byte)r, (byte)g, (byte)b);
return new Color() {
R = (byte)b,
G = (byte)b,
B = (byte)b
};
}
else if (r == g) {
Debug.WriteLine("Fourth condition matched ({0}, {1}, {2})", (byte)r, (byte)g, (byte)b);
return new Color() {
R = (byte)b,
G = (byte)b,
B = (byte)b
};
}
else if (r == b) {
Debug.WriteLine("Fifth condition matched ({0}, {1}, {2})", (byte)r, (byte)g, (byte)b);
return new Color() {
R = (byte)g,
G = (byte)g,
B = (byte)g
};
}
else if (g == b) {
Debug.WriteLine("Sixth condition matched ({0}, {1}, {2})", (byte)r, (byte)g, (byte)b);
return new Color() {
R = (byte)r,
G = (byte)r,
B = (byte)r
};
}
else {
Debug.WriteLine("No condition matched ({0}, {1}, {2})", (byte)r, (byte)g, (byte)b);
return new Color() {
R = 255,
G = 255,
B = 255
};
}
}
將來,我可能會用switch/case
塊替換較大的if/else-if/else
塊,以減少體積。
嘗試以下任一方法:
要么
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.