diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt
index 0f2d1b0f7b..4431adcaba 100644
--- a/.github/actions/spell-check/expect.txt
+++ b/.github/actions/spell-check/expect.txt
@@ -295,6 +295,7 @@ codeofconduct
codereview
COINIT
Colorbrush
+colorconv
colorpicker
colorpickerref
COLORREF
@@ -903,6 +904,8 @@ hresult
hrgn
HRSRC
HSCROLL
+hsb
+hsi
hsl
hstring
hsv
@@ -913,6 +916,7 @@ html
htt
http
hu
+hwb
HWINEVENTHOOK
hwnd
HWNDFIRST
@@ -1087,6 +1091,7 @@ IPrincipal
IProgram
IPublic
IQuery
+IRead
IReflect
IRegistered
IRegistration
@@ -1439,6 +1444,7 @@ NCMBUTTONDOWN
NCMBUTTONUP
NCMOUSELEAVE
NCMOUSEMOVE
+NCol
NCPAINT
NCRBUTTONDBLCLK
NCRBUTTONDOWN
diff --git a/.github/actions/spell-check/patterns.txt b/.github/actions/spell-check/patterns.txt
index 60513959e0..e5192cd0c3 100644
--- a/.github/actions/spell-check/patterns.txt
+++ b/.github/actions/spell-check/patterns.txt
@@ -10,6 +10,11 @@ data:[a-zA-Z=;,/0-9+-]+
"Lorem[^"]+?\."
TestCase\("[^"]+"
+# Test line with hexadecimal colors
+\[DataRow\("[0-9A-F]{6}", \d{3}, \d{3}, \d{3}\)\]
+\[DataRow\("[0-9A-F]{6}", \d{3}.\d{1}, \d{3}.\d{1}, \d{3}.\d{1}\)\]
+\[DataRow\("[0-9A-F]{6}", "[BCGMRY]\d\d?", \d{3}, \d{3}\)\]
+
# Windows paths
\\native
\\notifications
diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Library/ColorPickerProperties.cs b/src/core/Microsoft.PowerToys.Settings.UI.Library/ColorPickerProperties.cs
index 7f65789992..f5305f5960 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI.Library/ColorPickerProperties.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI.Library/ColorPickerProperties.cs
@@ -4,37 +4,10 @@
using System.Text.Json;
using System.Text.Json.Serialization;
+using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
namespace Microsoft.PowerToys.Settings.UI.Library
{
- 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
{
public ColorPickerProperties()
diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Library/ColorPickerSettings.cs b/src/core/Microsoft.PowerToys.Settings.UI.Library/ColorPickerSettings.cs
index 72ebb295c9..a27a1076a3 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI.Library/ColorPickerSettings.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI.Library/ColorPickerSettings.cs
@@ -40,14 +40,10 @@ namespace Microsoft.PowerToys.Settings.UI.Library
}
public string GetModuleName()
- {
- return Name;
- }
+ => Name;
// This can be utilized in the future if the settings.json file is to be modified/deleted.
public bool UpgradeSettingsConfiguration()
- {
- return false;
- }
+ => false;
}
}
diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Library/Enumerations/ColorRepresentationType.cs b/src/core/Microsoft.PowerToys.Settings.UI.Library/Enumerations/ColorRepresentationType.cs
new file mode 100644
index 0000000000..9e456dfef6
--- /dev/null
+++ b/src/core/Microsoft.PowerToys.Settings.UI.Library/Enumerations/ColorRepresentationType.cs
@@ -0,0 +1,59 @@
+// Copyright (c) Microsoft Corporation
+// The Microsoft Corporation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace Microsoft.PowerToys.Settings.UI.Library.Enumerations
+{
+ // NOTE: don't change the order (numbers) of the enumeration entires
+
+ ///
+ /// The type of the color representation
+ ///
+ 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,
+
+ ///
+ /// Color presentation as HSB color value (hue[0°..360°], saturation[0%..100%], brightness[0%..100%])
+ ///
+ HSB = 5,
+
+ ///
+ /// Color presentation as HSI color value (hue[0°..360°], saturation[0%..100%], intensity[0%..100%])
+ ///
+ HSI = 6,
+
+ ///
+ /// Color presentation as HWB color value (hue[0°..360°], whiteness[0%..100%], blackness[0%..100%])
+ ///
+ HWB = 7,
+
+ ///
+ /// Color presentation as natural color (hue, whiteness[0%..100%], blackness[0%..100%])
+ ///
+ NCol = 8,
+ }
+}
diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Library/ViewModels/ColorPickerViewModel.cs b/src/core/Microsoft.PowerToys.Settings.UI.Library/ViewModels/ColorPickerViewModel.cs
index ff4f37f612..9d6dce41d6 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI.Library/ViewModels/ColorPickerViewModel.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI.Library/ViewModels/ColorPickerViewModel.cs
@@ -3,8 +3,10 @@
// See the LICENSE file in the project root for more information.
using System;
+using System.Collections.Generic;
using System.Globalization;
using System.Text.Json;
+using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
@@ -16,7 +18,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
private readonly ISettingsUtils _settingsUtils;
- private ColorPickerSettings _colorPickerSettings;
+ private readonly ColorPickerSettings _colorPickerSettings;
private bool _isEnabled;
@@ -30,6 +32,19 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
throw new ArgumentNullException(nameof(settingsRepository));
}
+ SelectableColorRepresentations = new Dictionary
+ {
+ { ColorRepresentationType.CMYK, "CMYK - cmyk(100%, 50%, 75%, 0%)" },
+ { ColorRepresentationType.HEX, "HEX - #FFAA00" },
+ { ColorRepresentationType.HSB, "HSB - hsb(100, 50%, 75%)" },
+ { ColorRepresentationType.HSI, "HSI - hsi(100, 50%, 75%)" },
+ { ColorRepresentationType.HSL, "HSL - hsl(100, 50%, 75%)" },
+ { ColorRepresentationType.HSV, "HSV - hsv(100, 50%, 75%)" },
+ { ColorRepresentationType.HWB, "HWB - hwb(100, 50%, 75%)" },
+ { ColorRepresentationType.NCol, "NCol - R10, 50%, 75%" },
+ { ColorRepresentationType.RGB, "RGB - rgb(100, 50, 75)" },
+ };
+
GeneralSettingsConfig = settingsRepository.SettingsConfig;
_settingsUtils = settingsUtils ?? throw new ArgumentNullException(nameof(settingsUtils));
@@ -48,13 +63,14 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
SendConfigMSG = ipcMSGCallBackFunc;
}
+ ///
+ /// Gets a list with all selectable s
+ ///
+ public IReadOnlyDictionary SelectableColorRepresentations { get; }
+
public bool IsEnabled
{
- get
- {
- return _isEnabled;
- }
-
+ get => _isEnabled;
set
{
if (_isEnabled != value)
@@ -64,7 +80,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
// Set the status of ColorPicker in the general settings
GeneralSettingsConfig.Enabled.ColorPicker = value;
- OutGoingGeneralSettings outgoing = new OutGoingGeneralSettings(GeneralSettingsConfig);
+ var outgoing = new OutGoingGeneralSettings(GeneralSettingsConfig);
SendConfigMSG(outgoing.ToString());
}
@@ -73,11 +89,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
public bool ChangeCursor
{
- get
- {
- return _colorPickerSettings.Properties.ChangeCursor;
- }
-
+ get => _colorPickerSettings.Properties.ChangeCursor;
set
{
if (_colorPickerSettings.Properties.ChangeCursor != value)
@@ -91,11 +103,7 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
public HotkeySettings ActivationShortcut
{
- get
- {
- return _colorPickerSettings.Properties.ActivationShortcut;
- }
-
+ get => _colorPickerSettings.Properties.ActivationShortcut;
set
{
if (_colorPickerSettings.Properties.ActivationShortcut != value)
@@ -107,19 +115,15 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
}
}
- public int CopiedColorRepresentationIndex
+ public ColorRepresentationType SelectedColorRepresentationValue
{
- get
- {
- return (int)_colorPickerSettings.Properties.CopiedColorRepresentation;
- }
-
+ get => _colorPickerSettings.Properties.CopiedColorRepresentation;
set
{
- if (_colorPickerSettings.Properties.CopiedColorRepresentation != (ColorRepresentationType)value)
+ if (_colorPickerSettings.Properties.CopiedColorRepresentation != value)
{
- _colorPickerSettings.Properties.CopiedColorRepresentation = (ColorRepresentationType)value;
- OnPropertyChanged(nameof(CopiedColorRepresentationIndex));
+ _colorPickerSettings.Properties.CopiedColorRepresentation = value;
+ OnPropertyChanged(nameof(SelectedColorRepresentationValue));
NotifySettingsChanged();
}
}
diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Views/ColorPickerPage.xaml b/src/core/Microsoft.PowerToys.Settings.UI/Views/ColorPickerPage.xaml
index 7fb9e40c5d..1c9b6333b7 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI/Views/ColorPickerPage.xaml
+++ b/src/core/Microsoft.PowerToys.Settings.UI/Views/ColorPickerPage.xaml
@@ -13,6 +13,95 @@
AutomationProperties.LandmarkType="Main">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -26,109 +115,16 @@
-
-
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Views/ColorPickerPage.xaml.cs b/src/core/Microsoft.PowerToys.Settings.UI/Views/ColorPickerPage.xaml.cs
index 6d994eedc2..c7a17a3335 100644
--- a/src/core/Microsoft.PowerToys.Settings.UI/Views/ColorPickerPage.xaml.cs
+++ b/src/core/Microsoft.PowerToys.Settings.UI/Views/ColorPickerPage.xaml.cs
@@ -21,5 +21,33 @@ namespace Microsoft.PowerToys.Settings.UI.Views
DataContext = ViewModel;
InitializeComponent();
}
+
+ ///
+ /// Event is called when the is completely loaded, inclusive the ItemSource
+ ///
+ /// The sender of this event
+ /// The arguments of this event
+ private void ColorPicker_ComboBox_Loaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
+ {
+ /**
+ * UWP hack
+ * because UWP load the bound ItemSource of the ComboBox asynchronous,
+ * so after InitializeComponent() the ItemSource is still empty and can't automatically select a entry.
+ * Selection via SelectedItem and SelectedValue is still not working too
+ */
+ var index = 0;
+
+ foreach (var item in ViewModel.SelectableColorRepresentations)
+ {
+ if (item.Key == ViewModel.SelectedColorRepresentationValue)
+ {
+ break;
+ }
+
+ index++;
+ }
+
+ ColorPicker_ComboBox.SelectedIndex = index;
+ }
}
}
diff --git a/src/modules/colorPicker/ColorPickerUI/Helpers/ColorHelper.cs b/src/modules/colorPicker/ColorPickerUI/Helpers/ColorHelper.cs
index 44f547fc5b..edb2f6d1e0 100644
--- a/src/modules/colorPicker/ColorPickerUI/Helpers/ColorHelper.cs
+++ b/src/modules/colorPicker/ColorPickerUI/Helpers/ColorHelper.cs
@@ -13,44 +13,7 @@ namespace ColorPicker.Helpers
internal static class ColorHelper
{
///
- /// Convert a given color to a HSL color (hue, saturation, lightness)
- ///
- /// The to convert
- /// The hue [0°..360°], saturation [0..1] and lightness [0..1] values of the converted color
- internal static (double hue, double saturation, double lightness) ConvertToHSLColor(Color color)
- {
- var min = Math.Min(Math.Min(color.R, color.G), color.B) / 255d;
- var max = Math.Max(Math.Max(color.R, color.G), color.B) / 255d;
-
- var lightness = (max + min) / 2d;
-
- if (lightness == 0d || min == max)
- {
- return (color.GetHue(), 0d, lightness);
- }
- else if (lightness > 0d && lightness <= 0.5d)
- {
- return (color.GetHue(), (max - min) / (max + min), lightness);
- }
-
- return (color.GetHue(), (max - min) / (2d - (max + min)), lightness);
- }
-
- ///
- /// Convert a given color to a HSV color (hue, saturation, value)
- ///
- /// The to convert
- /// The hue [0°..360°], saturation [0..1] and value [0..1] of the converted color
- internal static (double hue, double saturation, double value) ConvertToHSVColor(Color color)
- {
- var min = Math.Min(Math.Min(color.R, color.G), color.B) / 255d;
- var max = Math.Max(Math.Max(color.R, color.G), color.B) / 255d;
-
- return (color.GetHue(), max == 0d ? 0d : (max - min) / max, max);
- }
-
- ///
- /// Convert a given color to a CYMK color (cyan, magenta, yellow, black key)
+ /// Convert a given to a CYMK color (cyan, magenta, yellow, black key)
///
/// The to convert
/// The cyan[0..1], magenta[0..1], yellow[0..1] and black key[0..1] of the converted color
@@ -80,5 +43,135 @@ namespace ColorPicker.Helpers
return (cyan, magenta, yellow, blackKey);
}
+
+ ///
+ /// Convert a given to a HSB color (hue, saturation, brightness)
+ ///
+ /// The to convert
+ /// The hue [0°..360°], saturation [0..1] and brightness [0..1] of the converted color
+ internal static (double hue, double saturation, double brightness) ConvertToHSBColor(Color color)
+ => (color.GetHue(), color.GetSaturation(), color.GetBrightness());
+
+ ///
+ /// Convert a given to a HSI color (hue, saturation, intensity)
+ ///
+ /// The to convert
+ /// The hue [0°..360°], saturation [0..1] and intensity [0..1] of the converted color
+ internal static (double hue, double saturation, double intensity) ConvertToHSIColor(Color color)
+ {
+ // special case for black
+ if (color.R == 0 && color.G == 0 && color.B == 0)
+ {
+ return (0d, 0d, 0d);
+ }
+
+ var red = color.R / 255d;
+ var green = color.G / 255d;
+ var blue = color.B / 255d;
+
+ var intensity = (red + green + blue) / 3d;
+
+ var min = Math.Min(Math.Min(color.R, color.G), color.B) / 255d;
+
+ return (color.GetHue(), 1d - (min / intensity), intensity);
+ }
+
+ ///
+ /// Convert a given to a HSL color (hue, saturation, lightness)
+ ///
+ /// The to convert
+ /// The hue [0°..360°], saturation [0..1] and lightness [0..1] values of the converted color
+ internal static (double hue, double saturation, double lightness) ConvertToHSLColor(Color color)
+ {
+ var min = Math.Min(Math.Min(color.R, color.G), color.B) / 255d;
+ var max = Math.Max(Math.Max(color.R, color.G), color.B) / 255d;
+
+ var lightness = (max + min) / 2d;
+
+ if (lightness == 0d || min == max)
+ {
+ return (color.GetHue(), 0d, lightness);
+ }
+ else if (lightness > 0d && lightness <= 0.5d)
+ {
+ return (color.GetHue(), (max - min) / (max + min), lightness);
+ }
+
+ return (color.GetHue(), (max - min) / (2d - (max + min)), lightness);
+ }
+
+ ///
+ /// Convert a given to a HSV color (hue, saturation, value)
+ ///
+ /// The to convert
+ /// The hue [0°..360°], saturation [0..1] and value [0..1] of the converted color
+ internal static (double hue, double saturation, double value) ConvertToHSVColor(Color color)
+ {
+ var min = Math.Min(Math.Min(color.R, color.G), color.B) / 255d;
+ var max = Math.Max(Math.Max(color.R, color.G), color.B) / 255d;
+
+ return (color.GetHue(), max == 0d ? 0d : (max - min) / max, max);
+ }
+
+ ///
+ /// Convert a given to a HWB color (hue, whiteness, blackness)
+ ///
+ /// The to convert
+ /// The hue [0°..360°], whiteness [0..1] and blackness [0..1] of the converted color
+ internal static (double hue, double whiteness, double blackness) ConvertToHWBColor(Color color)
+ {
+ var min = Math.Min(Math.Min(color.R, color.G), color.B) / 255d;
+ var max = Math.Max(Math.Max(color.R, color.G), color.B) / 255d;
+
+ return (color.GetHue(), min, 1 - max);
+ }
+
+ ///
+ /// Convert a given to a natural color (hue, whiteness, blackness)
+ ///
+ /// The to convert
+ /// The hue, whiteness [0..1] and blackness [0..1] of the converted color
+ internal static (string hue, double whiteness, double blackness) ConvertToNaturalColor(Color color)
+ {
+ var min = Math.Min(Math.Min(color.R, color.G), color.B) / 255d;
+ var max = Math.Max(Math.Max(color.R, color.G), color.B) / 255d;
+
+ return (GetNaturalColorFromHue(color.GetHue()), min, 1 - max);
+ }
+
+ ///
+ /// Return the natural color for the given hue value
+ ///
+ /// The hue value to convert
+ /// A natural color
+ private static string GetNaturalColorFromHue(double hue)
+ {
+ if (hue < 60d)
+ {
+ return $"R{Math.Round(hue / 0.6d, 0)}";
+ }
+
+ if (hue < 120d)
+ {
+ return $"Y{Math.Round((hue - 60d) / 0.6d, 0)}";
+ }
+
+ if (hue < 180d)
+ {
+ return $"G{Math.Round((hue - 120d) / 0.6d, 0)}";
+ }
+
+ if (hue < 240d)
+ {
+ return $"C{Math.Round((hue - 180d) / 0.6d, 0)}";
+ }
+
+ if (hue < 300d)
+ {
+ return $"B{Math.Round((hue - 240d) / 0.6d, 0)}";
+ }
+
+ return $"M{Math.Round((hue - 300d) / 0.6d, 0)}";
+ }
}
}
diff --git a/src/modules/colorPicker/ColorPickerUI/Helpers/ColorRepresentationHelper.cs b/src/modules/colorPicker/ColorPickerUI/Helpers/ColorRepresentationHelper.cs
index 1b2294d915..b21304a9ab 100644
--- a/src/modules/colorPicker/ColorPickerUI/Helpers/ColorRepresentationHelper.cs
+++ b/src/modules/colorPicker/ColorPickerUI/Helpers/ColorRepresentationHelper.cs
@@ -5,7 +5,7 @@
using System;
using System.Drawing;
using System.Globalization;
-using Microsoft.PowerToys.Settings.UI.Library;
+using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
namespace ColorPicker.Helpers
{
@@ -25,14 +25,38 @@ namespace ColorPicker.Helpers
{
ColorRepresentationType.CMYK => ColorToCYMK(color),
ColorRepresentationType.HEX => ColorToHex(color),
+ ColorRepresentationType.HSB => ColorToHSB(color),
+ ColorRepresentationType.HSI => ColorToHSI(color),
ColorRepresentationType.HSL => ColorToHSL(color),
ColorRepresentationType.HSV => ColorToHSV(color),
+ ColorRepresentationType.HWB => ColorToHWB(color),
+ ColorRepresentationType.NCol => ColorToNCol(color),
ColorRepresentationType.RGB => ColorToRGB(color),
// Fall-back value, when "_userSettings.CopiedColorRepresentation.Value" is incorrect
_ => ColorToHex(color),
};
+ ///
+ /// Return a representation of a CYMK color
+ ///
+ /// The for the CYMK color presentation
+ /// A representation of a CYMK color
+ private static string ColorToCYMK(Color color)
+ {
+ var (cyan, magenta, yellow, blackKey) = ColorHelper.ConvertToCMYKColor(color);
+
+ cyan = Math.Round(cyan * 100);
+ magenta = Math.Round(magenta * 100);
+ yellow = Math.Round(yellow * 100);
+ blackKey = Math.Round(blackKey * 100);
+
+ return $"cmyk({cyan.ToString(CultureInfo.InvariantCulture)}%"
+ + $", {magenta.ToString(CultureInfo.InvariantCulture)}%"
+ + $", {yellow.ToString(CultureInfo.InvariantCulture)}%"
+ + $", {blackKey.ToString(CultureInfo.InvariantCulture)}%)";
+ }
+
///
/// Return a hexadecimal representation of a RGB color
///
@@ -44,19 +68,45 @@ namespace ColorPicker.Helpers
+ $"{color.B.ToString("X2", CultureInfo.InvariantCulture)}";
///
- /// Return a representation of a RGB color
+ /// Return a representation of a HSB color
///
- /// The see cref="Color"/> for the RGB color presentation
- /// A representation of a RGB color
- private static string ColorToRGB(Color color)
- => $"rgb({color.R.ToString(CultureInfo.InvariantCulture)}"
- + $", {color.G.ToString(CultureInfo.InvariantCulture)}"
- + $", {color.B.ToString(CultureInfo.InvariantCulture)})";
+ /// The for the HSB color presentation
+ /// A representation of a HSB color
+ private static string ColorToHSB(Color color)
+ {
+ var (hue, saturation, brightness) = ColorHelper.ConvertToHSBColor(color);
+
+ hue = Math.Round(hue);
+ saturation = Math.Round(saturation * 100);
+ brightness = Math.Round(brightness * 100);
+
+ return $"hsb({hue.ToString(CultureInfo.InvariantCulture)}"
+ + $", {saturation.ToString(CultureInfo.InvariantCulture)}%"
+ + $", {brightness.ToString(CultureInfo.InvariantCulture)}%)";
+ }
+
+ ///
+ /// Return a representation of a HSI color
+ ///
+ /// The for the HSI color presentation
+ /// A representation of a HSI color
+ private static string ColorToHSI(Color color)
+ {
+ var (hue, saturation, intensity) = ColorHelper.ConvertToHSIColor(color);
+
+ hue = Math.Round(hue);
+ saturation = Math.Round(saturation * 100);
+ intensity = Math.Round(intensity * 100);
+
+ return $"hsi({hue.ToString(CultureInfo.InvariantCulture)}"
+ + $", {saturation.ToString(CultureInfo.InvariantCulture)}%"
+ + $", {intensity.ToString(CultureInfo.InvariantCulture)}%)";
+ }
///
/// Return a representation of a HSL color
///
- /// The see cref="Color"/> for the HSL color presentation
+ /// The for the HSL color presentation
/// A representation of a HSL color
private static string ColorToHSL(Color color)
{
@@ -75,7 +125,7 @@ namespace ColorPicker.Helpers
///
/// Return a representation of a HSV color
///
- /// The see cref="Color"/> for the HSV color presentation
+ /// The for the HSV color presentation
/// A representation of a HSV color
private static string ColorToHSV(Color color)
{
@@ -92,24 +142,48 @@ namespace ColorPicker.Helpers
}
///
- /// Return a representation of a HSV color
+ /// Return a representation of a HWB color
///
- /// The see cref="Color"/> for the HSV color presentation
- /// A representation of a HSV color
- private static string ColorToCYMK(Color color)
+ /// The for the HWB color presentation
+ /// A representation of a HWB color
+ private static string ColorToHWB(Color color)
{
- var (cyan, magenta, yellow, blackKey) = ColorHelper.ConvertToCMYKColor(color);
+ var (hue, whiteness, blackness) = ColorHelper.ConvertToHWBColor(color);
- cyan = Math.Round(cyan * 100);
- magenta = Math.Round(magenta * 100);
- yellow = Math.Round(yellow * 100);
- blackKey = Math.Round(blackKey * 100);
+ hue = Math.Round(hue);
+ whiteness = Math.Round(whiteness * 100);
+ blackness = Math.Round(blackness * 100);
- // Using InvariantCulture since this is used for color representation
- return $"cmyk({cyan.ToString(CultureInfo.InvariantCulture)}%"
- + $", {magenta.ToString(CultureInfo.InvariantCulture)}%"
- + $", {yellow.ToString(CultureInfo.InvariantCulture)}%"
- + $", {blackKey.ToString(CultureInfo.InvariantCulture)}%)";
+ return $"hwb({hue.ToString(CultureInfo.InvariantCulture)}"
+ + $", {whiteness.ToString(CultureInfo.InvariantCulture)}%"
+ + $", {blackness.ToString(CultureInfo.InvariantCulture)}%)";
}
+
+ ///
+ /// Return a representation of a natural color
+ ///
+ /// The for the natural color presentation
+ /// A representation of a natural color
+ private static string ColorToNCol(Color color)
+ {
+ var (hue, whiteness, blackness) = ColorHelper.ConvertToNaturalColor(color);
+
+ whiteness = Math.Round(whiteness * 100);
+ blackness = Math.Round(blackness * 100);
+
+ return $"{hue}"
+ + $", {whiteness.ToString(CultureInfo.InvariantCulture)}%"
+ + $", {blackness.ToString(CultureInfo.InvariantCulture)}%";
+ }
+
+ ///
+ /// Return a representation of a RGB color
+ ///
+ /// The see cref="Color"/> for the RGB color presentation
+ /// A representation of a RGB color
+ private static string ColorToRGB(Color color)
+ => $"rgb({color.R.ToString(CultureInfo.InvariantCulture)}"
+ + $", {color.G.ToString(CultureInfo.InvariantCulture)}"
+ + $", {color.B.ToString(CultureInfo.InvariantCulture)})";
}
}
diff --git a/src/modules/colorPicker/ColorPickerUI/Settings/IUserSettings.cs b/src/modules/colorPicker/ColorPickerUI/Settings/IUserSettings.cs
index b05be4d12e..585b441279 100644
--- a/src/modules/colorPicker/ColorPickerUI/Settings/IUserSettings.cs
+++ b/src/modules/colorPicker/ColorPickerUI/Settings/IUserSettings.cs
@@ -2,7 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using Microsoft.PowerToys.Settings.UI.Library;
+using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
namespace ColorPicker.Settings
{
diff --git a/src/modules/colorPicker/ColorPickerUI/Settings/UserSettings.cs b/src/modules/colorPicker/ColorPickerUI/Settings/UserSettings.cs
index 3ccea1f1e4..852278f90b 100644
--- a/src/modules/colorPicker/ColorPickerUI/Settings/UserSettings.cs
+++ b/src/modules/colorPicker/ColorPickerUI/Settings/UserSettings.cs
@@ -8,6 +8,7 @@ using System.IO;
using System.IO.Abstractions;
using System.Threading;
using Microsoft.PowerToys.Settings.UI.Library;
+using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
namespace ColorPicker.Settings
diff --git a/src/modules/colorPicker/ColorPickerUI/ViewModels/MainViewModel.cs b/src/modules/colorPicker/ColorPickerUI/ViewModels/MainViewModel.cs
index a600471f61..d747eae0a2 100644
--- a/src/modules/colorPicker/ColorPickerUI/ViewModels/MainViewModel.cs
+++ b/src/modules/colorPicker/ColorPickerUI/ViewModels/MainViewModel.cs
@@ -15,7 +15,6 @@ using ColorPicker.Mouse;
using ColorPicker.Settings;
using ColorPicker.Telemetry;
using ColorPicker.ViewModelContracts;
-using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Telemetry;
namespace ColorPicker.ViewModels
diff --git a/src/modules/colorPicker/UnitTest-ColorPickerUI/Helpers/ColorHelperTest.cs b/src/modules/colorPicker/UnitTest-ColorPickerUI/Helpers/ColorHelperTest.cs
index aae56ac7c2..804ecddd7a 100644
--- a/src/modules/colorPicker/UnitTest-ColorPickerUI/Helpers/ColorHelperTest.cs
+++ b/src/modules/colorPicker/UnitTest-ColorPickerUI/Helpers/ColorHelperTest.cs
@@ -1,5 +1,6 @@
using System;
using System.Drawing;
+using System.Globalization;
using ColorPicker.Helpers;
using Microsoft.VisualStudio.TestTools.UnitTesting;
@@ -41,7 +42,7 @@ namespace UnitTest_ColorPickerUI.Helpers
[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)
+ public void ColorRGBtoHSLTest(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]
@@ -90,7 +91,7 @@ namespace UnitTest_ColorPickerUI.Helpers
[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)
+ public void ColorRGBtoHSVTest(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]
@@ -138,7 +139,7 @@ namespace UnitTest_ColorPickerUI.Helpers
[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)
+ public void ColorRGBtoCMYKTest(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);
@@ -156,8 +157,130 @@ namespace UnitTest_ColorPickerUI.Helpers
Assert.AreEqual(result.blackKey * 100d, blackKey, 0.5d);
}
+ // values taken from https://en.wikipedia.org/wiki/HSL_and_HSV#Examples
[TestMethod]
- public void ColorRGBtoCMYKZeroDiv()
+ [DataRow("FFFFFF", 000.0, 000.0, 100.0)] // white
+ [DataRow("808080", 000.0, 000.0, 050.0)] // gray
+ [DataRow("000000", 000.0, 000.0, 000.0)] // black
+ [DataRow("FF0000", 000.0, 100.0, 033.3)] // red
+ [DataRow("BFBF00", 060.0, 100.0, 050.0)] // yellow
+ [DataRow("008000", 120.0, 100.0, 016.7)] // green
+ [DataRow("80FFFF", 180.0, 040.0, 083.3)] // cyan
+ [DataRow("8080FF", 240.0, 025.0, 066.7)] // blue
+ [DataRow("BF40BF", 300.0, 057.1, 058.3)] // magenta
+ [DataRow("A0A424", 061.8, 069.9, 047.1)]
+ [DataRow("411BEA", 251.1, 075.6, 042.6)]
+ [DataRow("1EAC41", 134.9, 066.7, 034.9)]
+ [DataRow("F0C80E", 049.5, 091.1, 059.3)]
+ [DataRow("B430E5", 283.7, 068.6, 059.6)]
+ [DataRow("ED7651", 014.3, 044.6, 057.0)]
+ [DataRow("FEF888", 056.9, 036.3, 083.5)]
+ [DataRow("19CB97", 162.4, 080.0, 049.5)]
+ [DataRow("362698", 248.3, 053.3, 031.9)]
+ [DataRow("7E7EB8", 240.5, 013.5, 057.0)]
+ public void ColorRGBtoHSITest(string hexValue, double hue, double saturation, double intensity)
+ {
+ var red = int.Parse(hexValue.Substring(0, 2), NumberStyles.HexNumber);
+ var green = int.Parse(hexValue.Substring(2, 2), NumberStyles.HexNumber);
+ var blue = int.Parse(hexValue.Substring(4, 2), NumberStyles.HexNumber);
+
+ var color = Color.FromArgb(255, red, green, blue);
+ var result = ColorHelper.ConvertToHSIColor(color);
+
+ // hue[0°..360°]
+ Assert.AreEqual(result.hue, hue, 0.5d);
+
+ // saturation[0..1]
+ Assert.AreEqual(result.saturation * 100d, saturation, 0.5d);
+
+ // intensity[0..1]
+ Assert.AreEqual(result.intensity * 100d, intensity, 0.5d);
+ }
+
+ // values taken from https://en.wikipedia.org/wiki/HSL_and_HSV#Examples
+ // and manual convert via https://colorconv.com/hwb
+ [TestMethod]
+ [DataRow("FFFFFF", 000, 100, 000)] // white
+ [DataRow("808080", 000, 050, 050)] // gray
+ [DataRow("000000", 000, 000, 100)] // black
+ [DataRow("FF0000", 000, 000, 000)] // red
+ [DataRow("BFBF00", 060, 000, 025)] // yellow
+ [DataRow("008000", 120, 000, 050)] // green
+ [DataRow("80FFFF", 180, 050, 000)] // cyan
+ [DataRow("8080FF", 240, 050, 000)] // blue
+ [DataRow("BF40BF", 300, 025, 025)] // magenta
+ [DataRow("A0A424", 062, 014, 036)]
+ [DataRow("411BEA", 251, 011, 008)]
+ [DataRow("1EAC41", 135, 012, 033)]
+ [DataRow("F0C80E", 049, 005, 006)]
+ [DataRow("B430E5", 284, 019, 010)]
+ [DataRow("ED7651", 014, 032, 007)]
+ [DataRow("FEF888", 057, 053, 000)]
+ [DataRow("19CB97", 162, 010, 020)]
+ [DataRow("362698", 248, 015, 040)]
+ [DataRow("7E7EB8", 240, 049, 028)]
+ public void ColorRGBtoHWBTest(string hexValue, double hue, double whiteness, double blackness)
+ {
+ var red = int.Parse(hexValue.Substring(0, 2), NumberStyles.HexNumber);
+ var green = int.Parse(hexValue.Substring(2, 2), NumberStyles.HexNumber);
+ var blue = int.Parse(hexValue.Substring(4, 2), NumberStyles.HexNumber);
+
+ var color = Color.FromArgb(255, red, green, blue);
+ var result = ColorHelper.ConvertToHWBColor(color);
+
+ // hue[0°..360°]
+ Assert.AreEqual(result.hue, hue, 0.5d);
+
+ // whiteness[0..1]
+ Assert.AreEqual(result.whiteness * 100d, whiteness, 0.5d);
+
+ // blackness[0..1]
+ Assert.AreEqual(result.blackness * 100d, blackness, 0.5d);
+ }
+
+ // values taken from https://en.wikipedia.org/wiki/HSL_and_HSV#Examples
+ // and manual convert via https://colorconv.com/hwb
+ [TestMethod]
+ [DataRow("FFFFFF", "R0", 100, 000)] // white
+ [DataRow("808080", "R0", 050, 050)] // gray
+ [DataRow("000000", "R0", 000, 100)] // black
+ [DataRow("FF0000", "R0", 000, 000)] // red
+ [DataRow("BFBF00", "Y0", 000, 025)] // yellow
+ [DataRow("008000", "G0", 000, 050)] // green
+ [DataRow("80FFFF", "C0", 050, 000)] // cyan
+ [DataRow("8080FF", "B0", 050, 000)] // blue
+ [DataRow("BF40BF", "M0", 025, 025)] // magenta
+ [DataRow("A0A424", "Y3", 014, 036)]
+ [DataRow("411BEA", "B18", 011, 008)]
+ [DataRow("1EAC41", "G25", 012, 033)]
+ [DataRow("F0C80E", "R82", 005, 006)]
+ [DataRow("B430E5", "B73", 019, 010)]
+ [DataRow("ED7651", "R24", 032, 007)]
+ [DataRow("FEF888", "R95", 053, 000)]
+ [DataRow("19CB97", "G71", 010, 020)]
+ [DataRow("362698", "B14", 015, 040)]
+ [DataRow("7E7EB8", "B0", 049, 028)]
+ public void ColorRGBtoNColTest(string hexValue, string hue, double whiteness, double blackness)
+ {
+ var red = int.Parse(hexValue.Substring(0, 2), NumberStyles.HexNumber);
+ var green = int.Parse(hexValue.Substring(2, 2), NumberStyles.HexNumber);
+ var blue = int.Parse(hexValue.Substring(4, 2), NumberStyles.HexNumber);
+
+ var color = Color.FromArgb(255, red, green, blue);
+ var result = ColorHelper.ConvertToNaturalColor(color);
+
+ // hue
+ Assert.AreEqual(result.hue, hue);
+
+ // whiteness[0..1]
+ Assert.AreEqual(result.whiteness * 100d, whiteness, 0.5d);
+
+ // blackness[0..1]
+ Assert.AreEqual(result.blackness * 100d, blackness, 0.5d);
+ }
+
+ [TestMethod]
+ public void ColorRGBtoCMYKZeroDivTest()
{
for(var red = 0; red < 256; red++)
{
diff --git a/src/modules/colorPicker/UnitTest-ColorPickerUI/Helpers/ColorRepresentationHelperTest.cs b/src/modules/colorPicker/UnitTest-ColorPickerUI/Helpers/ColorRepresentationHelperTest.cs
index fe6fddf015..d9ce148756 100644
--- a/src/modules/colorPicker/UnitTest-ColorPickerUI/Helpers/ColorRepresentationHelperTest.cs
+++ b/src/modules/colorPicker/UnitTest-ColorPickerUI/Helpers/ColorRepresentationHelperTest.cs
@@ -1,5 +1,5 @@
using ColorPicker.Helpers;
-using Microsoft.PowerToys.Settings.UI.Library;
+using Microsoft.PowerToys.Settings.UI.Library.Enumerations;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Drawing;
@@ -11,11 +11,15 @@ namespace UnitTest_ColorPickerUI.Helpers
[TestMethod]
[DataRow(ColorRepresentationType.CMYK, "cmyk(0%, 0%, 0%, 100%)")]
[DataRow(ColorRepresentationType.HEX, "#000000")]
+ [DataRow(ColorRepresentationType.NCol, "R0, 0%, 100%")]
+ [DataRow(ColorRepresentationType.HSB, "hsb(0, 0%, 0%)")]
+ [DataRow(ColorRepresentationType.HSI, "hsi(0, 0%, 0%)")]
[DataRow(ColorRepresentationType.HSL, "hsl(0, 0%, 0%)")]
[DataRow(ColorRepresentationType.HSV, "hsv(0, 0%, 0%)")]
+ [DataRow(ColorRepresentationType.HWB, "hwb(0, 0%, 100%)")]
[DataRow(ColorRepresentationType.RGB, "rgb(0, 0, 0)")]
- public void ColorRGBtoCMYKZeroDiv(ColorRepresentationType type, string expected)
+ public void GetStringRepresentationTest(ColorRepresentationType type, string expected)
{
var result = ColorRepresentationHelper.GetStringRepresentation(Color.Black, type);
Assert.AreEqual(result, expected);