diff --git a/Unicolour.Tests/EqualityTests.cs b/Unicolour.Tests/EqualityTests.cs index 83742df8..04e99319 100644 --- a/Unicolour.Tests/EqualityTests.cs +++ b/Unicolour.Tests/EqualityTests.cs @@ -112,36 +112,12 @@ public void DifferentConfigurationObjects() AssertNotEqual(config1, config2); } - private static Unicolour GetRandomRgbUnicolour() - { - var (r, g, b) = TestColours.GetRandomRgb(); - return Unicolour.FromRgb(r, g, b, TestColours.GetRandomAlpha()); - } - - private static Unicolour GetRandomHsbUnicolour() - { - var (h, s, b) = TestColours.GetRandomHsb(); - return Unicolour.FromHsb(h, s, b, TestColours.GetRandomAlpha()); - } - - private static Unicolour GetRandomHslUnicolour() - { - var (h, s, l) = TestColours.GetRandomHsl(); - return Unicolour.FromHsl(h, s, l, TestColours.GetRandomAlpha()); - } - - private static Unicolour GetRandomXyzUnicolour() - { - var (x, y, z) = TestColours.GetRandomXyz(); - return Unicolour.FromXyz(x, y, z, TestColours.GetRandomAlpha()); - } - - private static Unicolour GetRandomLabUnicolour() - { - var (l, a, b) = TestColours.GetRandomLab(); - return Unicolour.FromLab(l, a, b, TestColours.GetRandomAlpha()); - } - + private static Unicolour GetRandomRgbUnicolour() => Unicolour.FromRgb(TestColours.GetRandomRgb().Tuple, TestColours.GetRandomAlpha()); + private static Unicolour GetRandomHsbUnicolour() => Unicolour.FromHsb(TestColours.GetRandomHsb().Tuple, TestColours.GetRandomAlpha()); + private static Unicolour GetRandomHslUnicolour() => Unicolour.FromHsl(TestColours.GetRandomHsl().Tuple, TestColours.GetRandomAlpha()); + private static Unicolour GetRandomXyzUnicolour() => Unicolour.FromXyz(TestColours.GetRandomXyz().Tuple, TestColours.GetRandomAlpha()); + private static Unicolour GetRandomLabUnicolour() => Unicolour.FromLab(TestColours.GetRandomLab().Tuple, TestColours.GetRandomAlpha()); + private static void AssertUnicoloursEqual(Unicolour unicolour1, Unicolour unicolour2) { AssertEqual(unicolour1.Rgb, unicolour2.Rgb); diff --git a/Unicolour.Tests/InterpolateHsbTests.cs b/Unicolour.Tests/InterpolateHsbTests.cs index b346e054..e91d9ad6 100644 --- a/Unicolour.Tests/InterpolateHsbTests.cs +++ b/Unicolour.Tests/InterpolateHsbTests.cs @@ -1,6 +1,5 @@ namespace Wacton.Unicolour.Tests; -using System; using NUnit.Framework; public class InterpolateHsbTests diff --git a/Unicolour.Tests/InterpolateHslTests.cs b/Unicolour.Tests/InterpolateHslTests.cs index 407ae57d..854a3fde 100644 --- a/Unicolour.Tests/InterpolateHslTests.cs +++ b/Unicolour.Tests/InterpolateHslTests.cs @@ -1,6 +1,5 @@ namespace Wacton.Unicolour.Tests; -using System; using NUnit.Framework; public class InterpolateHslTests diff --git a/Unicolour.Tests/InterpolateLabTests.cs b/Unicolour.Tests/InterpolateLabTests.cs index bfb7e5c1..9cbb5572 100644 --- a/Unicolour.Tests/InterpolateLabTests.cs +++ b/Unicolour.Tests/InterpolateLabTests.cs @@ -1,6 +1,5 @@ namespace Wacton.Unicolour.Tests; -using System; using NUnit.Framework; public class InterpolateLabTests diff --git a/Unicolour.Tests/InterpolateMonochromeTests.cs b/Unicolour.Tests/InterpolateMonochromeTests.cs index 0f7b2c8c..839e9ff8 100644 --- a/Unicolour.Tests/InterpolateMonochromeTests.cs +++ b/Unicolour.Tests/InterpolateMonochromeTests.cs @@ -95,13 +95,6 @@ public void MonochromeBothHsbColours() AssertHsb(blackToGrey.Hsb, (50, 0, 0.25)); AssertHsb(whiteToGrey.Hsb, (20, 0, 0.75)); } - - private static void AssertHsb(Hsb actualHsb, (double h, double s, double b) expectedHsb) - { - Assert.That(actualHsb.H, Is.EqualTo(expectedHsb.h).Within(0.00000000005)); - Assert.That(actualHsb.S, Is.EqualTo(expectedHsb.s).Within(0.00000000005)); - Assert.That(actualHsb.B, Is.EqualTo(expectedHsb.b).Within(0.00000000005)); - } private static void AssertRgb(Rgb actualRgb, (double r, double g, double b) expectedRgb) { @@ -109,4 +102,11 @@ private static void AssertRgb(Rgb actualRgb, (double r, double g, double b) expe Assert.That(actualRgb.G, Is.EqualTo(expectedRgb.g).Within(0.00000000005)); Assert.That(actualRgb.B, Is.EqualTo(expectedRgb.b).Within(0.00000000005)); } + + private static void AssertHsb(Hsb actualHsb, (double h, double s, double b) expectedHsb) + { + Assert.That(actualHsb.H, Is.EqualTo(expectedHsb.h).Within(0.00000000005)); + Assert.That(actualHsb.S, Is.EqualTo(expectedHsb.s).Within(0.00000000005)); + Assert.That(actualHsb.B, Is.EqualTo(expectedHsb.b).Within(0.00000000005)); + } } \ No newline at end of file diff --git a/Unicolour.Tests/InterpolateRgbTests.cs b/Unicolour.Tests/InterpolateRgbTests.cs index bf3a0d85..8ff98a77 100644 --- a/Unicolour.Tests/InterpolateRgbTests.cs +++ b/Unicolour.Tests/InterpolateRgbTests.cs @@ -1,6 +1,5 @@ namespace Wacton.Unicolour.Tests; -using System; using NUnit.Framework; public class InterpolateRgbTests diff --git a/Unicolour.Tests/InterpolateXyzTests.cs b/Unicolour.Tests/InterpolateXyzTests.cs index af88b2ad..8b96ac3a 100644 --- a/Unicolour.Tests/InterpolateXyzTests.cs +++ b/Unicolour.Tests/InterpolateXyzTests.cs @@ -1,6 +1,5 @@ namespace Wacton.Unicolour.Tests; -using System; using NUnit.Framework; public class InterpolateXyzTests diff --git a/Unicolour.Tests/SmokeTests.cs b/Unicolour.Tests/SmokeTests.cs index 75b9e2ca..45da016c 100644 --- a/Unicolour.Tests/SmokeTests.cs +++ b/Unicolour.Tests/SmokeTests.cs @@ -7,57 +7,121 @@ public static class SmokeTests [Test] public static void UnicolourHex() { - AssertNoError(Unicolour.FromHex("#000000")); - AssertNoError(Unicolour.FromHex("#FFFFFF")); - AssertNoError(Unicolour.FromHex("#667788")); + AssertHex("000000"); + AssertHex("FFFFFF"); + AssertHex("667788"); } [Test] public static void UnicolourRgb255() { - AssertNoError(Unicolour.FromRgb255(0, 0, 0)); - AssertNoError(Unicolour.FromRgb255(255, 255, 255)); - AssertNoError(Unicolour.FromRgb255(124, 125, 126)); + AssertRgb255((0, 0, 0)); + AssertRgb255((255, 255, 255)); + AssertRgb255((124, 125, 126)); } - + [Test] public static void UnicolourRgb() { - AssertNoError(Unicolour.FromRgb(0, 0, 0)); - AssertNoError(Unicolour.FromRgb(1, 1, 1)); - AssertNoError(Unicolour.FromRgb(0.4, 0.5, 0.6)); + AssertRgb((0, 0, 0)); + AssertRgb((1, 1, 1)); + AssertRgb((0.4, 0.5, 0.6)); } [Test] public static void UnicolourHsb() { - AssertNoError(Unicolour.FromHsb(0, 0, 0)); - AssertNoError(Unicolour.FromHsb(360, 1, 1)); - AssertNoError(Unicolour.FromHsb(180, 0.4, 0.6)); + AssertHsb((0, 0, 0)); + AssertHsb((360, 1, 1)); + AssertHsb((180, 0.4, 0.6)); } - + [Test] public static void UnicolourHsl() { - AssertNoError(Unicolour.FromHsl(0, 0, 0)); - AssertNoError(Unicolour.FromHsl(360, 1, 1)); - AssertNoError(Unicolour.FromHsl(180, 0.4, 0.6)); + AssertHsl((0, 0, 0)); + AssertHsl((360, 1, 1)); + AssertHsl((180, 0.4, 0.6)); } - + [Test] public static void UnicolourXyz() { - AssertNoError(Unicolour.FromXyz(0, 0, 0)); - AssertNoError(Unicolour.FromXyz(1, 1, 1)); - AssertNoError(Unicolour.FromXyz(0.4, 0.5, 0.6)); + AssertXyz((0, 0, 0)); + AssertXyz((1, 1, 1)); + AssertXyz((0.4, 0.5, 0.6)); } - + [Test] public static void UnicolourLab() { - AssertNoError(Unicolour.FromLab(0, -128, -128)); - AssertNoError(Unicolour.FromLab(100, 128, 128)); - AssertNoError(Unicolour.FromLab(50, -1, 1)); + AssertLab((0, -128, -128)); + AssertLab((100, 128, 128)); + AssertLab((50, -1, 1)); + } + + private static void AssertRgb((double, double, double) tuple) => AssertInit(tuple, Unicolour.FromRgb, Unicolour.FromRgb, Unicolour.FromRgb, Unicolour.FromRgb); + private static void AssertHsb((double, double, double) tuple) => AssertInit(tuple, Unicolour.FromHsb, Unicolour.FromHsb, Unicolour.FromHsb, Unicolour.FromHsb); + private static void AssertHsl((double, double, double) tuple) => AssertInit(tuple, Unicolour.FromHsl, Unicolour.FromHsl, Unicolour.FromHsl, Unicolour.FromHsl); + private static void AssertXyz((double, double, double) tuple) => AssertInit(tuple, Unicolour.FromXyz, Unicolour.FromXyz, Unicolour.FromXyz, Unicolour.FromXyz); + private static void AssertLab((double, double, double) tuple) => AssertInit(tuple, Unicolour.FromLab, Unicolour.FromLab, Unicolour.FromLab, Unicolour.FromLab); + + private delegate Unicolour FromValues(double first, double second, double third, double alpha = 1.0); + private delegate Unicolour FromValuesWithConfig(Configuration config, double first, double second, double third, double alpha = 1.0); + private delegate Unicolour FromTuple((double first, double second, double third) tuple, double alpha = 1.0); + private delegate Unicolour FromTupleWithConfig(Configuration config, (double first, double second, double third) tuple, double alpha = 1.0); + + private static void AssertInit((double first, double second, double third) tuple, + FromValues fromValues, FromValuesWithConfig fromValuesWithConfig, + FromTuple fromTuple, FromTupleWithConfig fromTupleWithConfig) + { + var (first, second, third) = tuple; + + var expected = fromValues(first, second, third); + AssertNoError(expected, fromValues(first, second, third)); + AssertNoError(expected, fromValues(first, second, third, 1.0)); + AssertNoError(expected, fromValuesWithConfig(Configuration.Default, first, second, third)); + AssertNoError(expected, fromValuesWithConfig(Configuration.Default, first, second, third, 1.0)); + AssertNoError(expected, fromTuple(tuple)); + AssertNoError(expected, fromTuple(tuple, 1.0)); + AssertNoError(expected, fromTupleWithConfig(Configuration.Default, tuple)); + AssertNoError(expected, fromTupleWithConfig(Configuration.Default, tuple, 1.0)); + } + + // dedicated method due to using ints instead of doubles + private static void AssertRgb255((int first, int second, int third) tuple) + { + var (first, second, third) = tuple; + + var expected = Unicolour.FromRgb255(first, second, third); + AssertNoError(expected, Unicolour.FromRgb255(first, second, third)); + AssertNoError(expected, Unicolour.FromRgb255(first, second, third, 255)); + AssertNoError(expected, Unicolour.FromRgb255(Configuration.Default, first, second, third)); + AssertNoError(expected, Unicolour.FromRgb255(Configuration.Default, first, second, third, 255)); + AssertNoError(expected, Unicolour.FromRgb255(tuple)); + AssertNoError(expected, Unicolour.FromRgb255(tuple, 255)); + AssertNoError(expected, Unicolour.FromRgb255(Configuration.Default, tuple)); + AssertNoError(expected, Unicolour.FromRgb255(Configuration.Default, tuple, 255)); + } + + private static void AssertHex(string hex) + { + var withHash = $"#{hex}"; + var withHashAndAlpha = $"#{hex}FF"; + var withoutHash = $"{hex}"; + var withoutHashAndAlpha = $"{hex}FF"; + + var expected = Unicolour.FromHex(withHash); + AssertNoError(expected, Unicolour.FromHex(withHash)); + AssertNoError(expected, Unicolour.FromHex(withHashAndAlpha)); + AssertNoError(expected, Unicolour.FromHex(withoutHash)); + AssertNoError(expected, Unicolour.FromHex(withoutHashAndAlpha)); + } + + private static void AssertNoError(Unicolour expected, Unicolour unicolour) + { + AssertNoError(unicolour); + Assert.That(unicolour, Is.EqualTo(expected)); } private static void AssertNoError(Unicolour unicolour) diff --git a/Unicolour/ColourTuple.cs b/Unicolour/ColourTuple.cs index 696ab29e..e08dfbbb 100644 --- a/Unicolour/ColourTuple.cs +++ b/Unicolour/ColourTuple.cs @@ -5,4 +5,5 @@ public record ColourTuple(double First, double Second, double Third) public double First { get; } = First; public double Second { get; } = Second; public double Third { get; } = Third; + public (double, double, double) Tuple => (First, Second, Third); } \ No newline at end of file diff --git a/Unicolour/Unicolour.csproj b/Unicolour/Unicolour.csproj index b2a20d13..5385c6a1 100644 --- a/Unicolour/Unicolour.csproj +++ b/Unicolour/Unicolour.csproj @@ -15,9 +15,9 @@ netstandard2.0 True Resources\Unicolour.png - 1.1.1 + 1.2.0 colour color converter RGB HSB HSV HSL LAB XYZ color-spaces colour-spaces interpolation comparison contrast luminance deltaE - Fix hue-based interpolation + Enable initialisation from XYZ & LAB values Resources\Unicolour.ico LICENSE diff --git a/Unicolour/UnicolourConstructors.cs b/Unicolour/UnicolourConstructors.cs index 8a745178..cc21f285 100644 --- a/Unicolour/UnicolourConstructors.cs +++ b/Unicolour/UnicolourConstructors.cs @@ -14,22 +14,34 @@ public static Unicolour FromHex(Configuration config, string hex) var (r255, g255, b255, a255) = Utils.ParseColourHex(hex); return FromRgb255(config, r255, g255, b255, a255); } + + public static Unicolour FromRgb255((int r255, int g255, int b255) tuple, int alpha255 = 255) => FromRgb255(Configuration.Default, tuple.r255, tuple.g255, tuple.b255, alpha255); + public static Unicolour FromRgb255(Configuration config, (int r255, int g255, int b255) tuple, int alpha255 = 255) => FromRgb255(config, tuple.r255, tuple.g255, tuple.b255, alpha255); + public static Unicolour FromRgb255(int r255, int g255, int b255, int alpha255 = 255) => FromRgb255(Configuration.Default, r255, g255, b255, alpha255); + public static Unicolour FromRgb255(Configuration config, int r255, int g255, int b255, int alpha255 = 255) => FromRgb(config, r255/255.0, g255/255.0, b255/255.0, alpha255/255.0); - public static Unicolour FromRgb255(int r255, int g255, int b255, int a255 = 255) => FromRgb255(Configuration.Default, r255, g255, b255, a255); - public static Unicolour FromRgb255(Configuration config, int r255, int g255, int b255, int a255 = 255) => FromRgb(config, r255/255.0, g255/255.0, b255/255.0, a255/255.0); - - public static Unicolour FromRgb(double r, double g, double b, double a = 1.0) => FromRgb(Configuration.Default, r, g, b, a); - public static Unicolour FromRgb(Configuration config, double r, double g, double b, double a = 1.0) => new(config, new Rgb(r, g, b, config), new Alpha(a)); + public static Unicolour FromRgb((double r, double g, double b) tuple, double alpha = 1.0) => FromRgb(Configuration.Default, tuple.r, tuple.g, tuple.b, alpha); + public static Unicolour FromRgb(Configuration config, (double r, double g, double b) tuple, double alpha = 1.0) => FromRgb(config, tuple.r, tuple.g, tuple.b, alpha); + public static Unicolour FromRgb(double r, double g, double b, double alpha = 1.0) => FromRgb(Configuration.Default, r, g, b, alpha); + public static Unicolour FromRgb(Configuration config, double r, double g, double b, double alpha = 1.0) => new(config, new Rgb(r, g, b, config), new Alpha(alpha)); - public static Unicolour FromHsb(double h, double s, double b, double a = 1.0) => FromHsb(Configuration.Default, h, s, b, a); - public static Unicolour FromHsb(Configuration config, double h, double s, double b, double a = 1.0) => new(config, new Hsb(h, s, b), new Alpha(a)); + public static Unicolour FromHsb((double h, double s, double b) tuple, double alpha = 1.0) => FromHsb(Configuration.Default, tuple.h, tuple.s, tuple.b, alpha); + public static Unicolour FromHsb(Configuration config, (double h, double s, double b) tuple, double alpha = 1.0) => FromHsb(config, tuple.h, tuple.s, tuple.b, alpha); + public static Unicolour FromHsb(double h, double s, double b, double alpha = 1.0) => FromHsb(Configuration.Default, h, s, b, alpha); + public static Unicolour FromHsb(Configuration config, double h, double s, double b, double alpha = 1.0) => new(config, new Hsb(h, s, b), new Alpha(alpha)); - public static Unicolour FromHsl(double h, double s, double l, double a = 1.0) => FromHsl(Configuration.Default, h, s, l, a); - public static Unicolour FromHsl(Configuration config, double h, double s, double l, double a = 1.0) => new(config, new Hsl(h, s, l), new Alpha(a)); + public static Unicolour FromHsl((double h, double s, double l) tuple, double alpha = 1.0) => FromHsl(Configuration.Default, tuple.h, tuple.s, tuple.l, alpha); + public static Unicolour FromHsl(Configuration config, (double h, double s, double l) tuple, double alpha = 1.0) => FromHsl(config, tuple.h, tuple.s, tuple.l, alpha); + public static Unicolour FromHsl(double h, double s, double l, double alpha = 1.0) => FromHsl(Configuration.Default, h, s, l, alpha); + public static Unicolour FromHsl(Configuration config, double h, double s, double l, double alpha = 1.0) => new(config, new Hsl(h, s, l), new Alpha(alpha)); - public static Unicolour FromXyz(double x, double y, double z, double a = 1.0) => FromXyz(Configuration.Default, x, y, z, a); - public static Unicolour FromXyz(Configuration config, double x, double y, double z, double a = 1.0) => new(config, new Xyz(x, y, z), new Alpha(a)); + public static Unicolour FromXyz((double x, double y, double z) tuple, double alpha = 1.0) => FromXyz(Configuration.Default, tuple.x, tuple.y, tuple.z, alpha); + public static Unicolour FromXyz(Configuration config, (double x, double y, double z) tuple, double alpha = 1.0) => FromXyz(config, tuple.x, tuple.y, tuple.z, alpha); + public static Unicolour FromXyz(double x, double y, double z, double alpha = 1.0) => FromXyz(Configuration.Default, x, y, z, alpha); + public static Unicolour FromXyz(Configuration config, double x, double y, double z, double alpha = 1.0) => new(config, new Xyz(x, y, z), new Alpha(alpha)); + public static Unicolour FromLab((double l, double a, double b) tuple, double alpha = 1.0) => FromLab(Configuration.Default, tuple.l, tuple.a, tuple.b, alpha); + public static Unicolour FromLab(Configuration config, (double l, double a, double b) tuple, double alpha = 1.0) => FromLab(config, tuple.l, tuple.a, tuple.b, alpha); public static Unicolour FromLab(double l, double a, double b, double alpha = 1.0) => FromLab(Configuration.Default, l, a, b, alpha); public static Unicolour FromLab(Configuration config, double l, double a, double b, double alpha = 1.0) => new(config, new Lab(l, a, b), new Alpha(alpha)); } \ No newline at end of file