From 5c6dcb4867e45caac486bf1cfd27dd2801c7f863 Mon Sep 17 00:00:00 2001 From: Shaun Simmons Date: Sat, 9 May 2020 05:21:06 -0400 Subject: [PATCH] Cleanup. TODO: Remove auto-clamping. --- .editorconfig | 4 - .../Color/ColorTestDataAttribute.cs | 28 +++---- PixelPalette.Tests/Color/HslTests.cs | 42 +++++----- PixelPalette.Tests/Color/HsvTests.cs | 77 +++++++++---------- PixelPalette.Tests/Color/RgbTests.cs | 52 ++++--------- PixelPalette.Tests/Color/XyzTests.cs | 5 +- PixelPalette/Bitmap/BitmapUtil.cs | 4 +- PixelPalette/Color/Cmyk.cs | 13 +--- PixelPalette/Color/Hex.cs | 2 +- PixelPalette/Color/Hsl.cs | 14 ++-- PixelPalette/Color/Hsv.cs | 12 +-- PixelPalette/Color/Rgb.cs | 48 ++++++++---- PixelPalette/Color/Xyz.cs | 6 +- PixelPalette/Window/CursorTrailWindow.xaml.cs | 8 +- PixelPalette/Window/MainWindow.xaml.cs | 47 +---------- 15 files changed, 152 insertions(+), 210 deletions(-) diff --git a/.editorconfig b/.editorconfig index feda6d8..475d4c5 100644 --- a/.editorconfig +++ b/.editorconfig @@ -32,11 +32,8 @@ dotnet_naming_rule.method_rule.severity=warning dotnet_naming_rule.method_rule.style=upper_camel_case_underscore_tolerant_style dotnet_naming_rule.method_rule.symbols=method_symbols dotnet_naming_rule.static_readonly_rule.severity=warning -dotnet_naming_rule.static_readonly_rule.style=min_upper_camel_case_style dotnet_naming_rule.static_readonly_rule.symbols=static_readonly_symbols dotnet_naming_style.min_upper_camel_case_style.capitalization=pascal_case -dotnet_naming_style.min_upper_camel_case_style.required_prefix=Min -dotnet_naming_style.upper_camel_case_style.capitalization=pascal_case dotnet_naming_style.upper_camel_case_underscore_tolerant_style.capitalization=pascal_case dotnet_naming_style.upper_camel_case_underscore_tolerant_style.word_separator=_ dotnet_naming_symbols.constants_symbols.applicable_accessibilities=public,internal,protected,protected_internal,private_protected @@ -72,7 +69,6 @@ resharper_csharp_align_multiple_declaration=true resharper_csharp_max_line_length=150 resharper_csharp_naming_rule.constants=AaBb resharper_csharp_naming_rule.method=AaBb_AaBb, AaBb -resharper_csharp_naming_rule.static_readonly=Min + AaBb, Max + AaBb resharper_csharp_outdent_commas=true resharper_csharp_stick_comment=false resharper_csharp_use_indent_from_previous_element=false diff --git a/PixelPalette.Tests/Color/ColorTestDataAttribute.cs b/PixelPalette.Tests/Color/ColorTestDataAttribute.cs index 3c19313..ebe45df 100644 --- a/PixelPalette.Tests/Color/ColorTestDataAttribute.cs +++ b/PixelPalette.Tests/Color/ColorTestDataAttribute.cs @@ -33,7 +33,7 @@ public IEnumerable GetData(MethodInfo methodInfo) Rgb = new Rgb(0, 0, 0), Hsl = new Hsl(0, 0, 0), Hsv = new Hsv(0, 0, 0), - Cmyk = new Cmyk(0, 0, 0, 100), + Cmyk = new Cmyk(0, 0, 0, 1), Xyz = new Xyz(0, 0, 0), Lab = new Lab(0, 0, 0) } @@ -43,9 +43,9 @@ public IEnumerable GetData(MethodInfo methodInfo) new ColorData { Name = "White", - Rgb = new Rgb(255, 255, 255), - Hsl = Hsl.FromScaledValues(0, 0, 100), - Hsv = Hsv.FromScaledValues(0, 0, 100), + Rgb = new Rgb(1, 1, 1), + Hsl = new Hsl(0, 0, 1), + Hsv = new Hsv(0, 0, 1), Cmyk = new Cmyk(0, 0, 0, 0), Xyz = new Xyz(95.047, 100, 108.883), Lab = new Lab(100, 0, 0) @@ -56,10 +56,10 @@ public IEnumerable GetData(MethodInfo methodInfo) new ColorData { Name = "Red", - Rgb = new Rgb(255, 0, 0), - Hsl = Hsl.FromScaledValues(0, 100, 50), - Hsv = Hsv.FromScaledValues(0, 100, 100), - Cmyk = new Cmyk(0, 100, 100, 0), + Rgb = new Rgb(1, 0, 0), + Hsl = new Hsl(0, 1, 0.5), + Hsv = new Hsv(0, 1, 1), + Cmyk = new Cmyk(0, 1, 1, 0), Xyz = new Xyz(41.2456, 21.2673, 1.9334), Lab = new Lab(53.2408, 80.0925, 67.2032) } @@ -69,10 +69,10 @@ public IEnumerable GetData(MethodInfo methodInfo) new ColorData { Name = "Green", - Rgb = new Rgb(0, 255, 0), + Rgb = new Rgb(0, 1, 0), Hsl = Hsl.FromScaledValues(120, 100, 50), Hsv = Hsv.FromScaledValues(120, 100, 100), - Cmyk = new Cmyk(100, 0, 100, 0), + Cmyk = new Cmyk(1, 0, 1, 0), Xyz = new Xyz(35.7576, 71.5152, 11.9192), Lab = new Lab(87.7347, -86.1827, 83.1793) } @@ -82,10 +82,10 @@ public IEnumerable GetData(MethodInfo methodInfo) new ColorData { Name = "Blue", - Rgb = new Rgb(0, 0, 255), + Rgb = new Rgb(0, 0, 1), Hsl = Hsl.FromScaledValues(240, 100, 50), Hsv = Hsv.FromScaledValues(240, 100, 100), - Cmyk = new Cmyk(100, 100, 0, 0), + Cmyk = new Cmyk(1, 1, 0, 0), Xyz = new Xyz(18.0437, 7.2175, 95.0304), Lab = new Lab(32.297, 79.1875, -107.8602) } @@ -95,10 +95,10 @@ public IEnumerable GetData(MethodInfo methodInfo) new ColorData { Name = "Material Blue", - Rgb = new Rgb(33, 150, 243), + Rgb = Rgb.FromScaledValues(33, 150, 243), Hsl = Hsl.FromScaledValues(206.5716, 89.744, 54.118), Hsv = Hsv.FromScaledValues(206.5716, 86.42, 95.294), - Cmyk = new Cmyk(86.419753, 38.271604, 0, 4.705882), + Cmyk = Cmyk.FromScaledValues(86.419753, 38.271604, 0, 4.705882), Xyz = new Xyz(27.704960365063513, 28.60350077011483, 88.83745176406208), Lab = new Lab(60.4301, 2.0799, -55.1094) } diff --git a/PixelPalette.Tests/Color/HslTests.cs b/PixelPalette.Tests/Color/HslTests.cs index 79ae509..99bfe85 100644 --- a/PixelPalette.Tests/Color/HslTests.cs +++ b/PixelPalette.Tests/Color/HslTests.cs @@ -70,7 +70,10 @@ public void FromScaledString_ShouldReturnObject( [TestMethod, ColorTestData] public void ColorConversions_ShouldBeAccurate(ColorData color) { - color.Hsl.ToRgb().ShouldBeEquivalentTo(color.Rgb); + var rgb = color.Hsl.ToRgb(); + rgb.RoundedRed.ShouldBeEquivalentTo(color.Rgb.RoundedRed); + rgb.RoundedGreen.ShouldBeEquivalentTo(color.Rgb.RoundedGreen); + rgb.RoundedBlue.ShouldBeEquivalentTo(color.Rgb.RoundedBlue); var hsv = color.Hsl.ToHsv(); hsv.RoundedHue.ShouldBeEquivalentTo(color.Hsv.RoundedHue); @@ -81,15 +84,16 @@ public void ColorConversions_ShouldBeAccurate(ColorData color) [TestMethod] public void ToRgb_ShouldBeCorrect_AtMaxHue() { - var hsl = Hsl.FromScaledValues(360, 50, 50); - hsl.ToRgb().ShouldBeEquivalentTo(new Rgb(191, 64, 64)); + var rgb = Hsl.FromScaledValues(360, 50, 50).ToRgb(); + rgb.ScaledRed.ShouldBeEquivalentTo(191); + rgb.ScaledGreen.ShouldBeEquivalentTo(64); + rgb.ScaledBlue.ShouldBeEquivalentTo(64); } [TestMethod] public void ToHsv_ShouldBeCorrect_AtMaxHue() { - var hsl = Hsl.FromScaledValues(360, 50, 50); - var hsv = hsl.ToHsv(); + var hsv = Hsl.FromScaledValues(360, 50, 50).ToHsv(); hsv.RoundedScaledHue.ShouldBe(360); hsv.RoundedScaledSaturation.ShouldBe(66.67); hsv.RoundedScaledValue.ShouldBe(75); @@ -98,8 +102,7 @@ public void ToHsv_ShouldBeCorrect_AtMaxHue() [TestMethod] public void ToHsv_ShouldBeCorrect_AtDecimals() { - var hsl = Hsl.FromScaledValues(60.2, 53, 70.91); - var hsv = hsl.ToHsv(); + var hsv = Hsl.FromScaledValues(60.2, 53, 70.91).ToHsv(); hsv.RoundedScaledHue.ShouldBe(60.2); hsv.RoundedScaledSaturation.ShouldBe(35.72); hsv.RoundedScaledValue.ShouldBe(86.33); @@ -108,8 +111,15 @@ public void ToHsv_ShouldBeCorrect_AtDecimals() [TestMethod] public void ToRgb_ShouldBeCorrect_AtDecimals() { - var hsl = Hsl.FromScaledValues(60.2, 53, 70.91); - hsl.ToRgb().ShouldBeEquivalentTo(new Rgb(220, 220, 142)); + var rgb = Hsl.FromScaledValues(60.2, 53, 70.91).ToRgb(); + rgb.ScaledRed.ShouldBeEquivalentTo(220); + rgb.ScaledGreen.ShouldBeEquivalentTo(220); + rgb.ScaledBlue.ShouldBeEquivalentTo(142); + + rgb = Hsl.FromScaledValues(60.5, 53, 70.91).ToRgb(); + rgb.ScaledRed.ShouldBeEquivalentTo(219); + rgb.ScaledGreen.ShouldBeEquivalentTo(220); + rgb.ScaledBlue.ShouldBeEquivalentTo(142); } [TestMethod] @@ -133,21 +143,15 @@ public void Darker_ShouldDecreaseLightness() [TestMethod] public void Hue_ShouldBeClamped() { - var hsl = Hsl.FromScaledValues(-0.01, 100, 100); - hsl.ScaledHue.ShouldBe(0); - - hsl = Hsl.FromScaledValues(360.01, 100, 100); - hsl.ScaledHue.ShouldBe(360); + Hsl.FromScaledValues(-0.01, 100, 100).ScaledHue.ShouldBe(0); + Hsl.FromScaledValues(360.01, 100, 100).ScaledHue.ShouldBe(360); } [TestMethod] public void Saturation_ShouldBeClamped() { - var hsl = Hsl.FromScaledValues(120, -1, 100); - hsl.ScaledSaturation.ShouldBe(0); - - hsl = Hsl.FromScaledValues(120, 101, 100); - hsl.ScaledSaturation.ShouldBe(100); + Hsl.FromScaledValues(120, -1, 100).ScaledSaturation.ShouldBe(0); + Hsl.FromScaledValues(120, 101, 100).ScaledSaturation.ShouldBe(100); } [TestMethod] diff --git a/PixelPalette.Tests/Color/HsvTests.cs b/PixelPalette.Tests/Color/HsvTests.cs index 55183ce..3611454 100644 --- a/PixelPalette.Tests/Color/HsvTests.cs +++ b/PixelPalette.Tests/Color/HsvTests.cs @@ -40,7 +40,10 @@ public void FromScaledString_ShouldReturnObject( [TestMethod, ColorTestData] public void ColorConversions_ShouldBeAccurate(ColorData color) { - color.Hsv.ToRgb().ShouldBeEquivalentTo(color.Rgb); + var rgb = color.Hsv.ToRgb(); + rgb.RoundedRed.ShouldBeEquivalentTo(color.Rgb.RoundedRed); + rgb.RoundedGreen.ShouldBeEquivalentTo(color.Rgb.RoundedGreen); + rgb.RoundedBlue.ShouldBeEquivalentTo(color.Rgb.RoundedBlue); var hsl = color.Hsv.ToHsl(); hsl.RoundedHue.ShouldBeEquivalentTo(color.Hsl.RoundedHue); @@ -51,32 +54,39 @@ public void ColorConversions_ShouldBeAccurate(ColorData color) [TestMethod] public void ToRgb_ShouldBeCorrect_AtMaxHue() { - var hsv = Hsv.FromScaledValues(360, 50, 50); - hsv.ToRgb().ShouldBeEquivalentTo(new Rgb(128, 64, 64)); - } - - [TestMethod] - public void ToRgb_ShouldBeCorrect_AtDecimals() - { - var hsv = Hsv.FromScaledValues(60.2, 53, 70.91); - hsv.ToRgb().ShouldBeEquivalentTo(new Rgb(181, 181, 85)); + var rgb = Hsv.FromScaledValues(360, 50, 50).ToRgb(); + rgb.ScaledRed.ShouldBeEquivalentTo(128); + rgb.ScaledGreen.ShouldBeEquivalentTo(64); + rgb.ScaledBlue.ShouldBeEquivalentTo(64); } [TestMethod] public void ToHsl_ShouldBeCorrect_AtMaxHue() { - var hsv = Hsv.FromScaledValues(360, 50, 50); - var hsl = hsv.ToHsl(); + var hsl = Hsv.FromScaledValues(360, 50, 50).ToHsl(); hsl.RoundedScaledHue.ShouldBe(360); hsl.RoundedScaledSaturation.ShouldBe(33.33); hsl.RoundedScaledLuminance.ShouldBe(37.5); } + [TestMethod] + public void ToRgb_ShouldBeCorrect_AtDecimals() + { + var rgb = Hsv.FromScaledValues(60.2, 53, 70.91).ToRgb(); + rgb.ScaledRed.ShouldBeEquivalentTo(181); + rgb.ScaledGreen.ShouldBeEquivalentTo(181); + rgb.ScaledBlue.ShouldBeEquivalentTo(85); + + rgb = Hsv.FromScaledValues(60.3, 53, 70.91).ToRgb(); + rgb.ScaledRed.ShouldBeEquivalentTo(180); + rgb.ScaledGreen.ShouldBeEquivalentTo(181); + rgb.ScaledBlue.ShouldBeEquivalentTo(85); + } + [TestMethod] public void ToHsl_ShouldBeCorrect_AtDecimals() { - var hsv = Hsv.FromScaledValues(60.2, 53, 70.91); - var hsl = hsv.ToHsl(); + var hsl = Hsv.FromScaledValues(60.2, 53, 70.91).ToHsl(); hsl.RoundedScaledHue.ShouldBe(60.2); hsl.RoundedScaledSaturation.ShouldBe(39.25); hsl.RoundedScaledLuminance.ShouldBe(52.12); @@ -85,67 +95,52 @@ public void ToHsl_ShouldBeCorrect_AtDecimals() [TestMethod] public void Hue_ShouldBeClamped() { - var hsv = Hsv.FromScaledValues(-0.01, 100, 100); - hsv.ScaledHue.ShouldBe(0); - - hsv = new Hsv(360.01, 100, 100); - hsv.ScaledHue.ShouldBe(360); + Hsv.FromScaledValues(-0.01, 100, 100).ScaledHue.ShouldBe(0); + new Hsv(360.01, 100, 100).ScaledHue.ShouldBe(360); } [TestMethod] public void Saturation_ShouldBeClamped() { - var hsv = Hsv.FromScaledValues(120, -1, 100); - hsv.ScaledSaturation.ShouldBe(0); - - hsv = Hsv.FromScaledValues(120, 101, 100); - hsv.ScaledSaturation.ShouldBe(100); + Hsv.FromScaledValues(120, -1, 100).ScaledSaturation.ShouldBe(0); + Hsv.FromScaledValues(120, 101, 100).ScaledSaturation.ShouldBe(100); } [TestMethod] public void Value_ShouldBeClamped() { - var hsv = Hsv.FromScaledValues(120, 0, -1); - hsv.ScaledValue.ShouldBe(0); - - hsv = Hsv.FromScaledValues(120, 0, 101); - hsv.ScaledValue.ShouldBe(100); + Hsv.FromScaledValues(120, 0, -1).ScaledValue.ShouldBe(0); + Hsv.FromScaledValues(120, 0, 101).ScaledValue.ShouldBe(100); } [TestMethod] public void RoundedHue_ShouldRound() { // Half-up - var hsv = Hsv.FromScaledValues(240.585, 100, 50); - hsv.RoundedScaledHue.ShouldBe(240.59); + Hsv.FromScaledValues(240.585, 100, 50).RoundedScaledHue.ShouldBe(240.59); // Down - hsv = Hsv.FromScaledValues(240.584, 100, 50); - hsv.RoundedScaledHue.ShouldBe(240.58); + Hsv.FromScaledValues(240.584, 100, 50).RoundedScaledHue.ShouldBe(240.58); } [TestMethod] public void RoundedSaturation100_ShouldRound() { // Half-up - var hsv = Hsv.FromScaledValues(240, 59.645, 100); - hsv.RoundedScaledSaturation.ShouldBe(59.65); + Hsv.FromScaledValues(240, 59.645, 100).RoundedScaledSaturation.ShouldBe(59.65); // Down - hsv = Hsv.FromScaledValues(240, 59.644, 100); - hsv.RoundedScaledSaturation.ShouldBe(59.64); + Hsv.FromScaledValues(240, 59.644, 100).RoundedScaledSaturation.ShouldBe(59.64); } [TestMethod] public void RoundedValue100_ShouldRound() { // Half-up - var hsv = Hsv.FromScaledValues(240, 100, 59.645); - hsv.RoundedScaledValue.ShouldBe(59.65); + Hsv.FromScaledValues(240, 100, 59.645).RoundedScaledValue.ShouldBe(59.65); // Down - hsv = Hsv.FromScaledValues(240, 100, 59.644); - hsv.RoundedScaledValue.ShouldBe(59.64); + Hsv.FromScaledValues(240, 100, 59.644).RoundedScaledValue.ShouldBe(59.64); } } } \ No newline at end of file diff --git a/PixelPalette.Tests/Color/RgbTests.cs b/PixelPalette.Tests/Color/RgbTests.cs index be42b99..fff75a4 100644 --- a/PixelPalette.Tests/Color/RgbTests.cs +++ b/PixelPalette.Tests/Color/RgbTests.cs @@ -1,4 +1,5 @@ -using PixelPalette.Color; +using System; +using PixelPalette.Color; using Microsoft.VisualStudio.TestTools.UnitTesting; using Shouldly; @@ -144,45 +145,22 @@ public void ColorConversions_ShouldBeAccurate(ColorData color) } [TestMethod] - public void Red_ShouldBeClamped() + public void NewRgb_WithOutOfRangeValue_ShouldThrowException() { - var rgb = new Rgb(-1, 0, 0); - rgb.ScaledRed.ShouldBe(0); - rgb = new Rgb(256, 0, 0); - rgb.ScaledRed.ShouldBe(255); + Assert.ThrowsException(() => new Rgb(-0.1, 0, 0)); + Assert.ThrowsException(() => new Rgb(1.1, 0, 0)); + Assert.ThrowsException(() => Rgb.FromScaledValues(-1, 0, 0)); + Assert.ThrowsException(() => Rgb.FromScaledValues(256, 0, 0)); - rgb = new Rgb(-0.1, 0, 0); - rgb.Red.ShouldBe(0.0); - rgb = new Rgb(1.1, 0, 0); - rgb.Red.ShouldBe(1.0); - } - - [TestMethod] - public void Green_ShouldBeClamped() - { - var rgb = new Rgb(0, -1, 0); - rgb.ScaledGreen.ShouldBe(0); - rgb = new Rgb(0, 256, 0); - rgb.ScaledGreen.ShouldBe(255); + Assert.ThrowsException(() => new Rgb(0, -0.1, 0)); + Assert.ThrowsException(() => new Rgb(0, 1.1, 0)); + Assert.ThrowsException(() => Rgb.FromScaledValues(0, -1, 0)); + Assert.ThrowsException(() => Rgb.FromScaledValues(0, 256, 0)); - rgb = new Rgb(0, -0.1, 0); - rgb.Green.ShouldBe(0.0); - rgb = new Rgb(0, 1.1, 0); - rgb.Green.ShouldBe(1.0); - } - - [TestMethod] - public void Blue_ShouldBeClamped() - { - var rgb = new Rgb(0, 0, -1); - rgb.ScaledBlue.ShouldBe(0); - rgb = new Rgb(0, 0, 256); - rgb.ScaledBlue.ShouldBe(255); - - rgb = new Rgb(0, 0, -0.1); - rgb.Blue.ShouldBe(0.0); - rgb = new Rgb(0, 0, 1.1); - rgb.Blue.ShouldBe(1.0); + Assert.ThrowsException(() => new Rgb(0, 0, -0.1)); + Assert.ThrowsException(() => new Rgb(0, 0, 1.1)); + Assert.ThrowsException(() => Rgb.FromScaledValues(0, 0, -1)); + Assert.ThrowsException(() => Rgb.FromScaledValues(0, 0, 256)); } } } \ No newline at end of file diff --git a/PixelPalette.Tests/Color/XyzTests.cs b/PixelPalette.Tests/Color/XyzTests.cs index 0f1f81f..7173b4e 100644 --- a/PixelPalette.Tests/Color/XyzTests.cs +++ b/PixelPalette.Tests/Color/XyzTests.cs @@ -10,7 +10,10 @@ public class XyzTests [TestMethod, ColorTestData] public void ColorConversions_ShouldBeAccurate(ColorData color) { - color.Xyz.ToRgb().ShouldBeEquivalentTo(color.Rgb); + var rgb = color.Xyz.ToRgb(); + rgb.ScaledRed.ShouldBeEquivalentTo(color.Rgb.ScaledRed); + rgb.ScaledGreen.ShouldBeEquivalentTo(color.Rgb.ScaledGreen); + rgb.ScaledBlue.ShouldBeEquivalentTo(color.Rgb.ScaledBlue); var lab = color.Xyz.ToLab(); lab.RoundedL.ShouldBeEquivalentTo(color.Lab.RoundedL); diff --git a/PixelPalette/Bitmap/BitmapUtil.cs b/PixelPalette/Bitmap/BitmapUtil.cs index 92515e6..a224422 100644 --- a/PixelPalette/Bitmap/BitmapUtil.cs +++ b/PixelPalette/Bitmap/BitmapUtil.cs @@ -100,7 +100,7 @@ public static Rgb PixelToRgb(BitmapSource source, int x, int y) var rect = new Int32Rect(x, y, 1, 1); source.CopyPixels(rect, bytes, bytesPerPixel, 0); - return new Rgb(bytes[2], bytes[1], bytes[0]); + return Rgb.FromScaledValues(bytes[2], bytes[1], bytes[0]); } public static Rgb AverageColor(BitmapSource source) @@ -125,7 +125,7 @@ public static Rgb AverageColor(BitmapSource source) red += pixelBuffer[i + 2]; } - return new Rgb((byte) (red / numPixels), (byte) (green / numPixels), (byte) (blue / numPixels)); + return Rgb.FromScaledValues((byte) (red / numPixels), (byte) (green / numPixels), (byte) (blue / numPixels)); } } } \ No newline at end of file diff --git a/PixelPalette/Color/Cmyk.cs b/PixelPalette/Color/Cmyk.cs index d631308..66edbf2 100644 --- a/PixelPalette/Color/Cmyk.cs +++ b/PixelPalette/Color/Cmyk.cs @@ -152,7 +152,6 @@ public static bool IsValidScaledComponent(double value) var y = double.Parse(match.Groups["y"].Value); var k = double.Parse(match.Groups["k"].Value); return FromScaledValues(c, m, y, k); - } public static double ClampedComponent(double v) @@ -233,15 +232,11 @@ public Rgb ToRgb() var y1 = Yellow; var k1 = Key; - var r = 255 * (1 - c1) * (1 - k1); - var g = 255 * (1 - m1) * (1 - k1); - var b = 255 * (1 - y1) * (1 - k1); + var r = (1 - c1) * (1 - k1); + var g = (1 - m1) * (1 - k1); + var b = (1 - y1) * (1 - k1); - return new Rgb( - (int) Math.Round(r, 0, MidpointRounding.ToPositiveInfinity), - (int) Math.Round(g, 0, MidpointRounding.ToPositiveInfinity), - (int) Math.Round(b, 0, MidpointRounding.ToPositiveInfinity) - ); + return new Rgb(r, g, b); } public bool Equals(Cmyk other) diff --git a/PixelPalette/Color/Hex.cs b/PixelPalette/Color/Hex.cs index b0e88af..8eed1d8 100644 --- a/PixelPalette/Color/Hex.cs +++ b/PixelPalette/Color/Hex.cs @@ -116,7 +116,7 @@ public override string ToString() public Rgb ToRgb() { - return new Rgb(_red, _green, _blue); + return Rgb.FromScaledValues(_red, _green, _blue); } public static bool IsValidHex(string hex) diff --git a/PixelPalette/Color/Hsl.cs b/PixelPalette/Color/Hsl.cs index a061c36..0334999 100644 --- a/PixelPalette/Color/Hsl.cs +++ b/PixelPalette/Color/Hsl.cs @@ -74,6 +74,9 @@ public readonly struct Hsl /// public double RoundedScaledLuminance => Round(ScaledLuminance, 2); + /// 0-1 + /// 0-1 + /// 0-1 public Hsl(double h, double s, double l) { Hue = ClampedHue(h); @@ -81,6 +84,9 @@ public Hsl(double h, double s, double l) Luminance = ClampedLuminance(l); } + /// 0-360 + /// 0-100 + /// 0-100 public static Hsl FromScaledValues(double h, double s, double l) { return new Hsl( @@ -298,11 +304,7 @@ public Rgb ToRgb() b1 = X; } - return new Rgb( - Convert.ToInt32((r1 + m) * 255), - Convert.ToInt32((g1 + m) * 255), - Convert.ToInt32((b1 + m) * 255) - ); + return new Rgb(Rgb.ClampedComponent(r1 + m), Rgb.ClampedComponent(g1 + m), Rgb.ClampedComponent(b1 + m)); } public Hsv ToHsv() @@ -317,7 +319,7 @@ public Hsv ToHsv() var sat = 0.0; if (val > 0) { - sat = 2 * (1 - (lum1 / val)); + sat = 2 * (1 - lum1 / val); } return new Hsv(hue / 360.0, sat, val); diff --git a/PixelPalette/Color/Hsv.cs b/PixelPalette/Color/Hsv.cs index 629c587..46c3c88 100644 --- a/PixelPalette/Color/Hsv.cs +++ b/PixelPalette/Color/Hsv.cs @@ -77,6 +77,9 @@ public readonly struct Hsv /// public double RoundedScaledValue => Round(ScaledValue, 2); + /// 0-1 + /// 0-1 + /// 0-1 public Hsv(double h, double s, double v) { Hue = ClampedHue(h); @@ -84,6 +87,9 @@ public Hsv(double h, double s, double v) Value = ClampedValue(v); } + /// 0-360 + /// 0-100 + /// 0-100 public static Hsv FromScaledValues(double h, double s, double v) { return new Hsv( @@ -285,11 +291,7 @@ public Rgb ToRgb() b1 = X; } - return new Rgb( - Convert.ToInt32((r1 + m) * 255), - Convert.ToInt32((g1 + m) * 255), - Convert.ToInt32((b1 + m) * 255) - ); + return new Rgb(Rgb.ClampedComponent(r1 + m), Rgb.ClampedComponent(g1 + m), Rgb.ClampedComponent(b1 + m)); } public Hsl ToHsl() diff --git a/PixelPalette/Color/Rgb.cs b/PixelPalette/Color/Rgb.cs index c07e926..fce2879 100644 --- a/PixelPalette/Color/Rgb.cs +++ b/PixelPalette/Color/Rgb.cs @@ -75,9 +75,9 @@ public readonly struct Rgb /// public int Brightness => (int) Math.Sqrt( - Red * Red * .241 + - Green * Green * .691 + - Blue * Blue * .068 + ScaledRed * ScaledRed * .241 + + ScaledGreen * ScaledGreen * .691 + + ScaledBlue * ScaledBlue * .068 ); /// @@ -85,21 +85,37 @@ public readonly struct Rgb /// public Rgb ContrastingTextColor() { - return Brightness < 130 ? new Rgb(255, 255, 255) : new Rgb(0, 0, 0); + return Brightness < 130 ? new Rgb(1.0, 1.0, 1.0) : new Rgb(0.0, 0.0, 0.0); } + /// 0-1 + /// 0-1 + /// 0-1 + /// Thrown when a value is out-of-range public Rgb(double r, double g, double b) { - Red = ClampedComponent(r); - Green = ClampedComponent(g); - Blue = ClampedComponent(b); + // 0..360-range integers may unintentionally be used as arguments and be implicitly cast to doubles. + // That can still happen, but there's a good chance of catching it so long as the value is > 1. + if (!IsValidComponent(r)) throw new ArgumentException(@"Value is out-of-range", nameof(r)); + if (!IsValidComponent(g)) throw new ArgumentException(@"Value is out-of-range", nameof(g)); + if (!IsValidComponent(b)) throw new ArgumentException(@"Value is out-of-range", nameof(b)); + + Red = r; + Green = g; + Blue = b; } - public Rgb(int r, int g, int b) + /// 0-255 + /// 0-255 + /// 0-255 + /// Thrown when a value is out-of-range + public static Rgb FromScaledValues(int r, int g, int b) { - Red = ClampedComponent(r) / 255.0; - Green = ClampedComponent(g) / 255.0; - Blue = ClampedComponent(b) / 255.0; + if (!IsValidScaledComponent(r)) throw new ArgumentException(@"Value is out-of-range", nameof(r)); + if (!IsValidScaledComponent(g)) throw new ArgumentException(@"Value is out-of-range", nameof(g)); + if (!IsValidScaledComponent(b)) throw new ArgumentException(@"Value is out-of-range", nameof(b)); + + return new Rgb(r / 255.0, g / 255.0, b / 255.0); } public static bool IsValidString(string theString) @@ -159,7 +175,7 @@ public static bool IsValidScaledComponent(int value) var g = int.Parse(match.Groups["green"].Value); var b = int.Parse(match.Groups["blue"].Value); if (!IsValidScaledComponent(r) || !IsValidScaledComponent(g) || !IsValidScaledComponent(b)) return null; - return new Rgb(r, g, b); + return FromScaledValues(r, g, b); } public static double ClampedComponent(double c) @@ -189,17 +205,17 @@ public Rgb WithBlue(double b) public Rgb WithRed(int r) { - return new Rgb(r / 255.0, Green, Blue); + return FromScaledValues(r, ScaledGreen, ScaledBlue); } public Rgb WithGreen(int g) { - return new Rgb(Red, g / 255.0, Blue); + return FromScaledValues(ScaledRed, g, ScaledBlue); } public Rgb WithBlue(int b) { - return new Rgb(Red, Green, b / 255.0); + return FromScaledValues(ScaledRed, ScaledGreen, b); } private static double Round(double d, int precision = 3) @@ -368,7 +384,7 @@ public Cmyk ToCmyk() yellow = (1 - b1 - key) / (1 - key); } - return new Cmyk(cyan * 100, magenta * 100, yellow * 100, key * 100); + return new Cmyk(cyan, magenta, yellow, key); } /// diff --git a/PixelPalette/Color/Xyz.cs b/PixelPalette/Color/Xyz.cs index c7612e6..3ee9ac6 100644 --- a/PixelPalette/Color/Xyz.cs +++ b/PixelPalette/Color/Xyz.cs @@ -132,11 +132,7 @@ public Rgb ToRgb() b1 = 12.92 * b1; } - return new Rgb( - Convert.ToInt32(r1 * 255), - Convert.ToInt32(g1 * 255), - Convert.ToInt32(b1 * 255) - ); + return new Rgb(Rgb.ClampedComponent(r1), Rgb.ClampedComponent(g1), Rgb.ClampedComponent(b1)); } [SuppressMessage("ReSharper", "InconsistentNaming")] diff --git a/PixelPalette/Window/CursorTrailWindow.xaml.cs b/PixelPalette/Window/CursorTrailWindow.xaml.cs index 0c75238..611a356 100644 --- a/PixelPalette/Window/CursorTrailWindow.xaml.cs +++ b/PixelPalette/Window/CursorTrailWindow.xaml.cs @@ -40,7 +40,7 @@ public CursorTrailWindow() PreviewContainer.Width = gridWidth; PreviewContainer.Height = gridWidth; - #region Draw grid lines +#region Draw grid lines for (var x = 1; x < numColumns; x += 1) { @@ -86,10 +86,10 @@ public CursorTrailWindow() }; PreviewContainer.Children.Add(hLineCrosshair); - #endregion +#endregion - #region Render the color preview +#region Render the color preview var winHeight = (int) Height; @@ -143,7 +143,7 @@ public CursorTrailWindow() }; _timer.Start(); - #endregion +#endregion } private void Window_Closing(object sender, CancelEventArgs cancelEventArgs) diff --git a/PixelPalette/Window/MainWindow.xaml.cs b/PixelPalette/Window/MainWindow.xaml.cs index 0c5ff32..fd19146 100644 --- a/PixelPalette/Window/MainWindow.xaml.cs +++ b/PixelPalette/Window/MainWindow.xaml.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.ComponentModel; -using System.Globalization; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Controls; @@ -65,50 +64,6 @@ private static void HandleMouseWheel(IInputElement control, [CanBeNull] Action u HandleMouseWheel(new[] {control}, upAction, downAction); } - // Shortcut method - private static void HandleInput(IEnumerable controls, Action action) - { - foreach (var control in controls) - { - control.TextChanged += (o, ev) => - { - if (!IsActiveControl(control)) return; - action(control.Text, control); - }; - } - } - - private static void HandleInput(TextBox control, Action action) - { - HandleInput(new[] {control}, action); - } - - // Shortcut method - private static void HandleInputEnterOrFocusLost(IEnumerable controls, Action action) - { - foreach (var control in controls) - { - void HandleIt() - { - var text = control.Text; - action(text, control); - } - - control.KeyDown += (o, ev) => - { - if (ev.Key != Key.Enter) return; - HandleIt(); - }; - - control.LostFocus += (o, ev) => { HandleIt(); }; - } - } - - private static void HandleInputEnterOrFocusLost(TextBox control, Action action) - { - HandleInputEnterOrFocusLost(new[] {control}, action); - } - // Shortcut method private static void HandleSliderChange(Slider control, Action action) { @@ -129,7 +84,7 @@ public MainWindow() if (_vm.Rgb == Rgb.Empty) { // Material Blue – #2196F3 - _vm.RefreshFromRgb(new Rgb(33, 150, 243)); + _vm.RefreshFromRgb(Rgb.FromScaledValues(33, 150, 243)); } // Eyedropper