diff --git a/components/ColorAnalyzer/samples/AccentAnalyzer.md b/components/ColorAnalyzer/samples/AccentAnalyzer.md
deleted file mode 100644
index 29591e7b1..000000000
--- a/components/ColorAnalyzer/samples/AccentAnalyzer.md
+++ /dev/null
@@ -1,21 +0,0 @@
----
-title: AccentAnalyzer Helper
-author: Avid29
-description: A tool for extracting colors from an image
-keywords: Accents, Color, Helpers
-dev_langs:
- - csharp
-category: Helpers
-subcategory: Miscellaneous
-discussion-id: 254
-issue-id: 0
-icon: assets/icon.png
----
-
-# AccentAnalyzer
-
-The AccentAnalyzer provides a pure XAML way to use the colors extracted from an image as a binding source for any `Color` property.
-
-> [!Sample AccentAnalyzerSample]
-
-> [!Sample ContrastHelperSample]
diff --git a/components/ColorAnalyzer/samples/ColorAnalyzer.Samples.csproj b/components/ColorAnalyzer/samples/ColorAnalyzer.Samples.csproj
index 724def1ee..57dfffe41 100644
--- a/components/ColorAnalyzer/samples/ColorAnalyzer.Samples.csproj
+++ b/components/ColorAnalyzer/samples/ColorAnalyzer.Samples.csproj
@@ -18,7 +18,4 @@
PreserveNewest
-
-
-
diff --git a/components/ColorAnalyzer/samples/ColorPaletteSampler/AccentAnalyzerSample.xaml b/components/ColorAnalyzer/samples/ColorPaletteSampler/AccentAnalyzerSample.xaml
deleted file mode 100644
index 2b7f841c0..000000000
--- a/components/ColorAnalyzer/samples/ColorPaletteSampler/AccentAnalyzerSample.xaml
+++ /dev/null
@@ -1,146 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/components/ColorAnalyzer/samples/ColorPaletteSampler/AccentColorSample.xaml b/components/ColorAnalyzer/samples/ColorPaletteSampler/AccentColorSample.xaml
new file mode 100644
index 000000000..5ae519283
--- /dev/null
+++ b/components/ColorAnalyzer/samples/ColorPaletteSampler/AccentColorSample.xaml
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/ColorAnalyzer/samples/ColorPaletteSampler/AccentColorSample.xaml.cs b/components/ColorAnalyzer/samples/ColorPaletteSampler/AccentColorSample.xaml.cs
new file mode 100644
index 000000000..63abce9f6
--- /dev/null
+++ b/components/ColorAnalyzer/samples/ColorPaletteSampler/AccentColorSample.xaml.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace ColorAnalyzerExperiment.Samples;
+
+///
+/// An example sample page of a custom control inheriting from Panel.
+///
+[ToolkitSample(id: nameof(AccentColorSample), "AccentAnalyzer helper", description: $"A sample for showing how the accent analyzer can be used.")]
+public sealed partial class AccentColorSample : ColorPaletteSamplerToolkitSampleBase
+{
+ public AccentColorSample()
+ {
+ this.InitializeComponent();
+ }
+}
diff --git a/components/ColorAnalyzer/samples/ColorPaletteSampler/BaseColorSample.xaml b/components/ColorAnalyzer/samples/ColorPaletteSampler/BaseColorSample.xaml
new file mode 100644
index 000000000..6f37840d8
--- /dev/null
+++ b/components/ColorAnalyzer/samples/ColorPaletteSampler/BaseColorSample.xaml
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/ColorAnalyzer/samples/ColorPaletteSampler/AccentAnalyzerSample.xaml.cs b/components/ColorAnalyzer/samples/ColorPaletteSampler/BaseColorSample.xaml.cs
similarity index 60%
rename from components/ColorAnalyzer/samples/ColorPaletteSampler/AccentAnalyzerSample.xaml.cs
rename to components/ColorAnalyzer/samples/ColorPaletteSampler/BaseColorSample.xaml.cs
index fca29f2c6..68a09e633 100644
--- a/components/ColorAnalyzer/samples/ColorPaletteSampler/AccentAnalyzerSample.xaml.cs
+++ b/components/ColorAnalyzer/samples/ColorPaletteSampler/BaseColorSample.xaml.cs
@@ -7,10 +7,10 @@ namespace ColorAnalyzerExperiment.Samples;
///
/// An example sample page of a custom control inheriting from Panel.
///
-[ToolkitSample(id: nameof(AccentAnalyzerSample), "AccentAnalyzer helper", description: $"A sample for showing how the accent analyzer can be used.")]
-public sealed partial class AccentAnalyzerSample : Page
+[ToolkitSample(id: nameof(BaseColorSample), "AccentAnalyzer helper", description: $"A sample for showing how the accent analyzer can be used.")]
+public sealed partial class BaseColorSample : ColorPaletteSamplerToolkitSampleBase
{
- public AccentAnalyzerSample()
+ public BaseColorSample()
{
this.InitializeComponent();
}
diff --git a/components/ColorAnalyzer/samples/ColorPaletteSampler/ColorPaletteSamplerToolkitSample.cs b/components/ColorAnalyzer/samples/ColorPaletteSampler/ColorPaletteSamplerToolkitSample.cs
new file mode 100644
index 000000000..dbd0d7f74
--- /dev/null
+++ b/components/ColorAnalyzer/samples/ColorPaletteSampler/ColorPaletteSamplerToolkitSample.cs
@@ -0,0 +1,21 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace ColorAnalyzerExperiment.Samples;
+
+public abstract partial class ColorPaletteSamplerToolkitSampleBase : Page
+{
+ public static readonly DependencyProperty SelectedImageProperty =
+ DependencyProperty.Register(nameof(SelectedImage), typeof(ImageSource), typeof(ColorPaletteSamplerToolkitSampleBase), new PropertyMetadata(null));
+
+ public ColorPaletteSamplerToolkitSampleBase()
+ {
+ }
+
+ public ImageSource SelectedImage
+ {
+ get => (ImageSource)GetValue(SelectedImageProperty);
+ set => SetValue(SelectedImageProperty, value);
+ }
+}
diff --git a/components/ColorAnalyzer/samples/ColorPaletteSampler/ColorWeightSample.xaml b/components/ColorAnalyzer/samples/ColorPaletteSampler/ColorWeightSample.xaml
new file mode 100644
index 000000000..145d29b73
--- /dev/null
+++ b/components/ColorAnalyzer/samples/ColorPaletteSampler/ColorWeightSample.xaml
@@ -0,0 +1,113 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/ColorAnalyzer/samples/ColorPaletteSampler/ColorWeightSample.xaml.cs b/components/ColorAnalyzer/samples/ColorPaletteSampler/ColorWeightSample.xaml.cs
new file mode 100644
index 000000000..7e0bde747
--- /dev/null
+++ b/components/ColorAnalyzer/samples/ColorPaletteSampler/ColorWeightSample.xaml.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace ColorAnalyzerExperiment.Samples;
+
+///
+/// An example sample page of a custom control inheriting from Panel.
+///
+[ToolkitSample(id: nameof(ColorWeightSample), "AccentAnalyzer helper", description: $"A sample for showing how the accent analyzer can be used.")]
+public sealed partial class ColorWeightSample : ColorPaletteSamplerToolkitSampleBase
+{
+ public ColorWeightSample()
+ {
+ this.InitializeComponent();
+ }
+}
diff --git a/components/ColorAnalyzer/samples/ColorPaletteSampler/ImageOptionsPane.xaml b/components/ColorAnalyzer/samples/ColorPaletteSampler/ImageOptionsPane.xaml
index 44227d2c9..34eb4f840 100644
--- a/components/ColorAnalyzer/samples/ColorPaletteSampler/ImageOptionsPane.xaml
+++ b/components/ColorAnalyzer/samples/ColorPaletteSampler/ImageOptionsPane.xaml
@@ -1,4 +1,4 @@
- $"ms-appx:///Assets/StockImages/{x}").ToList();
+ SetImage(new Uri(StockImages.First()));
}
private void Button_Click(object sender, RoutedEventArgs e)
@@ -39,6 +43,6 @@ private void GridView_ItemClick(object sender, ItemClickEventArgs e)
private void SetImage(Uri uri)
{
- _sample.SampledImage.Source = new BitmapImage(uri);
+ _sample.SelectedImage = new BitmapImage(uri);
}
}
diff --git a/components/ColorAnalyzer/samples/ColorPaletteSampler/MultiplePaletteSelectorSample.xaml b/components/ColorAnalyzer/samples/ColorPaletteSampler/MultiplePaletteSelectorSample.xaml
new file mode 100644
index 000000000..c99816386
--- /dev/null
+++ b/components/ColorAnalyzer/samples/ColorPaletteSampler/MultiplePaletteSelectorSample.xaml
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/ColorAnalyzer/samples/ColorPaletteSampler/MultiplePaletteSelectorSample.xaml.cs b/components/ColorAnalyzer/samples/ColorPaletteSampler/MultiplePaletteSelectorSample.xaml.cs
new file mode 100644
index 000000000..9206604b2
--- /dev/null
+++ b/components/ColorAnalyzer/samples/ColorPaletteSampler/MultiplePaletteSelectorSample.xaml.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace ColorAnalyzerExperiment.Samples;
+
+///
+/// An example sample page of a custom control inheriting from Panel.
+///
+[ToolkitSample(id: nameof(MultiplePaletteSelectorSample), "AccentAnalyzer helper", description: $"A sample for showing how the accent analyzer can be used.")]
+public sealed partial class MultiplePaletteSelectorSample : ColorPaletteSamplerToolkitSampleBase
+{
+ public MultiplePaletteSelectorSample()
+ {
+ this.InitializeComponent();
+ }
+}
diff --git a/components/ColorAnalyzer/samples/ColorPaletteSamplerToolkitSample.md b/components/ColorAnalyzer/samples/ColorPaletteSamplerToolkitSample.md
new file mode 100644
index 000000000..17b37374c
--- /dev/null
+++ b/components/ColorAnalyzer/samples/ColorPaletteSamplerToolkitSample.md
@@ -0,0 +1,53 @@
+---
+title: ColorPaletteSampler
+author: Avid29
+description: A resource that generates a color palette from an image or any other UI element.
+keywords: Color
+dev_langs:
+ - csharp
+category: Helpers
+subcategory: Miscellaneous
+discussion-id: 254
+issue-id: 736
+icon: assets/icon.png
+---
+
+# ColorPaletteSampler
+
+## Overview
+
+The `ColorPaletteSampler` is a resource that generates a color palette from any `UIElement`,
+but most notably from an `Image`. After the palette is generated, you can use a `PaletteSelector`
+or collection of `PaletteSelector` items to select colors from the palette to bind to in the UI.
+
+## AccentColorPaletteSelector
+
+The `AccentColorPaletteSelector` can be used to extract accent colors from an image. An
+accent color is a color that stands out, which we detect by looking for colors following
+a "colorness" formula.
+
+Here's an example where you can play around and see the results.
+
+> [!Sample AccentColorSample]
+
+## BaseColorPaletteSelector
+
+The `BaseColorPaletteSelector` can be used to extract basic colors from an image.
+Basic colors are colors that standand out less stands out, which we detect by using
+the same "colorness" formula, as accent colors, but inverting the results.
+
+> [!Sample BaseColorSample]
+
+## ColorWeightPaletteSelector
+
+The `ColorWeightPaletteSelector` can be used to determine which colors cover the most
+area in an image.
+
+> [!Sample ColorWeightSample]
+
+## Using multiple `PaletteSelectors` items
+
+Finally, multiple `PaletteSelector` items can be used together in a single `ColorPaletteSampler`
+to extract any combination of color data from an image.
+
+> [!Sample MultiplePaletteSelectorSample]
diff --git a/components/ColorAnalyzer/samples/ContrastHelper.md b/components/ColorAnalyzer/samples/ContrastHelper.md
new file mode 100644
index 000000000..3fdbc5561
--- /dev/null
+++ b/components/ColorAnalyzer/samples/ContrastHelper.md
@@ -0,0 +1,37 @@
+---
+title: ContrastHelper
+author: Avid29
+description: A helper for adjusting colors to ensure sufficient contrast.
+keywords: Color, Accesibility
+dev_langs:
+ - csharp
+category: Helpers
+subcategory: Miscellaneous
+discussion-id: 745
+issue-id: 736
+icon: assets/icon.png
+---
+
+# ContrastHelper
+
+### Using on TextBlocks or Controls
+
+The contrast helper can be applied to a `TextBlock` or `Control` to
+apply updates on its `Foreground` property.
+
+When checking the original contrast ratio, the `ContrastHelper` will
+attempt to grab the `Foreground` as a `SolidColorBrush`. If the original
+`Foreground` is not a `SolidColorBrush` it will default to `Colors.Transparent`,
+and always apply a raised contrast color.
+
+> [!Sample TextBlockContrastSample]
+
+If you are not using a `TextBlock` or `Control`,
+you can directly apply the `ContrastHelper` to a `SolidColorBrush`.
+
+Here for example, we adjust the stroke of a `Shape` by applying
+the helper on the `SolidColorBrush` inside the `Shape.Stroke` property.`
+
+### Using on SolidColorBrush
+
+> [!Sample SolidColorBrushContrastSample]
diff --git a/components/ColorAnalyzer/samples/ContrastHelper/ContrastHelperSample.xaml b/components/ColorAnalyzer/samples/ContrastHelper/ContrastHelperSample.xaml
deleted file mode 100644
index 6da841f01..000000000
--- a/components/ColorAnalyzer/samples/ContrastHelper/ContrastHelperSample.xaml
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/components/ColorAnalyzer/samples/ContrastHelper/ContrastHelperSample.xaml.cs b/components/ColorAnalyzer/samples/ContrastHelper/ContrastHelperSampleBase.cs
similarity index 62%
rename from components/ColorAnalyzer/samples/ContrastHelper/ContrastHelperSample.xaml.cs
rename to components/ColorAnalyzer/samples/ContrastHelper/ContrastHelperSampleBase.cs
index e65cf3286..0d8d11d02 100644
--- a/components/ColorAnalyzer/samples/ContrastHelper/ContrastHelperSample.xaml.cs
+++ b/components/ColorAnalyzer/samples/ContrastHelper/ContrastHelperSampleBase.cs
@@ -2,25 +2,28 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
+#if WINUI3
using Microsoft.UI;
+#endif
+
using Windows.UI;
namespace ColorAnalyzerExperiment.Samples;
-///
-/// An example sample page of a custom control inheriting from Panel.
-///
-[ToolkitSample(id: nameof(ContrastHelperSample), "ContrastAnalyzer helper", description: $"A sample for showing how the contrast analyzer can be used.")]
-public sealed partial class ContrastHelperSample : Page
+public abstract partial class ContrastHelperSampleBase : Page
{
public static readonly DependencyProperty DesiredBackgroundProperty =
- DependencyProperty.Register(nameof(DesiredBackground), typeof(Color), typeof(ContrastHelperSample), new PropertyMetadata(Colors.Black));
+ DependencyProperty.Register(nameof(DesiredBackground), typeof(Color), typeof(ContrastHelperSampleBase), new PropertyMetadata(Colors.Black));
public static readonly DependencyProperty DesiredForegroundProperty =
- DependencyProperty.Register(nameof(DesiredForeground), typeof(Color), typeof(ContrastHelperSample), new PropertyMetadata(Colors.White));
+ DependencyProperty.Register(nameof(DesiredForeground), typeof(Color), typeof(ContrastHelperSampleBase), new PropertyMetadata(Colors.White));
+
+ public static readonly DependencyProperty MinRatioProperty =
+ DependencyProperty.Register(nameof(MinRatio), typeof(double), typeof(ContrastHelperSampleBase), new PropertyMetadata(3d));
- private static readonly DependencyProperty MinRatioProperty =
- DependencyProperty.Register(nameof(MinRatio), typeof(double), typeof(ContrastHelperSample), new PropertyMetadata(0d));
+ public ContrastHelperSampleBase()
+ {
+ }
public Color DesiredBackground
{
@@ -39,9 +42,4 @@ public double MinRatio
get => (double)GetValue(MinRatioProperty);
set => SetValue(MinRatioProperty, value);
}
-
- public ContrastHelperSample()
- {
- this.InitializeComponent();
- }
}
diff --git a/components/ColorAnalyzer/samples/ContrastHelper/ContrastOptionsPane.xaml b/components/ColorAnalyzer/samples/ContrastHelper/ContrastOptionsPane.xaml
index 055ad47e0..685df7a76 100644
--- a/components/ColorAnalyzer/samples/ContrastHelper/ContrastOptionsPane.xaml
+++ b/components/ColorAnalyzer/samples/ContrastHelper/ContrastOptionsPane.xaml
@@ -1,4 +1,5 @@
-
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
-
+
+
+
+
-
-
-
-
+
+
+
diff --git a/components/ColorAnalyzer/samples/ContrastHelper/ContrastOptionsPane.xaml.cs b/components/ColorAnalyzer/samples/ContrastHelper/ContrastOptionsPane.xaml.cs
index 4ba613fcb..69bfd0ab9 100644
--- a/components/ColorAnalyzer/samples/ContrastHelper/ContrastOptionsPane.xaml.cs
+++ b/components/ColorAnalyzer/samples/ContrastHelper/ContrastOptionsPane.xaml.cs
@@ -8,22 +8,39 @@
using Windows.UI.Xaml.Media.Imaging;
#endif
+#if WINUI3
+using Microsoft.UI;
+#endif
+
+using Windows.UI;
+
namespace ColorAnalyzerExperiment.Samples;
-[ToolkitSampleOptionsPane(nameof(ContrastHelperSample))]
+[ToolkitSampleOptionsPane(nameof(TextBlockContrastSample))]
+[ToolkitSampleOptionsPane(nameof(SolidColorBrushContrastSample))]
public partial class ContrastOptionsPane : UserControl
{
- private ContrastHelperSample _sample;
- private ContrastHelperSample.XamlNamedPropertyRelay _sampleXamlRelay;
+ private ContrastHelperSampleBase _sample;
- public ContrastOptionsPane(ContrastHelperSample sample)
+ public ContrastOptionsPane(ContrastHelperSampleBase sample)
{
_sample = sample;
- _sampleXamlRelay = new ContrastHelperSample.XamlNamedPropertyRelay(sample);
-
+
this.InitializeComponent();
}
+ public Color DesiredForeground
+ {
+ get => _sample.DesiredForeground;
+ set => _sample.DesiredForeground = value;
+ }
+
+ public Color DesiredBackground
+ {
+ get => _sample.DesiredBackground;
+ set => _sample.DesiredBackground = value;
+ }
+
private void Foreground_ColorChanged(MUXC.ColorPicker sender, MUXC.ColorChangedEventArgs args)
{
// TODO: Disect the colorpicker
@@ -46,14 +63,4 @@ private void Ratio_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
{
_sample.MinRatio = (double)e.NewValue;
}
-
- private void FontSize_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
- {
- _sampleXamlRelay.TextSample.FontSize = (double)e.NewValue;
- }
-
- private void Thickness_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
- {
- _sampleXamlRelay.ShapeSample.StrokeThickness = (double)e.NewValue;
- }
}
diff --git a/components/ColorAnalyzer/samples/ContrastHelper/SolidColorBrushContrastSample.xaml b/components/ColorAnalyzer/samples/ContrastHelper/SolidColorBrushContrastSample.xaml
new file mode 100644
index 000000000..2767672a2
--- /dev/null
+++ b/components/ColorAnalyzer/samples/ContrastHelper/SolidColorBrushContrastSample.xaml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/ColorAnalyzer/samples/ContrastHelper/SolidColorBrushContrastSample.xaml.cs b/components/ColorAnalyzer/samples/ContrastHelper/SolidColorBrushContrastSample.xaml.cs
new file mode 100644
index 000000000..1cdd1f4f2
--- /dev/null
+++ b/components/ColorAnalyzer/samples/ContrastHelper/SolidColorBrushContrastSample.xaml.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace ColorAnalyzerExperiment.Samples;
+
+///
+/// An example sample page of a custom control inheriting from Panel.
+///
+[ToolkitSample(id: nameof(SolidColorBrushContrastSample), "ContrastAnalyzer helper", description: $"A sample for showing how the contrast analyzer can be used.")]
+public sealed partial class SolidColorBrushContrastSample : ContrastHelperSampleBase
+{
+ public SolidColorBrushContrastSample()
+ {
+ this.InitializeComponent();
+ }
+}
diff --git a/components/ColorAnalyzer/samples/ContrastHelper/TextBlockContrastSample.xaml b/components/ColorAnalyzer/samples/ContrastHelper/TextBlockContrastSample.xaml
new file mode 100644
index 000000000..2c4bb713a
--- /dev/null
+++ b/components/ColorAnalyzer/samples/ContrastHelper/TextBlockContrastSample.xaml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/ColorAnalyzer/samples/ContrastHelper/TextBlockContrastSample.xaml.cs b/components/ColorAnalyzer/samples/ContrastHelper/TextBlockContrastSample.xaml.cs
new file mode 100644
index 000000000..fcdbfd011
--- /dev/null
+++ b/components/ColorAnalyzer/samples/ContrastHelper/TextBlockContrastSample.xaml.cs
@@ -0,0 +1,17 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace ColorAnalyzerExperiment.Samples;
+
+///
+/// An example sample page of a custom control inheriting from Panel.
+///
+[ToolkitSample(id: nameof(TextBlockContrastSample), "ContrastAnalyzer helper", description: $"A sample for showing how the contrast analyzer can be used.")]
+public sealed partial class TextBlockContrastSample : ContrastHelperSampleBase
+{
+ public TextBlockContrastSample()
+ {
+ this.InitializeComponent();
+ }
+}
diff --git a/components/ColorAnalyzer/src/ColorExtensions.cs b/components/ColorAnalyzer/src/ColorExtensions.cs
index 2f6cc1db7..b1755d043 100644
--- a/components/ColorAnalyzer/src/ColorExtensions.cs
+++ b/components/ColorAnalyzer/src/ColorExtensions.cs
@@ -30,22 +30,22 @@ internal static double ContrastRatio(this Color color1, Color color2)
// Source WCAG guidelines: https://www.w3.org/TR/WCAG20/#contrast-ratiodef
// Calculate perceived luminance for both colors
- double luminance1 = color1.PerceivedLuminance();
- double luminance2 = color2.PerceivedLuminance();
+ double luminance1 = color1.RelativeLuminance();
+ double luminance2 = color2.RelativeLuminance();
// Determine lighter and darker luminance
double lighter = Math.Max(luminance1, luminance2);
double darker = Math.Min(luminance1, luminance2);
// Calculate contrast ratio
- return (lighter + 0.05f) / (darker + 0.05f);
+ return (lighter + 0.05) / (darker + 0.05);
}
- internal static double PerceivedLuminance(this Color color)
+ internal static double RelativeLuminance(this Color color)
{
// Color theory is a massive iceberg. Here's a peek at the tippy top:
- // There's two (main) standards for calculating luminance from RGB values.
+ // There's two (main) standards for calculating percieved luminance from RGB values.
// + ------------- + ------------------------------------ + ------------------ + ------------------------------------------------------------------------------- +
// | Standard | Formula | Ref. Section | Ref. Link |
@@ -61,11 +61,26 @@ internal static double PerceivedLuminance(this Color color)
// NOTE: If we for whatever reason we ever need to optimize this code,
// we can make approximations using integer math instead of floating point math.
- // The precise values are not critical, as long as the relative luminance is accurate.
+ // The precise values are not critical, as long as the proportions are similar and sum to 1.
// Like so: return (2 * color.R + 7 * color.G + color.B);
+ // Adjust channels relative luminance out of sRGB:
+ // https://www.w3.org/WAI/GL/wiki/Relative_luminance#Definition_as_Stated_in_WCAG_2.x
+ float sRGBtoRGB(float s)
+ {
+ if (s <= 0.03928f)
+ return s / 12.92f;
+
+ return MathF.Pow(((s + 0.055f) / 1.055f), 2.4f);
+ }
+
+ var vec = color.ToVector3();
+ var r = sRGBtoRGB(vec.X);
+ var g = sRGBtoRGB(vec.Y);
+ var b = sRGBtoRGB(vec.Z);
+
// TLDR: We use ITU Rec. 709 standard formula for perceived luminance.
- return (0.2126f * color.R + 0.7152f * color.G + 0.0722 * color.B) / 255;
+ return (0.2126f * r + 0.7152f * g + 0.0722 * b);
}
internal static float FindColorfulness(this Color color)
diff --git a/components/ColorAnalyzer/src/ContrastHelper/ContrastHelper.Properties.cs b/components/ColorAnalyzer/src/ContrastHelper/ContrastHelper.Properties.cs
index c621abf3b..0a65e9d5b 100644
--- a/components/ColorAnalyzer/src/ContrastHelper/ContrastHelper.Properties.cs
+++ b/components/ColorAnalyzer/src/ContrastHelper/ContrastHelper.Properties.cs
@@ -115,21 +115,39 @@ public partial class ContrastHelper
///
public static double GetContrastRatio(DependencyObject obj) => (double)obj.GetValue(ContrastRatioProperty);
- private static void SetContrastRatio(DependencyObject obj, double value) => obj.SetValue(ContrastRatioProperty, value);
+ ///
+ /// Sets the calculated contrast ratio compared to the actual foreground color.
+ ///
+ ///
+ /// This must be provided for binding, but should be treated as if it were private.
+ ///
+ public static void SetContrastRatio(DependencyObject obj, double value) => obj.SetValue(ContrastRatioProperty, value);
///
/// Gets the calculated contrast ratio compared to the original foreground color.
///
public static double GetOriginalContrastRatio(DependencyObject obj) => (double)obj.GetValue(OriginalContrastRatioProperty);
- private static void SetOriginalContrastRatio(DependencyObject obj, double value) => obj.SetValue(OriginalContrastRatioProperty, value);
+ ///
+ /// Sets the calculated contrast ratio compared to the original foreground color.
+ ///
+ ///
+ /// This must be provided for binding, but should be treated as if it were private.
+ ///
+ public static void SetOriginalContrastRatio(DependencyObject obj, double value) => obj.SetValue(OriginalContrastRatioProperty, value);
///
/// Gets the original color before adjustment for contrast.
///
public static Color GetOriginalColor(DependencyObject obj) => (Color)obj.GetValue(OriginalColorProperty);
- private static void SetOriginalColor(DependencyObject obj, Color color) => obj.SetValue(OriginalColorProperty, color);
+ ///
+ /// Sets the original color before adjustment for contrast.
+ ///
+ ///
+ /// This must be provided for binding, but should be treated as if it were private.
+ ///
+ public static void SetOriginalColor(DependencyObject obj, Color color) => obj.SetValue(OriginalColorProperty, color);
private static DependencyObject GetCallbackObject(DependencyObject obj) => (DependencyObject)obj.GetValue(CallbackObjectProperty);
diff --git a/components/ColorAnalyzer/src/ContrastHelper/ContrastHelper.cs b/components/ColorAnalyzer/src/ContrastHelper/ContrastHelper.cs
index 7943822ac..7156ef4a8 100644
--- a/components/ColorAnalyzer/src/ContrastHelper/ContrastHelper.cs
+++ b/components/ColorAnalyzer/src/ContrastHelper/ContrastHelper.cs
@@ -44,7 +44,7 @@ private static void ApplyContrastCheck(DependencyObject d)
// Current contrast is too small.
// Select either black or white backed on the opponent luminance
- var luminance = opponent.PerceivedLuminance();
+ var luminance = opponent.RelativeLuminance();
var contrastingColor = luminance < 0.5f ? Colors.White : Colors.Black;
UpdateContrastedProperties(d, contrastingColor);
}