diff --git a/PowerToys.sln b/PowerToys.sln
index c44829d472..1e9d13ae8e 100644
--- a/PowerToys.sln
+++ b/PowerToys.sln
@@ -269,6 +269,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Plugin.Calculator
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Plugin.Folder.UnitTests", "src\modules\launcher\Plugins\Microsoft.Plugin.Folder.UnitTests\Microsoft.Plugin.Folder.UnitTests.csproj", "{4FA206A5-F69F-4193-BF8F-F6EEB496734C}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTest-ColorPickerUI", "UnitTest-ColorPickerUI\UnitTest-ColorPickerUI.csproj", "{090CD7B7-3B0C-4D1D-BC98-83EB5D799BC1}"
+EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "logging", "src\logging\logging.vcxproj", "{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}"
EndProject
Global
@@ -545,6 +547,10 @@ Global
{4FA206A5-F69F-4193-BF8F-F6EEB496734C}.Debug|x64.Build.0 = Debug|x64
{4FA206A5-F69F-4193-BF8F-F6EEB496734C}.Release|x64.ActiveCfg = Release|x64
{4FA206A5-F69F-4193-BF8F-F6EEB496734C}.Release|x64.Build.0 = Release|x64
+ {090CD7B7-3B0C-4D1D-BC98-83EB5D799BC1}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {090CD7B7-3B0C-4D1D-BC98-83EB5D799BC1}.Debug|x64.Build.0 = Debug|Any CPU
+ {090CD7B7-3B0C-4D1D-BC98-83EB5D799BC1}.Release|x64.ActiveCfg = Release|x64
+ {090CD7B7-3B0C-4D1D-BC98-83EB5D799BC1}.Release|x64.Build.0 = Release|x64
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Debug|x64.ActiveCfg = Debug|x64
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Debug|x64.Build.0 = Debug|x64
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Release|x64.ActiveCfg = Release|x64
@@ -627,6 +633,7 @@ Global
{0F85E674-34AE-443D-954C-8321EB8B93B1} = {C3081D9A-1586-441A-B5F4-ED815B3719C1}
{632BBE62-5421-49EA-835A-7FFA4F499BD6} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
{4FA206A5-F69F-4193-BF8F-F6EEB496734C} = {4AFC9975-2456-4C70-94A4-84073C1CED93}
+ {090CD7B7-3B0C-4D1D-BC98-83EB5D799BC1} = {1D78B84B-CA39-406C-98F4-71F7EC266CC0}
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F} = {1AFB6476-670D-4E80-A464-657E01DFF482}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
diff --git a/UnitTest-ColorPickerUI/Helpers/ColorHelperTest.cs b/UnitTest-ColorPickerUI/Helpers/ColorHelperTest.cs
new file mode 100644
index 0000000000..5f9c867b93
--- /dev/null
+++ b/UnitTest-ColorPickerUI/Helpers/ColorHelperTest.cs
@@ -0,0 +1,187 @@
+using System;
+using System.Drawing;
+using ColorPicker.Helpers;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+
+namespace UnitTest_ColorPickerUI.Helpers
+{
+ ///
+ /// Test class to test
+ ///
+ [TestClass]
+ public class ColorConverterTest
+ {
+ // test values taken from https://de.wikipedia.org/wiki/HSV-Farbraum
+ [TestMethod]
+ [DataRow(000, 000, 000, 000, 000, 000)] // Black
+ [DataRow(000, 000, 100, 100, 100, 100)] // White
+ [DataRow(000, 100, 050, 100, 000, 000)] // Red
+ [DataRow(015, 100, 050, 100, 025, 000)] // Vermilion/Cinnabar
+ [DataRow(020, 060, 022.5, 036, 018, 009)] // Brown
+ [DataRow(030, 100, 050, 100, 050, 000)] // Orange
+ [DataRow(045, 100, 050, 100, 075, 000)] // Saffron
+ [DataRow(060, 100, 050, 100, 100, 000)] // Yellow
+ [DataRow(075, 100, 050, 075, 100, 000)] // Light green-yellow
+ [DataRow(090, 100, 050, 050, 100, 000)] // Green-yellow
+ [DataRow(105, 100, 050, 025, 100, 000)] // Lime
+ [DataRow(120, 100, 025, 000, 050, 000)] // Dark green
+ [DataRow(120, 100, 050, 000, 100, 000)] // Green
+ [DataRow(135, 100, 050, 000, 100, 025)] // Light blue-green
+ [DataRow(150, 100, 050, 000, 100, 050)] // Blue-green
+ [DataRow(165, 100, 050, 000, 100, 075)] // Green-cyan
+ [DataRow(180, 100, 050, 000, 100, 100)] // Cyan
+ [DataRow(195, 100, 050, 000, 075, 100)] // Blue-cyan
+ [DataRow(210, 100, 050, 000, 050, 100)] // Green-blue
+ [DataRow(225, 100, 050, 000, 025, 100)] // Light green-blue
+ [DataRow(240, 100, 050, 000, 000, 100)] // Blue
+ [DataRow(255, 100, 050, 025, 000, 100)] // Indigo
+ [DataRow(270, 100, 050, 050, 000, 100)] // Purple
+ [DataRow(285, 100, 050, 075, 000, 100)] // Blue-magenta
+ [DataRow(300, 100, 050, 100, 000, 100)] // Magenta
+ [DataRow(315, 100, 050, 100, 000, 075)] // Red-magenta
+ [DataRow(330, 100, 050, 100, 000, 050)] // Blue-red
+ [DataRow(345, 100, 050, 100, 000, 025)] // Light blue-red
+ public void ColorRGBtoHSL(double hue, double saturation, double lightness, int red, int green, int blue)
+ {
+ red = Convert.ToInt32(Math.Round(255d / 100d * red)); // [0%..100%] to [0..255]
+ green = Convert.ToInt32(Math.Round(255d / 100d * green)); // [0%..100%] to [0..255]
+ blue = Convert.ToInt32(Math.Round(255d / 100d * blue)); // [0%..100%] to [0..255]
+
+ var color = Color.FromArgb(255, red, green, blue);
+ var result = ColorHelper.ConvertToHSLColor(color);
+
+ // hue[0°..360°]
+ Assert.AreEqual(result.hue, hue, 0.2d);
+
+ // saturation[0..1]
+ Assert.AreEqual(result.saturation * 100d, saturation, 0.2d);
+
+ // lightness[0..1]
+ Assert.AreEqual(result.lightness * 100d, lightness, 0.2d);
+ }
+
+ // test values taken from https://de.wikipedia.org/wiki/HSV-Farbraum
+ [TestMethod]
+ [DataRow(000, 000, 000, 000, 000, 000)] // Black
+ [DataRow(000, 000, 100, 100, 100, 100)] // White
+ [DataRow(000, 100, 100, 100, 000, 000)] // Red
+ [DataRow(015, 100, 100, 100, 025, 000)] // Vermilion/Cinnabar
+ [DataRow(020, 075, 036, 036, 018, 009)] // Brown
+ [DataRow(030, 100, 100, 100, 050, 000)] // Orange
+ [DataRow(045, 100, 100, 100, 075, 000)] // Saffron
+ [DataRow(060, 100, 100, 100, 100, 000)] // Yellow
+ [DataRow(075, 100, 100, 075, 100, 000)] // Light green-yellow
+ [DataRow(090, 100, 100, 050, 100, 000)] // Green-yellow
+ [DataRow(105, 100, 100, 025, 100, 000)] // Lime
+ [DataRow(120, 100, 050, 000, 050, 000)] // Dark green
+ [DataRow(120, 100, 100, 000, 100, 000)] // Green
+ [DataRow(135, 100, 100, 000, 100, 025)] // Light blue-green
+ [DataRow(150, 100, 100, 000, 100, 050)] // Blue-green
+ [DataRow(165, 100, 100, 000, 100, 075)] // Green-cyan
+ [DataRow(180, 100, 100, 000, 100, 100)] // Cyan
+ [DataRow(195, 100, 100, 000, 075, 100)] // Blue-cyan
+ [DataRow(210, 100, 100, 000, 050, 100)] // Green-blue
+ [DataRow(225, 100, 100, 000, 025, 100)] // Light green-blue
+ [DataRow(240, 100, 100, 000, 000, 100)] // Blue
+ [DataRow(255, 100, 100, 025, 000, 100)] // Indigo
+ [DataRow(270, 100, 100, 050, 000, 100)] // Purple
+ [DataRow(285, 100, 100, 075, 000, 100)] // Blue-magenta
+ [DataRow(300, 100, 100, 100, 000, 100)] // Magenta
+ [DataRow(315, 100, 100, 100, 000, 075)] // Red-magenta
+ [DataRow(330, 100, 100, 100, 000, 050)] // Blue-red
+ [DataRow(345, 100, 100, 100, 000, 025)] // Light blue-red
+ public void ColorRGBtoHSV(double hue, double saturation, double value, int red, int green, int blue)
+ {
+ red = Convert.ToInt32(Math.Round(255d / 100d * red)); // [0%..100%] to [0..255]
+ green = Convert.ToInt32(Math.Round(255d / 100d * green)); // [0%..100%] to [0..255]
+ blue = Convert.ToInt32(Math.Round(255d / 100d * blue)); // [0%..100%] to [0..255]
+
+ var color = Color.FromArgb(255, red, green, blue);
+ var result = ColorHelper.ConvertToHSVColor(color);
+
+ // hue [0°..360°]
+ Assert.AreEqual(result.hue, hue, 0.2d);
+
+ // saturation[0..1]
+ Assert.AreEqual(result.saturation * 100d, saturation, 0.2d);
+
+ // value[0..1]
+ Assert.AreEqual(result.value * 100d, value, 0.2d);
+ }
+
+ [TestMethod]
+ [DataRow(000, 000, 000, 100, 000, 000, 000)] // Black
+ [DataRow(000, 000, 000, 000, 255, 255, 255)] // White
+ [DataRow(000, 100, 100, 000, 255, 000, 000)] // Red
+ [DataRow(000, 075, 100, 000, 255, 064, 000)] // Vermilion/Cinnabar
+ [DataRow(000, 050, 075, 064, 092, 046, 023)] // Brown
+ [DataRow(000, 050, 100, 000, 255, 128, 000)] // Orange
+ [DataRow(000, 025, 100, 000, 255, 192, 000)] // Saffron
+ [DataRow(000, 000, 100, 000, 255, 255, 000)] // Yellow
+ [DataRow(025, 000, 100, 000, 192, 255, 000)] // Light green-yellow
+ [DataRow(050, 000, 100, 000, 128, 255, 000)] // Green-yellow
+ [DataRow(075, 000, 100, 000, 064, 255, 000)] // Lime
+ [DataRow(100, 000, 100, 050, 000, 128, 000)] // Dark green
+ [DataRow(100, 000, 100, 000, 000, 255, 000)] // Green
+ [DataRow(100, 000, 075, 000, 000, 255, 064)] // Light blue-green
+ [DataRow(100, 000, 050, 000, 000, 255, 128)] // Blue-green
+ [DataRow(100, 000, 025, 000, 000, 255, 192)] // Green-cyan
+ [DataRow(100, 000, 000, 000, 000, 255, 255)] // Cyan
+ [DataRow(100, 025, 000, 000, 000, 192, 255)] // Blue-cyan
+ [DataRow(100, 050, 000, 000, 000, 128, 255)] // Green-blue
+ [DataRow(100, 075, 000, 000, 000, 064, 255)] // Light green-blue
+ [DataRow(100, 100, 000, 000, 000, 000, 255)] // Blue
+ [DataRow(075, 100, 000, 000, 064, 000, 255)] // Indigo
+ [DataRow(050, 100, 000, 000, 128, 000, 255)] // Purple
+ [DataRow(025, 100, 000, 000, 192, 000, 255)] // Blue-magenta
+ [DataRow(000, 100, 000, 000, 255, 000, 255)] // Magenta
+ [DataRow(000, 100, 025, 000, 255, 000, 192)] // Red-magenta
+ [DataRow(000, 100, 050, 000, 255, 000, 128)] // Blue-red
+ [DataRow(000, 100, 075, 000, 255, 000, 064)] // Light blue-red
+ public void ColorRGBtoCMYK(int cyan, int magenta, int yellow, int blackKey, int red, int green, int blue)
+ {
+ var color = Color.FromArgb(255, red, green, blue);
+ var result = ColorHelper.ConvertToCMYKColor(color);
+
+ // cyan[0..1]
+ Assert.AreEqual(result.cyan * 100d, cyan, 0.5d);
+
+ // magenta[0..1]
+ Assert.AreEqual(result.magenta * 100d, magenta, 0.5d);
+
+ // yellow[0..1]
+ Assert.AreEqual(result.yellow * 100d, yellow, 0.5d);
+
+ // black[0..1]
+ Assert.AreEqual(result.blackKey * 100d, blackKey, 0.5d);
+ }
+
+ [TestMethod]
+ public void ColorRGBtoCMYKZeroDiv()
+ {
+ for(var red = 0; red < 256; red++)
+ {
+ for(var blue = 0; blue < 256; blue++)
+ {
+ for(var green = 0; green < 256; green++)
+ {
+ var color = Color.FromArgb(red, green, blue);
+
+ Exception? exception = null;
+
+ try
+ {
+ _ = ColorHelper.ConvertToCMYKColor(color);
+ }
+ catch(Exception ex)
+ {
+ exception = ex;
+ }
+
+ Assert.IsNull(exception);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/UnitTest-ColorPickerUI/Helpers/ColorRepresentationHelperTest.cs b/UnitTest-ColorPickerUI/Helpers/ColorRepresentationHelperTest.cs
new file mode 100644
index 0000000000..44ec52ea89
--- /dev/null
+++ b/UnitTest-ColorPickerUI/Helpers/ColorRepresentationHelperTest.cs
@@ -0,0 +1,24 @@
+using ColorPicker.Helpers;
+using Microsoft.PowerToys.Settings.UI.Lib;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using System.Drawing;
+
+namespace UnitTest_ColorPickerUI.Helpers
+{
+ [TestClass]
+ public class ColorRepresentationHelperTest
+ {
+ [TestMethod]
+ [DataRow(ColorRepresentationType.CMYK, "cmyk(0%, 0%, 0%, 100%)")]
+ [DataRow(ColorRepresentationType.HEX, "#000000")]
+ [DataRow(ColorRepresentationType.HSL, "hsl(0, 0%, 0%)")]
+ [DataRow(ColorRepresentationType.HSV, "hsv(0, 0%, 0%)")]
+ [DataRow(ColorRepresentationType.RGB, "rgb(0, 0, 0)")]
+
+ public void ColorRGBtoCMYKZeroDiv(ColorRepresentationType type, string expected)
+ {
+ var result = ColorRepresentationHelper.GetStringRepresentation(Color.Black, type);
+ Assert.AreEqual(result, expected);
+ }
+ }
+}
diff --git a/UnitTest-ColorPickerUI/UnitTest-ColorPickerUI.csproj b/UnitTest-ColorPickerUI/UnitTest-ColorPickerUI.csproj
new file mode 100644
index 0000000000..34a479102a
--- /dev/null
+++ b/UnitTest-ColorPickerUI/UnitTest-ColorPickerUI.csproj
@@ -0,0 +1,35 @@
+
+
+
+ netcoreapp3.1
+ UnitTest_ColorPickerUI
+ false
+ enable
+ 9.0
+ Library
+
+
+
+ x64
+
+
+
+ x64
+
+
+
+
+
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+ all
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ColorPickerProperties.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ColorPickerProperties.cs
index a726465679..e5ea8ef888 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/ColorPickerProperties.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/ColorPickerProperties.cs
@@ -9,8 +9,30 @@ namespace Microsoft.PowerToys.Settings.UI.Lib
{
public enum ColorRepresentationType
{
+ ///
+ /// Color presentation as hexadecimal color value without the alpha-value (e.g. #0055FF)
+ ///
HEX = 0,
+
+ ///
+ /// Color presentation as RGB color value (red[0..255], green[0..255], blue[0..255])
+ ///
RGB = 1,
+
+ ///
+ /// Color presentation as CMYK color value (cyan[0%..100%], magenta[0%..100%], yellow[0%..100%], black key[0%..100%])
+ ///
+ CMYK = 2,
+
+ ///
+ /// Color presentation as HSL color value (hue[0°..360°], saturation[0..100%], lightness[0%..100%])
+ ///
+ HSL = 3,
+
+ ///
+ /// Color presentation as HSV color value (hue[0°..360°], saturation[0%..100%], value[0%..100%])
+ ///
+ HSV = 4,
}
public class ColorPickerProperties
@@ -31,8 +53,6 @@ namespace Microsoft.PowerToys.Settings.UI.Lib
public ColorRepresentationType CopiedColorRepresentation { get; set; }
public override string ToString()
- {
- return JsonSerializer.Serialize(this);
- }
+ => JsonSerializer.Serialize(this);
}
}
diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Views/ColorPickerPage.xaml b/src/core/Microsoft.PowerToys.Settings.UI/Views/ColorPickerPage.xaml
index 1ff3f00cc1..a28be48e6c 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI/Views/ColorPickerPage.xaml
+++ b/src/core/Microsoft.PowerToys.Settings.UI/Views/ColorPickerPage.xaml
@@ -68,7 +68,10 @@
Width="240"
IsEnabled="{Binding IsEnabled}">
-
+
+
+
+