Skip to content

Commit bf502c6

Browse files
committed
Use the WinUI algorithm for light/dark contrast color switching
1 parent 415a818 commit bf502c6

File tree

1 file changed

+29
-32
lines changed

1 file changed

+29
-32
lines changed

Microsoft.Toolkit.Uwp.UI.Controls/ColorPicker/ContrastBrushConverter.cs

Lines changed: 29 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -63,15 +63,13 @@ public object Convert(
6363
else
6464
{
6565
// Chose a white/black brush based on contrast to the base color
66-
if (this.GetBrightness(comparisonColor) > 0.5)
66+
if (this.UseLightContrastColor(comparisonColor))
6767
{
68-
// Bright color, use a dark for contrast
69-
return new SolidColorBrush(Colors.Black);
68+
return new SolidColorBrush(Colors.White);
7069
}
7170
else
7271
{
73-
// Dark color, use a light for contrast
74-
return new SolidColorBrush(Colors.White);
72+
return new SolidColorBrush(Colors.Black);
7573
}
7674
}
7775
}
@@ -87,37 +85,36 @@ public object ConvertBack(
8785
}
8886

8987
/// <summary>
90-
/// Gets the perceived brightness or intensity of the color.
91-
/// This value is normalized between zero (black) and one (white).
88+
/// Determines whether a light or dark contrast color should be used with the given displayed color.
9289
/// </summary>
9390
/// <remarks>
94-
///
95-
/// The base formula for luminance is from Rec. ITU-R BT.601-7 ():
96-
/// https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.601-7-201103-I!!PDF-E.pdf
97-
/// Section 2.5.1 Construction of luminance (EY) and colour-difference (ER–EY) and (EB–EY) signals.
98-
///
99-
/// This formula accounts for physiological aspects: the human eyeball is most sensitive to green light,
100-
/// less to red and least to blue.
101-
///
102-
/// Luminance = (0.299 * Red) + (0.587 * Green) + (0.114 * Blue)
103-
///
104-
/// This formula is also recommended by the W3C Techniques For Accessibility Evaluation And Repair Tools
105-
/// https://www.w3.org/TR/AERT/#color-contrast
106-
///
107-
/// Contrary to the above formula, this is not called luminance and is called brightness instead.
108-
/// This value is not measurable and is subjective which better fits the definition of brightness:
109-
/// - Luminance is the luminous intensity, projected on a given area and direction.
110-
/// Luminance is an objectively measurable attribute. The unit is 'Candela per Square Meter' (cd/m2).
111-
/// - Brightness is a subjective attribute of light. The monitor can be adjusted to a level of light
112-
/// between very dim and very bright. Brightness is perceived and cannot be measured objectively.
113-
///
114-
/// Other useful information can be found here:
115-
/// http://www.nbdtech.com/Blog/archive/2008/04/27/Calculating-the-Perceived-Brightness-of-a-Color.aspx
116-
///
91+
/// This code is using the WinUI algorithm.
11792
/// </remarks>
118-
private double GetBrightness(Color color)
93+
private bool UseLightContrastColor(Color displayedColor)
11994
{
120-
return ((0.299 * color.R) + (0.587 * color.G) + (0.114 * color.B)) / 255;
95+
// The selection ellipse should be light if and only if the chosen color
96+
// contrasts more with black than it does with white.
97+
// To find how much something contrasts with white, we use the equation
98+
// for relative luminance, which is given by
99+
//
100+
// L = 0.2126 * Rg + 0.7152 * Gg + 0.0722 * Bg
101+
//
102+
// where Xg = { X/3294 if X <= 10, (R/269 + 0.0513)^2.4 otherwise }
103+
//
104+
// If L is closer to 1, then the color is closer to white; if it is closer to 0,
105+
// then the color is closer to black. This is based on the fact that the human
106+
// eye perceives green to be much brighter than red, which in turn is perceived to be
107+
// brighter than blue.
108+
//
109+
// If the third dimension is value, then we won't be updating the spectrum's displayed colors,
110+
// so in that case we should use a value of 1 when considering the backdrop
111+
// for the selection ellipse.
112+
113+
double rg = displayedColor.R <= 10 ? displayedColor.R / 3294.0 : Math.Pow((displayedColor.R / 269.0) + 0.0513, 2.4);
114+
double gg = displayedColor.G <= 10 ? displayedColor.G / 3294.0 : Math.Pow((displayedColor.G / 269.0) + 0.0513, 2.4);
115+
double bg = displayedColor.B <= 10 ? displayedColor.B / 3294.0 : Math.Pow((displayedColor.B / 269.0) + 0.0513, 2.4);
116+
117+
return (0.2126 * rg) + (0.7152 * gg) + (0.0722 * bg) <= 0.5;
121118
}
122119
}
123120
}

0 commit comments

Comments
 (0)