diff --git a/README.md b/README.md index 12141bea..8c20a4b2 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,17 @@ Unicolour is a .NET library written in C# for working with colour: - Colour information - Colour gamut mapping +[🧭 Overview](#-overview)
+[âš¡ Quickstart](#-quickstart)
+[🔦 Features](#-features)
+[🌈 How to use](#-how-to-use)
+[✨ Examples](#-examples)
+[💡 Configuration](#-configuration)
+[🔮 Datasets](#-datasets)
+ Targets [.NET Standard 2.0](https://docs.microsoft.com/en-us/dotnet/standard/net-standard?tabs=net-standard-2-0) for use in .NET 5.0+, .NET Core 2.0+ and .NET Framework 4.6.1+ applications. -## Overview 🧭 +## 🧭 Overview A `Unicolour` encapsulates a single colour and its representation across different colour spaces. It supports: - RGB @@ -49,7 +57,12 @@ For each forward transformation there is a corresponding reverse transformation. XYZ is considered the root colour space. -## Quickstart âš¡ +This library was initially written for personal projects since existing libraries had complex APIs or missing features. +The goal of this library is to be accurate, intuitive, and easy to use. +Although performance is not a priority, conversions are only calculated once; when first evaluated (either on access or as part of an intermediate conversion step) the result is stored for future use. +It is also [extensively tested](Unicolour.Tests), including verification of roundtrip conversions, validation using known colour values, and 100% line coverage and branch coverage. + +## âš¡ Quickstart | Colour space | Create | Get | |-----------------------------------------|---------------------------------|----------------| | RGB (Hex) | `new(hex)` | `.Hex` | @@ -76,7 +89,7 @@ XYZ is considered the root colour space. | CAM16 | `new(ColourSpace.Cam16, ⋯)` | `.Cam16` | | HCT | `new(ColourSpace.Hct, ⋯)` | `.Hct` | -## Features 🔦 +## 🔦 Features A `Unicolour` can be instantiated using any of the supported colour spaces. Conversion to other colour spaces is handled by Unicolour, and the results can be accessed through properties. @@ -109,14 +122,9 @@ If a colour is outwith the display gamut, the closest in-gamut colour can be obt The algorithm implemented in Unicolour conforms to CSS specifications. Unicolour uses sRGB as the default RGB model and standard illuminant D65 (2° observer) as the default white point of the XYZ colour space. -These [can be overridden](#advanced-configuration-) using the `Configuration` parameter. +These [can be overridden](#-configuration) using the `Configuration` parameter. -This library was initially written for personal projects since existing libraries had complex APIs or missing features. -The goal of this library is to be accurate, intuitive, and easy to use. -Although performance is not a priority, conversions are only calculated once; when first evaluated (either on access or as part of an intermediate conversion step) the result is stored for future use. -It is also [extensively tested](Unicolour.Tests), including verification of roundtrip conversions, validation using known colour values, and 100% line coverage and branch coverage. - -## How to use 🌈 +## 🌈 How to use 1. Install the package from [NuGet](https://www.nuget.org/packages/Wacton.Unicolour/) ``` dotnet add package Wacton.Unicolour @@ -242,7 +250,7 @@ var tritanopia = unicolour.SimulateTritanopia(); var achromatopsia = unicolour.SimulateAchromatopsia(); ``` -## Examples ✨ +## ✨ Examples This repo contains an [example project](Unicolour.Example/Program.cs) that uses `Unicolour` to: 1. Generate gradients through different colour spaces 2. Render the colour spectrum with different colour vision deficiencies @@ -258,7 +266,7 @@ There is also a [console application](Unicolour.Console/Program.cs) that uses `U ![Colour information from hex value](Unicolour.Console/colour-info.png) -## Advanced configuration 💡 +## 💡 Configuration A `Configuration` parameter can be used to customise the RGB model (e.g. Display P3, Rec. 2020) and the white point of the XYZ colour space (e.g. D50 reference white used by ICC profiles). @@ -301,28 +309,28 @@ and Jzazbz scalar. The default white point used by all colour spaces is D65. This table lists which `Configuration` property determines the white point of each colour space. -| Colour space | Configuration | -|-----------------------------------------|---------------------| -| RGB | `RgbConfiguration` | -| Linear RGB | `RgbConfiguration` | -| HSB/HSV | `RgbConfiguration` | -| HSL | `RgbConfiguration` | -| HWB | `RgbConfiguration` | -| CIEXYZ | `XyzConfiguration` | -| CIExyY | `XyzConfiguration` | -| CIELAB | `XyzConfiguration` | -| CIELUV | `XyzConfiguration` | -| CIELChuv | `XyzConfiguration` | -| HSLuv | `XyzConfiguration` | -| HPLuv | `XyzConfiguration` | -| ICTCP | None _(always D65)_ | -| Jzazbz | None _(always D65)_ | -| JzCzhz | None _(always D65)_ | -| Oklab | None _(always D65)_ | -| Oklch | None _(always D65)_ | -| CIECAM02 | `CamConfiguration` | -| CAM16 | `CamConfiguration` | -| HCT | None _(always D65)_ | +| Colour space | White point configuration | +|-----------------------------------------|-------------------------------------| +| RGB | `RgbConfiguration` | +| Linear RGB | `RgbConfiguration` | +| HSB/HSV | `RgbConfiguration` | +| HSL | `RgbConfiguration` | +| HWB | `RgbConfiguration` | +| CIEXYZ | `XyzConfiguration` | +| CIExyY | `XyzConfiguration` | +| CIELAB | `XyzConfiguration` | +| CIELUV | `XyzConfiguration` | +| CIELChuv | `XyzConfiguration` | +| HSLuv | `XyzConfiguration` | +| HPLuv | `XyzConfiguration` | +| ICTCP | None (always D65) | +| Jzazbz | None (always D65) | +| JzCzhz | None (always D65) | +| Oklab | None (always D65) | +| Oklch | None (always D65) | +| CIECAM02 | `CamConfiguration` | +| CAM16 | `CamConfiguration` | +| HCT | None (always D65) | A `Unicolour` can be converted to a different configuration, which enables conversions between different RGB and XYZ models. @@ -343,6 +351,34 @@ var unicolourRec2020 = unicolourDisplayP3.ConvertToConfiguration(rec202Config); Console.WriteLine(unicolourRec2020.Rgb); // 0.57 0.96 0.27 ``` +## 🔮 Datasets +Some colour datasets have been compiled for convenience and are available as a [NuGet package](https://www.nuget.org/packages/Wacton.Unicolour/). + +Commonly used sets of colours: +- [CSS specification](https://www.w3.org/TR/css-color-4/#named-colors) named colours +- [Macbeth ColorChecker](https://en.wikipedia.org/wiki/ColorChecker) colour rendition chart + +Colour data used in academic literature: +- [Hung-Berns](https://doi.org/10.1002/col.5080200506) constant hue loci data +- [Ebner-Fairchild](https://doi.org/10.1117/12.298269) constant perceived-hue data + +Example usage: + +1. Install the package from [NuGet](https://www.nuget.org/packages/Wacton.Unicolour.Datasets/) +``` +dotnet add package Wacton.Unicolour.Datasets +``` + +2. Import the package +```c# +using Wacton.Unicolour.Datasets; +``` + +3. Reference the predefined `Unicolour` +```c# +var unicolour = Css.DeepPink; +``` + --- [Wacton.Unicolour](https://github.com/waacton/Unicolour) is licensed under the [MIT License](https://choosealicense.com/licenses/mit/), copyright © 2022-2023 William Acton. diff --git a/Unicolour.Datasets/Css.cs b/Unicolour.Datasets/Css.cs new file mode 100644 index 00000000..d78db93f --- /dev/null +++ b/Unicolour.Datasets/Css.cs @@ -0,0 +1,352 @@ +namespace Wacton.Unicolour.Datasets; + +public static class Css +{ + /* + * NOTE: cannot currently provide Unicolours that behave exactly to the CSS specification + * - CSS 'lab' & 'lch' uses D50 illuminant + * - CSS 'xyz' uses D65 illuminant + * - Unicolour uses illuminant from XyzConfig for both LAB & XYZ, so by default LAB values will appear different + * could add dedicated `LabConfiguration` easily enough if it became desirable, + * but until then it's easy enough to use `.ConvertToConfiguration()` to get the expected values + * (see PremultipliedAlphaTests.cs for examples) + */ + private static readonly Configuration Config = new(RgbConfiguration.StandardRgb, XyzConfiguration.D65); + + public static readonly Unicolour AliceBlue = new(Config, "#F0F8FF"); + public static readonly Unicolour AntiqueWhite = new(Config, "#FAEBD7"); + public static readonly Unicolour Aqua = new(Config, "#00FFFF"); + public static readonly Unicolour Aquamarine = new(Config, "#7FFFD4"); + public static readonly Unicolour Azure = new(Config, "#F0FFFF"); + public static readonly Unicolour Beige = new(Config, "#F5F5DC"); + public static readonly Unicolour Bisque = new(Config, "#FFE4C4"); + public static readonly Unicolour Black = new(Config, "#000000"); + public static readonly Unicolour BlanchedAlmond = new(Config, "#FFEBCD"); + public static readonly Unicolour Blue = new(Config, "#0000FF"); + public static readonly Unicolour BlueViolet = new(Config, "#8A2BE2"); + public static readonly Unicolour Brown = new(Config, "#A52A2A"); + public static readonly Unicolour Burlywood = new(Config, "#DEB887"); + public static readonly Unicolour CadetBlue = new(Config, "#5F9EA0"); + public static readonly Unicolour Chartreuse = new(Config, "#7FFF00"); + public static readonly Unicolour Chocolate = new(Config, "#D2691E"); + public static readonly Unicolour Coral = new(Config, "#FF7F50"); + public static readonly Unicolour CornflowerBlue = new(Config, "#6495ED"); + public static readonly Unicolour Cornsilk = new(Config, "#FFF8DC"); + public static readonly Unicolour Crimson = new(Config, "#DC143C"); + public static readonly Unicolour Cyan = new(Config, "#00FFFF"); + public static readonly Unicolour DarkBlue = new(Config, "#00008B"); + public static readonly Unicolour DarkCyan = new(Config, "#008B8B"); + public static readonly Unicolour DarkGoldenrod = new(Config, "#B8860B"); + public static readonly Unicolour DarkGray = new(Config, "#A9A9A9"); + public static readonly Unicolour DarkGreen = new(Config, "#006400"); + public static readonly Unicolour DarkGrey = new(Config, "#A9A9A9"); + public static readonly Unicolour DarkKhaki = new(Config, "#BDB76B"); + public static readonly Unicolour DarkMagenta = new(Config, "#8B008B"); + public static readonly Unicolour DarkOliveGreen = new(Config, "#556B2F"); + public static readonly Unicolour DarkOrange = new(Config, "#FF8C00"); + public static readonly Unicolour DarkOrchid = new(Config, "#9932CC"); + public static readonly Unicolour DarkRed = new(Config, "#8B0000"); + public static readonly Unicolour DarkSalmon = new(Config, "#E9967A"); + public static readonly Unicolour DarkSeaGreen = new(Config, "#8FBC8F"); + public static readonly Unicolour DarkSlateBlue = new(Config, "#483D8B"); + public static readonly Unicolour DarkSlateGray = new(Config, "#2F4F4F"); + public static readonly Unicolour DarkSlateGrey = new(Config, "#2F4F4F"); + public static readonly Unicolour DarkTurquoise = new(Config, "#00CED1"); + public static readonly Unicolour DarkViolet = new(Config, "#9400D3"); + public static readonly Unicolour DeepPink = new(Config, "#FF1493"); + public static readonly Unicolour DeepSkyBlue = new(Config, "#00BFFF"); + public static readonly Unicolour DimGray = new(Config, "#696969"); + public static readonly Unicolour DimGrey = new(Config, "#696969"); + public static readonly Unicolour DodgerBlue = new(Config, "#1E90FF"); + public static readonly Unicolour FireBrick = new(Config, "#B22222"); + public static readonly Unicolour FloralWhite = new(Config, "#FFFAF0"); + public static readonly Unicolour ForestGreen = new(Config, "#228B22"); + public static readonly Unicolour Fuchsia = new(Config, "#FF00FF"); + public static readonly Unicolour Gainsboro = new(Config, "#DCDCDC"); + public static readonly Unicolour GhostWhite = new(Config, "#F8F8FF"); + public static readonly Unicolour Gold = new(Config, "#FFD700"); + public static readonly Unicolour Goldenrod = new(Config, "#DAA520"); + public static readonly Unicolour Gray = new(Config, "#808080"); + public static readonly Unicolour Green = new(Config, "#008000"); + public static readonly Unicolour GreenYellow = new(Config, "#ADFF2F"); + public static readonly Unicolour Grey = new(Config, "#808080"); + public static readonly Unicolour Honeydew = new(Config, "#F0FFF0"); + public static readonly Unicolour HotPink = new(Config, "#FF69B4"); + public static readonly Unicolour IndianRed = new(Config, "#CD5C5C"); + public static readonly Unicolour Indigo = new(Config, "#4B0082"); + public static readonly Unicolour Ivory = new(Config, "#FFFFF0"); + public static readonly Unicolour Khaki = new(Config, "#F0E68C"); + public static readonly Unicolour Lavender = new(Config, "#E6E6FA"); + public static readonly Unicolour LavenderBlush = new(Config, "#FFF0F5"); + public static readonly Unicolour LawnGreen = new(Config, "#7CFC00"); + public static readonly Unicolour LemonChiffon = new(Config, "#FFFACD"); + public static readonly Unicolour LightBlue = new(Config, "#ADD8E6"); + public static readonly Unicolour LightCoral = new(Config, "#F08080"); + public static readonly Unicolour LightCyan = new(Config, "#E0FFFF"); + public static readonly Unicolour LightGoldenrodYellow = new(Config, "#FAFAD2"); + public static readonly Unicolour LightGray = new(Config, "#D3D3D3"); + public static readonly Unicolour LightGreen = new(Config, "#90EE90"); + public static readonly Unicolour LightGrey = new(Config, "#D3D3D3"); + public static readonly Unicolour LightPink = new(Config, "#FFB6C1"); + public static readonly Unicolour LightSalmon = new(Config, "#FFA07A"); + public static readonly Unicolour LightSeaGreen = new(Config, "#20B2AA"); + public static readonly Unicolour LightSkyBlue = new(Config, "#87CEFA"); + public static readonly Unicolour LightSlateGray = new(Config, "#778899"); + public static readonly Unicolour LightSlateGrey = new(Config, "#778899"); + public static readonly Unicolour LightSteelBlue = new(Config, "#B0C4DE"); + public static readonly Unicolour LightYellow = new(Config, "#FFFFE0"); + public static readonly Unicolour Lime = new(Config, "#00FF00"); + public static readonly Unicolour LimeGreen = new(Config, "#32CD32"); + public static readonly Unicolour Linen = new(Config, "#FAF0E6"); + public static readonly Unicolour Magenta = new(Config, "#FF00FF"); + public static readonly Unicolour Maroon = new(Config, "#800000"); + public static readonly Unicolour MediumAquamarine = new(Config, "#66CDAA"); + public static readonly Unicolour MediumBlue = new(Config, "#0000CD"); + public static readonly Unicolour MediumOrchid = new(Config, "#BA55D3"); + public static readonly Unicolour MediumPurple = new(Config, "#9370DB"); + public static readonly Unicolour MediumSeaGreen = new(Config, "#3CB371"); + public static readonly Unicolour MediumSlateBlue = new(Config, "#7B68EE"); + public static readonly Unicolour MediumSpringGreen = new(Config, "#00FA9A"); + public static readonly Unicolour MediumTurquoise = new(Config, "#48D1CC"); + public static readonly Unicolour MediumVioletRed = new(Config, "#C71585"); + public static readonly Unicolour MidnightBlue = new(Config, "#191970"); + public static readonly Unicolour MintCream = new(Config, "#F5FFFA"); + public static readonly Unicolour MistyRose = new(Config, "#FFE4E1"); + public static readonly Unicolour Moccasin = new(Config, "#FFE4B5"); + public static readonly Unicolour NavajoWhite = new(Config, "#FFDEAD"); + public static readonly Unicolour Navy = new(Config, "#000080"); + public static readonly Unicolour OldLace = new(Config, "#FDF5E6"); + public static readonly Unicolour Olive = new(Config, "#808000"); + public static readonly Unicolour OliveDrab = new(Config, "#6B8E23"); + public static readonly Unicolour Orange = new(Config, "#FFA500"); + public static readonly Unicolour OrangeRed = new(Config, "#FF4500"); + public static readonly Unicolour Orchid = new(Config, "#DA70D6"); + public static readonly Unicolour PaleGoldenrod = new(Config, "#EEE8AA"); + public static readonly Unicolour PaleGreen = new(Config, "#98FB98"); + public static readonly Unicolour PaleTurquoise = new(Config, "#AFEEEE"); + public static readonly Unicolour PaleVioletRed = new(Config, "#DB7093"); + public static readonly Unicolour PapayaWhip = new(Config, "#FFEFD5"); + public static readonly Unicolour PeachPuff = new(Config, "#FFDAB9"); + public static readonly Unicolour Peru = new(Config, "#CD853F"); + public static readonly Unicolour Pink = new(Config, "#FFC0CB"); + public static readonly Unicolour Plum = new(Config, "#DDA0DD"); + public static readonly Unicolour PowderBlue = new(Config, "#B0E0E6"); + public static readonly Unicolour Purple = new(Config, "#800080"); + public static readonly Unicolour RebeccaPurple = new(Config, "#663399"); + public static readonly Unicolour Red = new(Config, "#FF0000"); + public static readonly Unicolour RosyBrown = new(Config, "#BC8F8F"); + public static readonly Unicolour RoyalBlue = new(Config, "#4169E1"); + public static readonly Unicolour SaddleBrown = new(Config, "#8B4513"); + public static readonly Unicolour Salmon = new(Config, "#FA8072"); + public static readonly Unicolour SandyBrown = new(Config, "#F4A460"); + public static readonly Unicolour SeaGreen = new(Config, "#2E8B57"); + public static readonly Unicolour Seashell = new(Config, "#FFF5EE"); + public static readonly Unicolour Sienna = new(Config, "#A0522D"); + public static readonly Unicolour Silver = new(Config, "#C0C0C0"); + public static readonly Unicolour SkyBlue = new(Config, "#87CEEB"); + public static readonly Unicolour SlateBlue = new(Config, "#6A5ACD"); + public static readonly Unicolour SlateGray = new(Config, "#708090"); + public static readonly Unicolour SlateGrey = new(Config, "#708090"); + public static readonly Unicolour Snow = new(Config, "#FFFAFA"); + public static readonly Unicolour SpringGreen = new(Config, "#00FF7F"); + public static readonly Unicolour SteelBlue = new(Config, "#4682B4"); + public static readonly Unicolour Tan = new(Config, "#D2B48C"); + public static readonly Unicolour Teal = new(Config, "#008080"); + public static readonly Unicolour Thistle = new(Config, "#D8BFD8"); + public static readonly Unicolour Tomato = new(Config, "#FF6347"); + public static readonly Unicolour Turquoise = new(Config, "#40E0D0"); + public static readonly Unicolour Violet = new(Config, "#EE82EE"); + public static readonly Unicolour Wheat = new(Config, "#F5DEB3"); + public static readonly Unicolour White = new(Config, "#FFFFFF"); + public static readonly Unicolour WhiteSmoke = new(Config, "#F5F5F5"); + public static readonly Unicolour Yellow = new(Config, "#FFFF00"); + public static readonly Unicolour YellowGreen = new(Config, "#9ACD32"); + + // TODO: hex constructor that takes hex with 0-1 alpha + // (will need to handle alpha present in both hex string and alpha param) + public static readonly Unicolour Transparent = new(Config, "#00000000"); + + public static IEnumerable All => new List + { + AliceBlue, AntiqueWhite, Aqua, Aquamarine, Azure, + Beige, Bisque, Black, BlanchedAlmond, Blue, BlueViolet, Brown, Burlywood, + CadetBlue, Chartreuse, Chocolate, Coral, CornflowerBlue, Cornsilk, Crimson, Cyan, + DarkBlue, DarkCyan, DarkGoldenrod, DarkGray, DarkGreen, DarkGrey, DarkKhaki, DarkMagenta, DarkOliveGreen, DarkOrange, DarkOrchid, DarkRed, DarkSalmon, DarkSeaGreen, DarkSlateBlue, DarkSlateGray, DarkSlateGrey, DarkTurquoise, DarkViolet, DeepPink, DeepSkyBlue, DimGray, DimGrey, DodgerBlue, + FireBrick, FloralWhite, ForestGreen, Fuchsia, + Gainsboro, GhostWhite, Gold, Goldenrod, Gray, Green, GreenYellow, Grey, + Honeydew, HotPink, + IndianRed, Indigo, Ivory, + Khaki, + Lavender, LavenderBlush, LawnGreen, LemonChiffon, LightBlue, LightCoral, LightCyan, LightGoldenrodYellow, LightGray, LightGreen, LightGrey, LightPink, LightSalmon, LightSeaGreen, LightSkyBlue, LightSlateGray, LightSlateGrey, LightSteelBlue, LightYellow, Lime, LimeGreen, Linen, + Magenta, Maroon, MediumAquamarine, MediumBlue, MediumOrchid, MediumPurple, MediumSeaGreen, MediumSlateBlue, MediumSpringGreen, MediumTurquoise, MediumVioletRed, MidnightBlue, MintCream, MistyRose, Moccasin, + NavajoWhite, Navy, + OldLace, Olive, OliveDrab, Orange, OrangeRed, Orchid, + PaleGoldenrod, PaleGreen, PaleTurquoise, PaleVioletRed, PapayaWhip, PeachPuff, Peru, Pink, Plum, PowderBlue, Purple, + RebeccaPurple, Red, RosyBrown, RoyalBlue, + SaddleBrown, Salmon, SandyBrown, SeaGreen, Seashell, Sienna, Silver, SkyBlue, SlateBlue, SlateGray, SlateGrey, Snow, SpringGreen, SteelBlue, + Tan, Teal, Thistle, Tomato, Turquoise, + Violet, + Wheat, White, WhiteSmoke, + Yellow, YellowGreen + }; + + public static Unicolour? FromName(string name) + { + if (string.IsNullOrWhiteSpace(name)) return null; + var key = string.Concat(name.Where(x => !char.IsWhiteSpace(x))).ToLower(); + return Lookup.TryGetValue(key, out Unicolour? value) ? value : null; + } + + private static readonly Dictionary Lookup = new() + { + { nameof(AliceBlue).ToLower(), AliceBlue }, + { nameof(AntiqueWhite).ToLower(), AntiqueWhite }, + { nameof(Aqua).ToLower(), Aqua }, + { nameof(Aquamarine).ToLower(), Aquamarine }, + { nameof(Azure).ToLower(), Azure }, + { nameof(Beige).ToLower(), Beige }, + { nameof(Bisque).ToLower(), Bisque }, + { nameof(Black).ToLower(), Black }, + { nameof(BlanchedAlmond).ToLower(), BlanchedAlmond }, + { nameof(Blue).ToLower(), Blue }, + { nameof(BlueViolet).ToLower(), BlueViolet }, + { nameof(Brown).ToLower(), Brown }, + { nameof(Burlywood).ToLower(), Burlywood }, + { nameof(CadetBlue).ToLower(), CadetBlue }, + { nameof(Chartreuse).ToLower(), Chartreuse }, + { nameof(Chocolate).ToLower(), Chocolate }, + { nameof(Coral).ToLower(), Coral }, + { nameof(CornflowerBlue).ToLower(), CornflowerBlue }, + { nameof(Cornsilk).ToLower(), Cornsilk }, + { nameof(Crimson).ToLower(), Crimson }, + { nameof(Cyan).ToLower(), Cyan }, + { nameof(DarkBlue).ToLower(), DarkBlue }, + { nameof(DarkCyan).ToLower(), DarkCyan }, + { nameof(DarkGoldenrod).ToLower(), DarkGoldenrod }, + { nameof(DarkGray).ToLower(), DarkGray }, + { nameof(DarkGreen).ToLower(), DarkGreen }, + { nameof(DarkGrey).ToLower(), DarkGrey }, + { nameof(DarkKhaki).ToLower(), DarkKhaki }, + { nameof(DarkMagenta).ToLower(), DarkMagenta }, + { nameof(DarkOliveGreen).ToLower(), DarkOliveGreen }, + { nameof(DarkOrange).ToLower(), DarkOrange }, + { nameof(DarkOrchid).ToLower(), DarkOrchid }, + { nameof(DarkRed).ToLower(), DarkRed }, + { nameof(DarkSalmon).ToLower(), DarkSalmon }, + { nameof(DarkSeaGreen).ToLower(), DarkSeaGreen }, + { nameof(DarkSlateBlue).ToLower(), DarkSlateBlue }, + { nameof(DarkSlateGray).ToLower(), DarkSlateGray }, + { nameof(DarkSlateGrey).ToLower(), DarkSlateGrey }, + { nameof(DarkTurquoise).ToLower(), DarkTurquoise }, + { nameof(DarkViolet).ToLower(), DarkViolet }, + { nameof(DeepPink).ToLower(), DeepPink }, + { nameof(DeepSkyBlue).ToLower(), DeepSkyBlue }, + { nameof(DimGray).ToLower(), DimGray }, + { nameof(DimGrey).ToLower(), DimGrey }, + { nameof(DodgerBlue).ToLower(), DodgerBlue }, + { nameof(FireBrick).ToLower(), FireBrick }, + { nameof(FloralWhite).ToLower(), FloralWhite }, + { nameof(ForestGreen).ToLower(), ForestGreen }, + { nameof(Fuchsia).ToLower(), Fuchsia }, + { nameof(Gainsboro).ToLower(), Gainsboro }, + { nameof(GhostWhite).ToLower(), GhostWhite }, + { nameof(Gold).ToLower(), Gold }, + { nameof(Goldenrod).ToLower(), Goldenrod }, + { nameof(Gray).ToLower(), Gray }, + { nameof(Green).ToLower(), Green }, + { nameof(GreenYellow).ToLower(), GreenYellow }, + { nameof(Grey).ToLower(), Grey }, + { nameof(Honeydew).ToLower(), Honeydew }, + { nameof(HotPink).ToLower(), HotPink }, + { nameof(IndianRed).ToLower(), IndianRed }, + { nameof(Indigo).ToLower(), Indigo }, + { nameof(Ivory).ToLower(), Ivory }, + { nameof(Khaki).ToLower(), Khaki }, + { nameof(Lavender).ToLower(), Lavender }, + { nameof(LavenderBlush).ToLower(), LavenderBlush }, + { nameof(LawnGreen).ToLower(), LawnGreen }, + { nameof(LemonChiffon).ToLower(), LemonChiffon }, + { nameof(LightBlue).ToLower(), LightBlue }, + { nameof(LightCoral).ToLower(), LightCoral }, + { nameof(LightCyan).ToLower(), LightCyan }, + { nameof(LightGoldenrodYellow).ToLower(), LightGoldenrodYellow }, + { nameof(LightGray).ToLower(), LightGray }, + { nameof(LightGreen).ToLower(), LightGreen }, + { nameof(LightGrey).ToLower(), LightGrey }, + { nameof(LightPink).ToLower(), LightPink }, + { nameof(LightSalmon).ToLower(), LightSalmon }, + { nameof(LightSeaGreen).ToLower(), LightSeaGreen }, + { nameof(LightSkyBlue).ToLower(), LightSkyBlue }, + { nameof(LightSlateGray).ToLower(), LightSlateGray }, + { nameof(LightSlateGrey).ToLower(), LightSlateGrey }, + { nameof(LightSteelBlue).ToLower(), LightSteelBlue }, + { nameof(LightYellow).ToLower(), LightYellow }, + { nameof(Lime).ToLower(), Lime }, + { nameof(LimeGreen).ToLower(), LimeGreen }, + { nameof(Linen).ToLower(), Linen }, + { nameof(Magenta).ToLower(), Magenta }, + { nameof(Maroon).ToLower(), Maroon }, + { nameof(MediumAquamarine).ToLower(), MediumAquamarine }, + { nameof(MediumBlue).ToLower(), MediumBlue }, + { nameof(MediumOrchid).ToLower(), MediumOrchid }, + { nameof(MediumPurple).ToLower(), MediumPurple }, + { nameof(MediumSeaGreen).ToLower(), MediumSeaGreen }, + { nameof(MediumSlateBlue).ToLower(), MediumSlateBlue }, + { nameof(MediumSpringGreen).ToLower(), MediumSpringGreen }, + { nameof(MediumTurquoise).ToLower(), MediumTurquoise }, + { nameof(MediumVioletRed).ToLower(), MediumVioletRed }, + { nameof(MidnightBlue).ToLower(), MidnightBlue }, + { nameof(MintCream).ToLower(), MintCream }, + { nameof(MistyRose).ToLower(), MistyRose }, + { nameof(Moccasin).ToLower(), Moccasin }, + { nameof(NavajoWhite).ToLower(), NavajoWhite }, + { nameof(Navy).ToLower(), Navy }, + { nameof(OldLace).ToLower(), OldLace }, + { nameof(Olive).ToLower(), Olive }, + { nameof(OliveDrab).ToLower(), OliveDrab }, + { nameof(Orange).ToLower(), Orange }, + { nameof(OrangeRed).ToLower(), OrangeRed }, + { nameof(Orchid).ToLower(), Orchid }, + { nameof(PaleGoldenrod).ToLower(), PaleGoldenrod }, + { nameof(PaleGreen).ToLower(), PaleGreen }, + { nameof(PaleTurquoise).ToLower(), PaleTurquoise }, + { nameof(PaleVioletRed).ToLower(), PaleVioletRed }, + { nameof(PapayaWhip).ToLower(), PapayaWhip }, + { nameof(PeachPuff).ToLower(), PeachPuff }, + { nameof(Peru).ToLower(), Peru }, + { nameof(Pink).ToLower(), Pink }, + { nameof(Plum).ToLower(), Plum }, + { nameof(PowderBlue).ToLower(), PowderBlue }, + { nameof(Purple).ToLower(), Purple }, + { nameof(RebeccaPurple).ToLower(), RebeccaPurple }, + { nameof(Red).ToLower(), Red }, + { nameof(RosyBrown).ToLower(), RosyBrown }, + { nameof(RoyalBlue).ToLower(), RoyalBlue }, + { nameof(SaddleBrown).ToLower(), SaddleBrown }, + { nameof(Salmon).ToLower(), Salmon }, + { nameof(SandyBrown).ToLower(), SandyBrown }, + { nameof(SeaGreen).ToLower(), SeaGreen }, + { nameof(Seashell).ToLower(), Seashell }, + { nameof(Sienna).ToLower(), Sienna }, + { nameof(Silver).ToLower(), Silver }, + { nameof(SkyBlue).ToLower(), SkyBlue }, + { nameof(SlateBlue).ToLower(), SlateBlue }, + { nameof(SlateGray).ToLower(), SlateGray }, + { nameof(SlateGrey).ToLower(), SlateGrey }, + { nameof(Snow).ToLower(), Snow }, + { nameof(SpringGreen).ToLower(), SpringGreen }, + { nameof(SteelBlue).ToLower(), SteelBlue }, + { nameof(Tan).ToLower(), Tan }, + { nameof(Teal).ToLower(), Teal }, + { nameof(Thistle).ToLower(), Thistle }, + { nameof(Tomato).ToLower(), Tomato }, + { nameof(Turquoise).ToLower(), Turquoise }, + { nameof(Violet).ToLower(), Violet }, + { nameof(Wheat).ToLower(), Wheat }, + { nameof(White).ToLower(), White }, + { nameof(WhiteSmoke).ToLower(), WhiteSmoke }, + { nameof(Yellow).ToLower(), Yellow }, + { nameof(YellowGreen).ToLower(), YellowGreen }, + { nameof(Transparent).ToLower(), Transparent } + }; +} \ No newline at end of file diff --git a/Unicolour.Datasets/EbnerFairchild.cs b/Unicolour.Datasets/EbnerFairchild.cs index aab1135a..e1c49ef6 100644 --- a/Unicolour.Datasets/EbnerFairchild.cs +++ b/Unicolour.Datasets/EbnerFairchild.cs @@ -1,5 +1,6 @@ namespace Wacton.Unicolour.Datasets; +// https://zenodo.org/records/3362536 · https://doi.org/10.1117/12.298269 public static class EbnerFairchild { private static readonly Xyz WhiteXyz = new(0.9501, 1.0000, 1.0881); diff --git a/Unicolour.Datasets/HungBerns.cs b/Unicolour.Datasets/HungBerns.cs index d90f245d..718c11a3 100644 --- a/Unicolour.Datasets/HungBerns.cs +++ b/Unicolour.Datasets/HungBerns.cs @@ -1,5 +1,6 @@ namespace Wacton.Unicolour.Datasets; +// https://zenodo.org/records/3367463 · https://doi.org/10.1002/col.5080200506 public static class HungBerns { private static readonly Xyy WhiteXyy = new(0.3101, 0.3163, 1.000); diff --git a/Unicolour.Datasets/Unicolour.Datasets.csproj b/Unicolour.Datasets/Unicolour.Datasets.csproj index 1066854f..882f74ab 100644 --- a/Unicolour.Datasets/Unicolour.Datasets.csproj +++ b/Unicolour.Datasets/Unicolour.Datasets.csproj @@ -7,10 +7,28 @@ Wacton.Unicolour.Datasets Wacton.Unicolour.Datasets 10 + true + 1.0.0 + William Acton + Datasets for use with 🌈 Wacton.Unicolour + William Acton + https://github.com/waacton/Unicolour + Unicolour.png + https://github.com/waacton/Unicolour + unicolour colour color colour-data color-data colour-dataset color-dataset + Predefine datasets for use with Wacton.Unicolour + + + True + + Unicolour.png + + + diff --git a/Unicolour.Example/Program.cs b/Unicolour.Example/Program.cs index 8ef409af..026a103d 100644 --- a/Unicolour.Example/Program.cs +++ b/Unicolour.Example/Program.cs @@ -1,4 +1,5 @@ using Wacton.Unicolour; +using Wacton.Unicolour.Datasets; using Wacton.Unicolour.Example; GenerateColourSpaceGradients(); @@ -20,7 +21,7 @@ void GenerateColourSpaceGradients() var black = new Unicolour(ColourSpace.Rgb, 0, 0, 0); var green = new Unicolour(ColourSpace.Rgb, 0, 1, 0); - var light = new Unicolour("#E8E8FF"); + var lightText = new Unicolour("#E8E8FF"); var column1 = DrawColumn(new[] { purple, orange }); var column2 = DrawColumn(new[] { pink, cyan }); var column3 = DrawColumn(new[] { black, green }); @@ -37,27 +38,27 @@ void GenerateColourSpaceGradients() Image DrawColumn(Unicolour[] colourPoints) { - var rgb = Gradient.Draw(("RGB", light), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Rgb, end, amount)); - var rgbLinear = Gradient.Draw(("RGB Linear", light), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.RgbLinear, end, amount)); - var hsb = Gradient.Draw(("HSB", light), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Hsb, end, amount)); - var hsl = Gradient.Draw(("HSL", light), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Hsl, end, amount)); - var hwb = Gradient.Draw(("HWB", light), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Hwb, end, amount)); - var xyz = Gradient.Draw(("XYZ", light), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Xyz, end, amount)); - var xyy = Gradient.Draw(("xyY", light), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Xyy, end, amount)); - var lab = Gradient.Draw(("LAB", light), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Lab, end, amount)); - var lchab = Gradient.Draw(("LCHab", light), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Lchab, end, amount)); - var luv = Gradient.Draw(("LUV", light), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Luv, end, amount)); - var lchuv = Gradient.Draw(("LCHuv", light), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Lchuv, end, amount)); - var hsluv = Gradient.Draw(("HSLuv", light), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Hsluv, end, amount)); - var hpluv = Gradient.Draw(("HPLuv", light), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Hpluv, end, amount)); - var ictcp = Gradient.Draw(("ICtCp", light), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Ictcp, end, amount)); - var jzazbz = Gradient.Draw(("JzAzBz", light), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Jzazbz, end, amount)); - var jzczhz = Gradient.Draw(("JzCzHz", light), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Jzczhz, end, amount)); - var oklab = Gradient.Draw(("OKLAB", light), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Oklab, end, amount)); - var oklch = Gradient.Draw(("OKLCH", light), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Oklch, end, amount)); - var cam02 = Gradient.Draw(("CAM02", light), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Cam02, end, amount)); - var cam16 = Gradient.Draw(("CAM16", light), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Cam16, end, amount)); - var hct = Gradient.Draw(("HCT", light), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Hct, end, amount)); + var rgb = Gradient.Draw(("RGB", lightText), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Rgb, end, amount)); + var rgbLinear = Gradient.Draw(("RGB Linear", lightText), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.RgbLinear, end, amount)); + var hsb = Gradient.Draw(("HSB", lightText), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Hsb, end, amount)); + var hsl = Gradient.Draw(("HSL", lightText), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Hsl, end, amount)); + var hwb = Gradient.Draw(("HWB", lightText), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Hwb, end, amount)); + var xyz = Gradient.Draw(("XYZ", lightText), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Xyz, end, amount)); + var xyy = Gradient.Draw(("xyY", lightText), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Xyy, end, amount)); + var lab = Gradient.Draw(("LAB", lightText), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Lab, end, amount)); + var lchab = Gradient.Draw(("LCHab", lightText), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Lchab, end, amount)); + var luv = Gradient.Draw(("LUV", lightText), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Luv, end, amount)); + var lchuv = Gradient.Draw(("LCHuv", lightText), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Lchuv, end, amount)); + var hsluv = Gradient.Draw(("HSLuv", lightText), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Hsluv, end, amount)); + var hpluv = Gradient.Draw(("HPLuv", lightText), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Hpluv, end, amount)); + var ictcp = Gradient.Draw(("ICtCp", lightText), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Ictcp, end, amount)); + var jzazbz = Gradient.Draw(("JzAzBz", lightText), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Jzazbz, end, amount)); + var jzczhz = Gradient.Draw(("JzCzHz", lightText), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Jzczhz, end, amount)); + var oklab = Gradient.Draw(("OKLAB", lightText), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Oklab, end, amount)); + var oklch = Gradient.Draw(("OKLCH", lightText), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Oklch, end, amount)); + var cam02 = Gradient.Draw(("CAM02", lightText), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Cam02, end, amount)); + var cam16 = Gradient.Draw(("CAM16", lightText), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Cam16, end, amount)); + var hct = Gradient.Draw(("HCT", lightText), columnWidth, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Hct, end, amount)); var columnImage = new Image(columnWidth, rowHeight * rows); columnImage.Mutate(context => context @@ -104,16 +105,17 @@ void GenerateVisionDeficiencyGradients() new(ColourSpace.Hsb, 360, 0.666, 1) }; - var dark = new Unicolour("#404046"); - var none = Gradient.Draw(("No deficiency", dark), width, rowHeight, colourPoints, + var darkText = new Unicolour("#404046"); + + var none = Gradient.Draw(("No deficiency", darkText), width, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Hsb, end, amount)); - var protanopia = Gradient.Draw(("Protanopia", dark), width, rowHeight, colourPoints, + var protanopia = Gradient.Draw(("Protanopia", darkText), width, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Hsb, end, amount).SimulateProtanopia()); - var deuteranopia = Gradient.Draw(("Deuteranopia", dark), width, rowHeight, colourPoints, + var deuteranopia = Gradient.Draw(("Deuteranopia", darkText), width, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Hsb, end, amount).SimulateDeuteranopia()); - var tritanopia = Gradient.Draw(("Tritanopia", dark), width, rowHeight, colourPoints, + var tritanopia = Gradient.Draw(("Tritanopia", darkText), width, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Hsb, end, amount).SimulateTritanopia()); - var achromatopsia = Gradient.Draw(("Achromatopsia", dark), width, rowHeight, colourPoints, + var achromatopsia = Gradient.Draw(("Achromatopsia", darkText), width, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Hsb, end, amount).SimulateAchromatopsia()); var image = new Image(width, rowHeight * rows); @@ -133,18 +135,13 @@ void GenerateAlphaInterpolation() const int width = 1000; const int rows = 2; const int rowHeight = 120; + + var colourPoints = new[] { Css.Red, Css.Transparent, Css.Blue }; + var text = Css.Black; - var colourPoints = new Unicolour[] - { - new(ColourSpace.Rgb, 1, 0, 0, 1), - new(ColourSpace.Rgb, 0, 0, 0, 0), - new(ColourSpace.Rgb, 0, 0, 1, 1) - }; - - var black = new Unicolour("#000000"); - var premultiplied = Gradient.Draw(("With premultiplied alpha", black), width, rowHeight, colourPoints, + var premultiplied = Gradient.Draw(("With premultiplied alpha", text), width, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Rgb, end, amount, true)); - var notPremultiplied = Gradient.Draw(("Without premultiplied alpha", black), width, rowHeight, colourPoints, + var notPremultiplied = Gradient.Draw(("Without premultiplied alpha", text), width, rowHeight, colourPoints, (start, end, amount) => start.Mix(ColourSpace.Rgb, end, amount, false)); var image = new Image(width, rowHeight * rows); diff --git a/Unicolour.Example/Unicolour.Example.csproj b/Unicolour.Example/Unicolour.Example.csproj index dc3d32a6..a16db686 100644 --- a/Unicolour.Example/Unicolour.Example.csproj +++ b/Unicolour.Example/Unicolour.Example.csproj @@ -17,6 +17,7 @@ + diff --git a/Unicolour.Tests/DatasetCssTests.cs b/Unicolour.Tests/DatasetCssTests.cs new file mode 100644 index 00000000..0f537e60 --- /dev/null +++ b/Unicolour.Tests/DatasetCssTests.cs @@ -0,0 +1,561 @@ +namespace Wacton.Unicolour.Tests; + +using System.Collections.Generic; +using System.Linq; +using NUnit.Framework; +using Wacton.Unicolour.Datasets; +using Wacton.Unicolour.Tests.Utils; +using static Datasets.Css; + +public class DatasetCssTests +{ + // https://www.w3.org/TR/css-color-4/#named-colors + private static readonly List Rgb255TestData = new() + { + new TestCaseData(AliceBlue, 240, 248, 255).SetName("Alice Blue"), + new TestCaseData(AntiqueWhite, 250, 235, 215).SetName("Antique White"), + new TestCaseData(Aqua, 0, 255, 255).SetName("Aqua"), + new TestCaseData(Aquamarine, 127, 255, 212).SetName("Aquamarine"), + new TestCaseData(Azure, 240, 255, 255).SetName("Azure"), + new TestCaseData(Beige, 245, 245, 220).SetName("Beige"), + new TestCaseData(Bisque, 255, 228, 196).SetName("Bisque"), + new TestCaseData(Black, 0, 0, 0).SetName("Black"), + new TestCaseData(BlanchedAlmond, 255, 235, 205).SetName("Blanched Almond"), + new TestCaseData(Blue, 0, 0, 255).SetName("Blue"), + new TestCaseData(BlueViolet, 138, 43, 226).SetName("Blue Violet"), + new TestCaseData(Brown, 165, 42, 42).SetName("Brown"), + new TestCaseData(Burlywood, 222, 184, 135).SetName("Burlywood"), + new TestCaseData(CadetBlue, 95, 158, 160).SetName("Cadet Blue"), + new TestCaseData(Chartreuse, 127, 255, 0).SetName("Chartreuse"), + new TestCaseData(Chocolate, 210, 105, 30).SetName("Chocolate"), + new TestCaseData(Coral, 255, 127, 80).SetName("Coral"), + new TestCaseData(CornflowerBlue, 100, 149, 237).SetName("Cornflower Blue"), + new TestCaseData(Cornsilk, 255, 248, 220).SetName("Cornsilk"), + new TestCaseData(Crimson, 220, 20, 60).SetName("Crimson"), + new TestCaseData(Cyan, 0, 255, 255).SetName("Cyan"), + new TestCaseData(DarkBlue, 0, 0, 139).SetName("Dark Blue"), + new TestCaseData(DarkCyan, 0, 139, 139).SetName("Dark Cyan"), + new TestCaseData(DarkGoldenrod, 184, 134, 11).SetName("Dark Goldenrod"), + new TestCaseData(DarkGray, 169, 169, 169).SetName("Dark Gray"), + new TestCaseData(DarkGreen, 0, 100, 0).SetName("Dark Green"), + new TestCaseData(DarkGrey, 169, 169, 169).SetName("Dark Grey"), + new TestCaseData(DarkKhaki, 189, 183, 107).SetName("Dark Khaki"), + new TestCaseData(DarkMagenta, 139, 0, 139).SetName("Dark Magenta"), + new TestCaseData(DarkOliveGreen, 85, 107, 47).SetName("Dark Olive Green"), + new TestCaseData(DarkOrange, 255, 140, 0).SetName("Dark Orange"), + new TestCaseData(DarkOrchid, 153, 50, 204).SetName("Dark Orchid"), + new TestCaseData(DarkRed, 139, 0, 0).SetName("Dark Red"), + new TestCaseData(DarkSalmon, 233, 150, 122).SetName("Dark Salmon"), + new TestCaseData(DarkSeaGreen, 143, 188, 143).SetName("Dark Sea Green"), + new TestCaseData(DarkSlateBlue, 72, 61, 139).SetName("Dark Slate Blue"), + new TestCaseData(DarkSlateGray, 47, 79, 79).SetName("Dark Slate Gray"), + new TestCaseData(DarkSlateGrey, 47, 79, 79).SetName("Dark Slate Grey"), + new TestCaseData(DarkTurquoise, 0, 206, 209).SetName("Dark Turquoise"), + new TestCaseData(DarkViolet, 148, 0, 211).SetName("Dark Violet"), + new TestCaseData(DeepPink, 255, 20, 147).SetName("Deep Pink"), + new TestCaseData(DeepSkyBlue, 0, 191, 255).SetName("Deep Sky Blue"), + new TestCaseData(DimGray, 105, 105, 105).SetName("Dim Gray"), + new TestCaseData(DimGrey, 105, 105, 105).SetName("Dim Grey"), + new TestCaseData(DodgerBlue, 30, 144, 255).SetName("Dodger Blue"), + new TestCaseData(FireBrick, 178, 34, 34).SetName("Fire Brick"), + new TestCaseData(FloralWhite, 255, 250, 240).SetName("Floral White"), + new TestCaseData(ForestGreen, 34, 139, 34).SetName("Forest Green"), + new TestCaseData(Fuchsia, 255, 0, 255).SetName("Fuchsia"), + new TestCaseData(Gainsboro, 220, 220, 220).SetName("Gainsboro"), + new TestCaseData(GhostWhite, 248, 248, 255).SetName("Ghost White"), + new TestCaseData(Gold, 255, 215, 0).SetName("Gold"), + new TestCaseData(Goldenrod, 218, 165, 32).SetName("Goldenrod"), + new TestCaseData(Gray, 128, 128, 128).SetName("Gray"), + new TestCaseData(Green, 0, 128, 0).SetName("Green"), + new TestCaseData(GreenYellow, 173, 255, 47).SetName("Green Yellow"), + new TestCaseData(Grey, 128, 128, 128).SetName("Grey"), + new TestCaseData(Honeydew, 240, 255, 240).SetName("Honeydew"), + new TestCaseData(HotPink, 255, 105, 180).SetName("Hot Pink"), + new TestCaseData(IndianRed, 205, 92, 92).SetName("Indian Red"), + new TestCaseData(Indigo, 75, 0, 130).SetName("Indigo"), + new TestCaseData(Ivory, 255, 255, 240).SetName("Ivory"), + new TestCaseData(Khaki, 240, 230, 140).SetName("Khaki"), + new TestCaseData(Lavender, 230, 230, 250).SetName("Lavender"), + new TestCaseData(LavenderBlush, 255, 240, 245).SetName("Lavender Blush"), + new TestCaseData(LawnGreen, 124, 252, 0).SetName("Lawn Green"), + new TestCaseData(LemonChiffon, 255, 250, 205).SetName("Lemon Chiffon"), + new TestCaseData(LightBlue, 173, 216, 230).SetName("Light Blue"), + new TestCaseData(LightCoral, 240, 128, 128).SetName("Light Coral"), + new TestCaseData(LightCyan, 224, 255, 255).SetName("Light Cyan"), + new TestCaseData(LightGoldenrodYellow, 250, 250, 210).SetName("Light Goldenrod Yellow"), + new TestCaseData(LightGray, 211, 211, 211).SetName("Light Gray"), + new TestCaseData(LightGreen, 144, 238, 144).SetName("Light Green"), + new TestCaseData(LightGrey, 211, 211, 211).SetName("Light Grey"), + new TestCaseData(LightPink, 255, 182, 193).SetName("Light Pink"), + new TestCaseData(LightSalmon, 255, 160, 122).SetName("Light Salmon"), + new TestCaseData(LightSeaGreen, 32, 178, 170).SetName("Light Sea Green"), + new TestCaseData(LightSkyBlue, 135, 206, 250).SetName("Light Sky Blue"), + new TestCaseData(LightSlateGray, 119, 136, 153).SetName("Light Slate Gray"), + new TestCaseData(LightSlateGrey, 119, 136, 153).SetName("Light Slate Grey"), + new TestCaseData(LightSteelBlue, 176, 196, 222).SetName("Light Steel Blue"), + new TestCaseData(LightYellow, 255, 255, 224).SetName("Light Yellow"), + new TestCaseData(Lime, 0, 255, 0).SetName("Lime"), + new TestCaseData(LimeGreen, 50, 205, 50).SetName("Lime Green"), + new TestCaseData(Linen, 250, 240, 230).SetName("Linen"), + new TestCaseData(Magenta, 255, 0, 255).SetName("Magenta"), + new TestCaseData(Maroon, 128, 0, 0).SetName("Maroon"), + new TestCaseData(MediumAquamarine, 102, 205, 170).SetName("Medium Aquamarine"), + new TestCaseData(MediumBlue, 0, 0, 205).SetName("Medium Blue"), + new TestCaseData(MediumOrchid, 186, 85, 211).SetName("Medium Orchid"), + new TestCaseData(MediumPurple, 147, 112, 219).SetName("Medium Purple"), + new TestCaseData(MediumSeaGreen, 60, 179, 113).SetName("Medium Sea Green"), + new TestCaseData(MediumSlateBlue, 123, 104, 238).SetName("Medium Slate Blue"), + new TestCaseData(MediumSpringGreen, 0, 250, 154).SetName("Medium Spring Green"), + new TestCaseData(MediumTurquoise, 72, 209, 204).SetName("Medium Turquoise"), + new TestCaseData(MediumVioletRed, 199, 21, 133).SetName("Medium Violet Red"), + new TestCaseData(MidnightBlue, 25, 25, 112).SetName("Midnight Blue"), + new TestCaseData(MintCream, 245, 255, 250).SetName("Mint Cream"), + new TestCaseData(MistyRose, 255, 228, 225).SetName("Misty Rose"), + new TestCaseData(Moccasin, 255, 228, 181).SetName("Moccasin"), + new TestCaseData(NavajoWhite, 255, 222, 173).SetName("Navajo White"), + new TestCaseData(Navy, 0, 0, 128).SetName("Navy"), + new TestCaseData(OldLace, 253, 245, 230).SetName("Old Lace"), + new TestCaseData(Olive, 128, 128, 0).SetName("Olive"), + new TestCaseData(OliveDrab, 107, 142, 35).SetName("Olive Drab"), + new TestCaseData(Orange, 255, 165, 0).SetName("Orange"), + new TestCaseData(OrangeRed, 255, 69, 0).SetName("Orange Red"), + new TestCaseData(Orchid, 218, 112, 214).SetName("Orchid"), + new TestCaseData(PaleGoldenrod, 238, 232, 170).SetName("Pale Goldenrod"), + new TestCaseData(PaleGreen, 152, 251, 152).SetName("Pale Green"), + new TestCaseData(PaleTurquoise, 175, 238, 238).SetName("Pale Turquoise"), + new TestCaseData(PaleVioletRed, 219, 112, 147).SetName("Pale Violet Red"), + new TestCaseData(PapayaWhip, 255, 239, 213).SetName("Papaya Whip"), + new TestCaseData(PeachPuff, 255, 218, 185).SetName("Peach Puff"), + new TestCaseData(Peru, 205, 133, 63).SetName("Peru"), + new TestCaseData(Pink, 255, 192, 203).SetName("Pink"), + new TestCaseData(Plum, 221, 160, 221).SetName("Plum"), + new TestCaseData(PowderBlue, 176, 224, 230).SetName("Powder Blue"), + new TestCaseData(Purple, 128, 0, 128).SetName("Purple"), + new TestCaseData(RebeccaPurple, 102, 51, 153).SetName("Rebecca Purple"), + new TestCaseData(Red, 255, 0, 0).SetName("Red"), + new TestCaseData(RosyBrown, 188, 143, 143).SetName("Rosy Brown"), + new TestCaseData(RoyalBlue, 65, 105, 225).SetName("Royal Blue"), + new TestCaseData(SaddleBrown, 139, 69, 19).SetName("Saddle Brown"), + new TestCaseData(Salmon, 250, 128, 114).SetName("Salmon"), + new TestCaseData(SandyBrown, 244, 164, 96).SetName("Sandy Brown"), + new TestCaseData(SeaGreen, 46, 139, 87).SetName("Sea Green"), + new TestCaseData(Seashell, 255, 245, 238).SetName("Seashell"), + new TestCaseData(Sienna, 160, 82, 45).SetName("Sienna"), + new TestCaseData(Silver, 192, 192, 192).SetName("Silver"), + new TestCaseData(SkyBlue, 135, 206, 235).SetName("Sky Blue"), + new TestCaseData(SlateBlue, 106, 90, 205).SetName("Slate Blue"), + new TestCaseData(SlateGray, 112, 128, 144).SetName("Slate Gray"), + new TestCaseData(SlateGrey, 112, 128, 144).SetName("Slate Grey"), + new TestCaseData(Snow, 255, 250, 250).SetName("Snow"), + new TestCaseData(SpringGreen, 0, 255, 127).SetName("Spring Green"), + new TestCaseData(SteelBlue, 70, 130, 180).SetName("Steel Blue"), + new TestCaseData(Tan, 210, 180, 140).SetName("Tan"), + new TestCaseData(Teal, 0, 128, 128).SetName("Teal"), + new TestCaseData(Thistle, 216, 191, 216).SetName("Thistle"), + new TestCaseData(Tomato, 255, 99, 71).SetName("Tomato"), + new TestCaseData(Turquoise, 64, 224, 208).SetName("Turquoise"), + new TestCaseData(Violet, 238, 130, 238).SetName("Violet"), + new TestCaseData(Wheat, 245, 222, 179).SetName("Wheat"), + new TestCaseData(White, 255, 255, 255).SetName("White"), + new TestCaseData(WhiteSmoke, 245, 245, 245).SetName("White Smoke"), + new TestCaseData(Yellow, 255, 255, 0).SetName("Yellow"), + new TestCaseData(YellowGreen, 154, 205, 50).SetName("Yellow Green") + }; + + private static readonly List DuplicateTestData = new() + { + new TestCaseData(Cyan, Aqua).SetName("Cyan"), + new TestCaseData(Magenta, Fuchsia).SetName("Magenta"), + new TestCaseData(DarkGrey, DarkGray).SetName("Dark Grey"), + new TestCaseData(DarkSlateGrey, DarkSlateGray).SetName("Dark Slate Grey"), + new TestCaseData(DimGrey, DimGray).SetName("Dim Grey"), + new TestCaseData(Grey, Gray).SetName("Grey"), + new TestCaseData(LightGrey, LightGray).SetName("Light Grey"), + new TestCaseData(LightSlateGrey, LightSlateGray).SetName("Light Slate Grey"), + new TestCaseData(SlateGrey, SlateGray).SetName("Slate Grey") + }; + + [TestCaseSource(nameof(Rgb255TestData))] + public void Rgb255(Unicolour unicolour, int expectedR, int expectedG, int expectedB) + { + var expectedRgb255 = new Rgb255(expectedR, expectedG, expectedB); + TestUtils.AssertTriplet(unicolour, expectedRgb255.Triplet, 0); + } + + [Test] + public void Transparent() + { + TestUtils.AssertTriplet(Css.Transparent, new(0, 0, 0), 0); + Assert.That(Css.Transparent.Alpha.A, Is.EqualTo(0)); + } + + [TestCaseSource(nameof(DuplicateTestData))] + public void Duplicates(Unicolour unicolour1, Unicolour unicolour2) + { + Assert.That(ReferenceEquals(unicolour1, unicolour2), Is.False); + Assert.That(unicolour1.Hex, Is.EqualTo(unicolour2.Hex)); + } + + [Test] + public void DuplicateCount() + { + var hexValues = Css.All.Select(x => x.Hex).ToList(); + var duplicateCount = hexValues.Count - hexValues.Distinct().Count(); + Assert.That(duplicateCount, Is.EqualTo(DuplicateTestData.Count)); + } + + [Test] + public void All() + { + Assert.That(Css.All.Count(), Is.EqualTo(148)); + Assert.That(Css.All.Distinct().Count(), Is.EqualTo(139)); + } + + [TestCase("aliceblue")] + [TestCase("antiquewhite")] + [TestCase("aqua")] + [TestCase("aquamarine")] + [TestCase("azure")] + [TestCase("beige")] + [TestCase("bisque")] + [TestCase("black")] + [TestCase("blanchedalmond")] + [TestCase("blue")] + [TestCase("blueviolet")] + [TestCase("brown")] + [TestCase("burlywood")] + [TestCase("cadetblue")] + [TestCase("chartreuse")] + [TestCase("chocolate")] + [TestCase("coral")] + [TestCase("cornflowerblue")] + [TestCase("cornsilk")] + [TestCase("crimson")] + [TestCase("cyan")] + [TestCase("darkblue")] + [TestCase("darkcyan")] + [TestCase("darkgoldenrod")] + [TestCase("darkgray")] + [TestCase("darkgreen")] + [TestCase("darkgrey")] + [TestCase("darkkhaki")] + [TestCase("darkmagenta")] + [TestCase("darkolivegreen")] + [TestCase("darkorange")] + [TestCase("darkorchid")] + [TestCase("darkred")] + [TestCase("darksalmon")] + [TestCase("darkseagreen")] + [TestCase("darkslateblue")] + [TestCase("darkslategray")] + [TestCase("darkslategrey")] + [TestCase("darkturquoise")] + [TestCase("darkviolet")] + [TestCase("deeppink")] + [TestCase("deepskyblue")] + [TestCase("dimgray")] + [TestCase("dimgrey")] + [TestCase("dodgerblue")] + [TestCase("firebrick")] + [TestCase("floralwhite")] + [TestCase("forestgreen")] + [TestCase("fuchsia")] + [TestCase("gainsboro")] + [TestCase("ghostwhite")] + [TestCase("gold")] + [TestCase("goldenrod")] + [TestCase("gray")] + [TestCase("green")] + [TestCase("greenyellow")] + [TestCase("grey")] + [TestCase("honeydew")] + [TestCase("hotpink")] + [TestCase("indianred")] + [TestCase("indigo")] + [TestCase("ivory")] + [TestCase("khaki")] + [TestCase("lavender")] + [TestCase("lavenderblush")] + [TestCase("lawngreen")] + [TestCase("lemonchiffon")] + [TestCase("lightblue")] + [TestCase("lightcoral")] + [TestCase("lightcyan")] + [TestCase("lightgoldenrodyellow")] + [TestCase("lightgray")] + [TestCase("lightgreen")] + [TestCase("lightgrey")] + [TestCase("lightpink")] + [TestCase("lightsalmon")] + [TestCase("lightseagreen")] + [TestCase("lightskyblue")] + [TestCase("lightslategray")] + [TestCase("lightslategrey")] + [TestCase("lightsteelblue")] + [TestCase("lightyellow")] + [TestCase("lime")] + [TestCase("limegreen")] + [TestCase("linen")] + [TestCase("magenta")] + [TestCase("maroon")] + [TestCase("mediumaquamarine")] + [TestCase("mediumblue")] + [TestCase("mediumorchid")] + [TestCase("mediumpurple")] + [TestCase("mediumseagreen")] + [TestCase("mediumslateblue")] + [TestCase("mediumspringgreen")] + [TestCase("mediumturquoise")] + [TestCase("mediumvioletred")] + [TestCase("midnightblue")] + [TestCase("mintcream")] + [TestCase("mistyrose")] + [TestCase("moccasin")] + [TestCase("navajowhite")] + [TestCase("navy")] + [TestCase("oldlace")] + [TestCase("olive")] + [TestCase("olivedrab")] + [TestCase("orange")] + [TestCase("orangered")] + [TestCase("orchid")] + [TestCase("palegoldenrod")] + [TestCase("palegreen")] + [TestCase("paleturquoise")] + [TestCase("palevioletred")] + [TestCase("papayawhip")] + [TestCase("peachpuff")] + [TestCase("peru")] + [TestCase("pink")] + [TestCase("plum")] + [TestCase("powderblue")] + [TestCase("purple")] + [TestCase("rebeccapurple")] + [TestCase("red")] + [TestCase("rosybrown")] + [TestCase("royalblue")] + [TestCase("saddlebrown")] + [TestCase("salmon")] + [TestCase("sandybrown")] + [TestCase("seagreen")] + [TestCase("seashell")] + [TestCase("sienna")] + [TestCase("silver")] + [TestCase("skyblue")] + [TestCase("slateblue")] + [TestCase("slategray")] + [TestCase("slategrey")] + [TestCase("snow")] + [TestCase("springgreen")] + [TestCase("steelblue")] + [TestCase("tan")] + [TestCase("teal")] + [TestCase("thistle")] + [TestCase("tomato")] + [TestCase("transparent")] + [TestCase("turquoise")] + [TestCase("violet")] + [TestCase("wheat")] + [TestCase("white")] + [TestCase("whitesmoke")] + [TestCase("yellow")] + [TestCase("yellowgreen")] + public void Name(string name) + { + var unicolour = FromName(name); + Assert.That(unicolour, Is.Not.Null); + } + + [TestCase("\taliceblue\n")] + [TestCase("\ta ntiquewhit e\n")] + [TestCase("\ta qu a\n")] + [TestCase("\ta quamarin e\n")] + [TestCase("\ta zur e\n")] + [TestCase("\tb eig e\n")] + [TestCase("\tb isqu e\n")] + [TestCase("\tb lac k\n")] + [TestCase("\tb lanchedalmon d\n")] + [TestCase("\tb lu e\n")] + [TestCase("\tb lueviole t\n")] + [TestCase("\tb row n\n")] + [TestCase("\tb urlywoo d\n")] + [TestCase("\tc adetblu e\n")] + [TestCase("\tc hartreus e\n")] + [TestCase("\tc hocolat e\n")] + [TestCase("\tc ora l\n")] + [TestCase("\tc ornflowerblu e\n")] + [TestCase("\tc ornsil k\n")] + [TestCase("\tc rimso n\n")] + [TestCase("\tc ya n\n")] + [TestCase("\td arkblu e\n")] + [TestCase("\td arkcya n\n")] + [TestCase("\td arkgoldenro d\n")] + [TestCase("\td arkgra y\n")] + [TestCase("\td arkgree n\n")] + [TestCase("\td arkgre y\n")] + [TestCase("\td arkkhak i\n")] + [TestCase("\td arkmagent a\n")] + [TestCase("\td arkolivegree n\n")] + [TestCase("\td arkorang e\n")] + [TestCase("\td arkorchi d\n")] + [TestCase("\td arkre d\n")] + [TestCase("\td arksalmo n\n")] + [TestCase("\td arkseagree n\n")] + [TestCase("\td arkslateblu e\n")] + [TestCase("\td arkslategra y\n")] + [TestCase("\td arkslategre y\n")] + [TestCase("\td arkturquois e\n")] + [TestCase("\td arkviole t\n")] + [TestCase("\td eeppin k\n")] + [TestCase("\td eepskyblu e\n")] + [TestCase("\td imgra y\n")] + [TestCase("\td imgre y\n")] + [TestCase("\td odgerblu e\n")] + [TestCase("\tf irebric k\n")] + [TestCase("\tf loralwhit e\n")] + [TestCase("\tf orestgree n\n")] + [TestCase("\tf uchsi a\n")] + [TestCase("\tg ainsbor o\n")] + [TestCase("\tg hostwhit e\n")] + [TestCase("\tg ol d\n")] + [TestCase("\tg oldenro d\n")] + [TestCase("\tg ra y\n")] + [TestCase("\tg ree n\n")] + [TestCase("\tg reenyello w\n")] + [TestCase("\tg re y\n")] + [TestCase("\th oneyde w\n")] + [TestCase("\th otpin k\n")] + [TestCase("\ti ndianre d\n")] + [TestCase("\ti ndig o\n")] + [TestCase("\ti vor y\n")] + [TestCase("\tk hak i\n")] + [TestCase("\tl avende r\n")] + [TestCase("\tl avenderblus h\n")] + [TestCase("\tl awngree n\n")] + [TestCase("\tl emonchiffo n\n")] + [TestCase("\tl ightblu e\n")] + [TestCase("\tl ightcora l\n")] + [TestCase("\tl ightcya n\n")] + [TestCase("\tl ightgoldenrodyello w\n")] + [TestCase("\tl ightgra y\n")] + [TestCase("\tl ightgree n\n")] + [TestCase("\tl ightgre y\n")] + [TestCase("\tl ightpin k\n")] + [TestCase("\tl ightsalmo n\n")] + [TestCase("\tl ightseagree n\n")] + [TestCase("\tl ightskyblu e\n")] + [TestCase("\tl ightslategra y\n")] + [TestCase("\tl ightslategre y\n")] + [TestCase("\tl ightsteelblu e\n")] + [TestCase("\tl ightyello w\n")] + [TestCase("\tl im e\n")] + [TestCase("\tl imegree n\n")] + [TestCase("\tl ine n\n")] + [TestCase("\tm agent a\n")] + [TestCase("\tm aroo n\n")] + [TestCase("\tm ediumaquamarin e\n")] + [TestCase("\tm ediumblu e\n")] + [TestCase("\tm ediumorchi d\n")] + [TestCase("\tm ediumpurpl e\n")] + [TestCase("\tm ediumseagree n\n")] + [TestCase("\tm ediumslateblu e\n")] + [TestCase("\tm ediumspringgree n\n")] + [TestCase("\tm ediumturquois e\n")] + [TestCase("\tm ediumvioletre d\n")] + [TestCase("\tm idnightblu e\n")] + [TestCase("\tm intcrea m\n")] + [TestCase("\tm istyros e\n")] + [TestCase("\tm occasi n\n")] + [TestCase("\tn avajowhit e\n")] + [TestCase("\tn av y\n")] + [TestCase("\to ldlac e\n")] + [TestCase("\to liv e\n")] + [TestCase("\to livedra b\n")] + [TestCase("\to rang e\n")] + [TestCase("\to rangere d\n")] + [TestCase("\to rchi d\n")] + [TestCase("\tp alegoldenro d\n")] + [TestCase("\tp alegree n\n")] + [TestCase("\tp aleturquois e\n")] + [TestCase("\tp alevioletre d\n")] + [TestCase("\tp apayawhi p\n")] + [TestCase("\tp eachpuf f\n")] + [TestCase("\tp er u\n")] + [TestCase("\tp in k\n")] + [TestCase("\tp lu m\n")] + [TestCase("\tp owderblu e\n")] + [TestCase("\tp urpl e\n")] + [TestCase("\tr ebeccapurpl e\n")] + [TestCase("\tr e d\n")] + [TestCase("\tr osybrow n\n")] + [TestCase("\tr oyalblu e\n")] + [TestCase("\ts addlebrow n\n")] + [TestCase("\ts almo n\n")] + [TestCase("\ts andybrow n\n")] + [TestCase("\ts eagree n\n")] + [TestCase("\ts eashel l\n")] + [TestCase("\ts ienn a\n")] + [TestCase("\ts ilve r\n")] + [TestCase("\ts kyblu e\n")] + [TestCase("\ts lateblu e\n")] + [TestCase("\ts lategra y\n")] + [TestCase("\ts lategre y\n")] + [TestCase("\ts no w\n")] + [TestCase("\ts pringgree n\n")] + [TestCase("\ts teelblu e\n")] + [TestCase("\tt a n\n")] + [TestCase("\tt ea l\n")] + [TestCase("\tt histl e\n")] + [TestCase("\tt omat o\n")] + [TestCase("\tt ransparen t\n")] + [TestCase("\tt urquois e\n")] + [TestCase("\tv iole t\n")] + [TestCase("\tw hea t\n")] + [TestCase("\tw hit e\n")] + [TestCase("\tw hitesmok e\n")] + [TestCase("\ty ello w\n")] + [TestCase("\ty ellowgre en\n")] + public void NameWithWhitespace(string name) + { + var unicolour = FromName(name); + Assert.That(unicolour, Is.Not.Null); + } + + // some of these names taken from https://en.wikipedia.org/wiki/X11_color_names but are not defined in the CSS specification + // other names look like they should exist based on other names, but don't + // also: only handling casing and whitespace, not attempting to strip punctuation + [TestCase("light goldenrod")] + [TestCase("navy blue")] + [TestCase("web gray")] + [TestCase("web grey")] + [TestCase("web green")] + [TestCase("web maroon")] + [TestCase("web purple")] + [TestCase("goldenrod yellow")] + [TestCase("olive green")] + [TestCase("medium goldenrod")] + [TestCase("medium red")] + [TestCase("violet red")] + [TestCase("biege")] + [TestCase("chartruese")] + [TestCase("dodgeblue")] + [TestCase("orang")] + [TestCase("stealblue")] + [TestCase("tourquise")] + [TestCase("periwinkle")] + [TestCase("unicolour")] + [TestCase("a")] + [TestCase("\"aliceblue\"")] + [TestCase("123")] + [TestCase(".")] + [TestCase(" ")] + [TestCase("")] + [TestCase("\t")] + [TestCase("\n")] + [TestCase(null)] + public void NameNotFound(string name) + { + var unicolour = FromName(name); + Assert.That(unicolour, Is.Null); + } +} \ No newline at end of file diff --git a/Unicolour.Tests/DatasetMacbethTests.cs b/Unicolour.Tests/DatasetMacbethTests.cs index d717e592..3c48c90c 100644 --- a/Unicolour.Tests/DatasetMacbethTests.cs +++ b/Unicolour.Tests/DatasetMacbethTests.cs @@ -11,38 +11,40 @@ public class DatasetMacbethTests { private static readonly Configuration ConfigIlluminantC = new(xyzConfiguration: new XyzConfiguration(WhitePoint.From(Illuminant.C))); - private static readonly List XyyIlluminantC = new() + // https://poynton.ca/notes/color/GretagMacbeth-ColorChecker.html + private static readonly List XyyTestData = new() { - new TestCaseData(DarkSkin, new Xyy(0.400, 0.350, 10.1 / 100.0)).SetName("Dark skin"), - new TestCaseData(LightSkin, new Xyy(0.377, 0.345, 35.8 / 100.0)).SetName("Light skin"), - new TestCaseData(BlueSky, new Xyy(0.247, 0.251, 19.3 / 100.0)).SetName("Blue sky"), - new TestCaseData(Foliage, new Xyy(0.337, 0.422, 13.3 / 100.0)).SetName("Foliage"), - new TestCaseData(BlueFlower, new Xyy(0.265, 0.240, 24.3 / 100.0)).SetName("Blue flower"), - new TestCaseData(BluishGreen, new Xyy(0.261, 0.343, 43.1 / 100.0)).SetName("Bluish green"), - new TestCaseData(Orange, new Xyy(0.506, 0.407, 30.1 / 100.0)).SetName("Orange"), - new TestCaseData(PurplishBlue, new Xyy(0.211, 0.175, 12 / 100.0)).SetName("Purplish blue"), - new TestCaseData(ModerateRed, new Xyy(0.453, 0.306, 19.8 / 100.0)).SetName("Moderate red"), - new TestCaseData(Purple, new Xyy(0.285, 0.202, 6.6 / 100.0)).SetName("Purple"), - new TestCaseData(YellowGreen, new Xyy(0.38, 0.489, 44.3 / 100.0)).SetName("Yellow green"), - new TestCaseData(OrangeYellow, new Xyy(0.473, 0.438, 43.1 / 100.0)).SetName("Orange yellow"), - new TestCaseData(Blue, new Xyy(0.187, 0.129, 6.1 / 100.0)).SetName("Blue"), - new TestCaseData(Green, new Xyy(0.305, 0.478, 23.4 / 100.0)).SetName("Green"), - new TestCaseData(Red, new Xyy(0.539, 0.313, 12 / 100.0)).SetName("Red"), - new TestCaseData(Yellow, new Xyy(0.448, 0.47, 59.1 / 100.0)).SetName("Yellow"), - new TestCaseData(Magenta, new Xyy(0.364, 0.233, 19.8 / 100.0)).SetName("Magenta"), - new TestCaseData(Cyan, new Xyy(0.196, 0.252, 19.8 / 100.0)).SetName("Cyan"), - new TestCaseData(White, new Xyy(0.31, 0.316, 90 / 100.0)).SetName("White"), - new TestCaseData(Neutral8, new Xyy(0.31, 0.316, 59.1 / 100.0)).SetName("Neutral 8"), - new TestCaseData(Neutral65, new Xyy(0.31, 0.316, 36.2 / 100.0)).SetName("Neutral 6.5"), - new TestCaseData(Neutral5, new Xyy(0.31, 0.316, 19.8 / 100.0)).SetName("Neutral 5"), - new TestCaseData(Neutral35, new Xyy(0.31, 0.316, 9 / 100.0)).SetName("Neutral 3.5"), - new TestCaseData(Black, new Xyy(0.31, 0.316, 3.1 / 100.0)).SetName("Black") + new TestCaseData(DarkSkin, 0.400, 0.350, 10.1).SetName("Dark skin"), + new TestCaseData(LightSkin, 0.377, 0.345, 35.8).SetName("Light skin"), + new TestCaseData(BlueSky, 0.247, 0.251, 19.3).SetName("Blue sky"), + new TestCaseData(Foliage, 0.337, 0.422, 13.3).SetName("Foliage"), + new TestCaseData(BlueFlower, 0.265, 0.240, 24.3).SetName("Blue flower"), + new TestCaseData(BluishGreen, 0.261, 0.343, 43.1).SetName("Bluish green"), + new TestCaseData(Orange, 0.506, 0.407, 30.1).SetName("Orange"), + new TestCaseData(PurplishBlue, 0.211, 0.175, 12).SetName("Purplish blue"), + new TestCaseData(ModerateRed, 0.453, 0.306, 19.8).SetName("Moderate red"), + new TestCaseData(Purple, 0.285, 0.202, 6.6).SetName("Purple"), + new TestCaseData(YellowGreen, 0.38, 0.489, 44.3).SetName("Yellow green"), + new TestCaseData(OrangeYellow, 0.473, 0.438, 43.1).SetName("Orange yellow"), + new TestCaseData(Blue, 0.187, 0.129, 6.1).SetName("Blue"), + new TestCaseData(Green, 0.305, 0.478, 23.4).SetName("Green"), + new TestCaseData(Red, 0.539, 0.313, 12).SetName("Red"), + new TestCaseData(Yellow, 0.448, 0.47, 59.1).SetName("Yellow"), + new TestCaseData(Magenta, 0.364, 0.233, 19.8).SetName("Magenta"), + new TestCaseData(Cyan, 0.196, 0.252, 19.8).SetName("Cyan"), + new TestCaseData(White, 0.31, 0.316, 90).SetName("White"), + new TestCaseData(Neutral8, 0.31, 0.316, 59.1).SetName("Neutral 8"), + new TestCaseData(Neutral65, 0.31, 0.316, 36.2).SetName("Neutral 6.5"), + new TestCaseData(Neutral5, 0.31, 0.316, 19.8).SetName("Neutral 5"), + new TestCaseData(Neutral35, 0.31, 0.316, 9).SetName("Neutral 3.5"), + new TestCaseData(Black, 0.31, 0.316, 3.1).SetName("Black") }; - [TestCaseSource(nameof(XyyIlluminantC))] - public void Test(Unicolour unicolour, Xyy expectedXyy) + [TestCaseSource(nameof(XyyTestData))] + public void Xyy(Unicolour unicolour, double expectedX, double expectedY, double expectedLuminance) { var unicolourIlluminantC = unicolour.ConvertToConfiguration(ConfigIlluminantC); + var expectedXyy = new Xyy(expectedX, expectedY, expectedLuminance / 100.0); TestUtils.AssertTriplet(unicolourIlluminantC, expectedXyy.Triplet, 0.02); }