├── ColorMine.Test ├── Lib │ └── Moq.dll ├── Utility │ └── DoubleExtensionTest.cs ├── Themes │ ├── GifItemizerTest.cs │ ├── Adapters │ │ └── BitmapAdapterTest.cs │ └── PercentagePaletteInventoryTest.cs ├── Properties │ └── AssemblyInfo.cs ├── ColorSpaces │ ├── ConversionTests.tt │ ├── ColorSpaceTest.tt │ ├── Comparisons │ │ ├── Cie1976ComparisonTest.cs │ │ └── CmcComparisonTest.cs │ ├── ConversionResults.xml │ ├── ColorSpaceTest.cs │ └── ConversionTests.cs └── ColorMine.Test.csproj ├── ColorMine ├── ColorSpaces │ ├── Comparisons │ │ ├── IDeltaEComparison.cs │ │ ├── IColorSpaceComparison.cs │ │ ├── Cie1976Comparison.cs │ │ └── CmcComparison.cs │ ├── Conversions │ │ ├── RgbConverter.cs │ │ ├── CmyConverter.cs │ │ ├── YxyConverter.cs │ │ ├── CmykConverter.cs │ │ ├── LchConverter.cs │ │ ├── XyzConverter.cs │ │ ├── LabConverter.cs │ │ └── HslConverter.cs │ ├── ColorSpaces.tt │ ├── ColorSpaces.xml │ ├── ColorSpace.cs │ └── ColorSpaces.cs ├── Themes │ ├── IItemizerStrategy.cs │ ├── IPaletteInventory.cs │ ├── IImage.cs │ ├── GifItemizer.cs │ ├── Adapters │ │ └── BitmapAdapter.cs │ └── PercentagePaletteInventory.cs ├── Utility │ └── DoubleExtension.cs ├── Properties │ └── AssemblyInfo.cs └── colormine.csproj ├── ColorMine.sln.DotSettings ├── .gitignore ├── README.md ├── LICENSE.txt └── ColorMine.sln /ColorMine.Test/Lib/Moq.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hvalidi/ColorMine/HEAD/ColorMine.Test/Lib/Moq.dll -------------------------------------------------------------------------------- /ColorMine/ColorSpaces/Comparisons/IDeltaEComparison.cs: -------------------------------------------------------------------------------- 1 | namespace ColorMine.ColorSpaces.Comparisons 2 | { 3 | internal interface IDeltaEComparison : IColorSpaceComparison 4 | { 5 | } 6 | } -------------------------------------------------------------------------------- /ColorMine/Themes/IItemizerStrategy.cs: -------------------------------------------------------------------------------- 1 | namespace ColorMine.Themes 2 | { 3 | interface IItemizerStrategy 4 | { 5 | T Itemize(IImage image) where T : ICatalog, new(); 6 | } 7 | } -------------------------------------------------------------------------------- /ColorMine/Themes/IPaletteInventory.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Drawing; 3 | 4 | namespace ColorMine.Themes 5 | { 6 | public interface ICatalog 7 | { 8 | IDictionary Items { get; } 9 | IImage Image { set; } 10 | } 11 | } -------------------------------------------------------------------------------- /ColorMine/Themes/IImage.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using System.Drawing.Imaging; 3 | using System.IO; 4 | 5 | namespace ColorMine.Themes 6 | { 7 | public interface IImage 8 | { 9 | int Width { get; } 10 | int Height { get; } 11 | Color GetPixel(int x, int y); 12 | void Save(Stream stream, ImageFormat format); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /ColorMine/ColorSpaces/Conversions/RgbConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | 3 | namespace ColorMine.ColorSpaces.Conversions 4 | { 5 | internal static class RgbConverter 6 | { 7 | internal static void ToColorSpace(IRgb color, IRgb item) 8 | { 9 | item.R = color.R; 10 | item.G = color.G; 11 | item.B = color.B; 12 | } 13 | 14 | internal static IRgb ToColor(IRgb item) 15 | { 16 | return item; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /ColorMine/ColorSpaces/Comparisons/IColorSpaceComparison.cs: -------------------------------------------------------------------------------- 1 | namespace ColorMine.ColorSpaces.Comparisons 2 | { 3 | public interface IColorSpaceComparison 4 | { 5 | /// 6 | /// Compares two colors 7 | /// 8 | /// The first color 9 | /// The second color 10 | /// Score based on similarity, the lower the score the closer the colors 11 | double Compare(IColorSpace a, IColorSpace b); 12 | } 13 | } -------------------------------------------------------------------------------- /ColorMine/Utility/DoubleExtension.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ColorMine.Utility 4 | { 5 | public static class DoubleExtension 6 | { 7 | private const double DefaultPrecision = .0001; 8 | 9 | internal static bool BasicallyEqualTo(this double a, double b) 10 | { 11 | return a.BasicallyEqualTo(b, DefaultPrecision); 12 | } 13 | 14 | internal static bool BasicallyEqualTo(this double a, double b, double precision) 15 | { 16 | return Math.Abs(a - b) <= precision; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /ColorMine.sln.DotSettings: -------------------------------------------------------------------------------- 1 | 2 | <data><IncludeFilters /><ExcludeFilters /></data> 3 | <data /> -------------------------------------------------------------------------------- /ColorMine/ColorSpaces/Comparisons/Cie1976Comparison.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ColorMine.ColorSpaces.Comparisons 4 | { 5 | public class Cie1976Comparison : IDeltaEComparison 6 | { 7 | public double Compare(IColorSpace colorA, IColorSpace colorB) 8 | { 9 | var a = colorA.To(); 10 | var b = colorB.To(); 11 | 12 | var differences = Distance(a.L, b.L) + Distance(a.A, b.A) + Distance(a.B, b.B); 13 | return Math.Sqrt(differences); 14 | } 15 | 16 | private static double Distance(double a, double b) 17 | { 18 | return Math.Pow(a - b, 2); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /ColorMine/ColorSpaces/Conversions/CmyConverter.cs: -------------------------------------------------------------------------------- 1 | namespace ColorMine.ColorSpaces.Conversions 2 | { 3 | internal static class CmyConverter 4 | { 5 | internal static void ToColorSpace(IRgb color, ICmy item) 6 | { 7 | item.C = 1 - (color.R / 255.0); 8 | item.M = 1 - (color.G / 255.0); 9 | item.Y = 1 - (color.B / 255.0); 10 | } 11 | 12 | internal static IRgb ToColor(ICmy item) 13 | { 14 | return new Rgb 15 | { 16 | R = (1 - item.C) * 255.0, 17 | G = (1 - item.M) * 255.0, 18 | B = (1 - item.Y) * 255.0 19 | }; 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /ColorMine/Themes/GifItemizer.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using System.Drawing.Imaging; 3 | using System.IO; 4 | using ColorMine.Themes.Adapters; 5 | 6 | namespace ColorMine.Themes 7 | { 8 | /// 9 | /// Converts an image into an IColorCatalog by converting to a gif and returning the converted colors 10 | /// 11 | public sealed class GifItemizer : IItemizerStrategy 12 | { 13 | public T Itemize(IImage image) where T : ICatalog, new() 14 | { 15 | using(var stream = new MemoryStream()) 16 | { 17 | image.Save(stream, ImageFormat.Gif); 18 | return new T 19 | { 20 | Image = new BitmapAdapter(new Bitmap(stream)) 21 | }; 22 | } 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #OS junk files 2 | [Tt]humbs.db 3 | *.DS_Store 4 | 5 | #Visual Studio files 6 | *.[Oo]bj 7 | *.user 8 | *.aps 9 | *.pch 10 | *.vspscc 11 | *.vssscc 12 | *_i.c 13 | *_p.c 14 | *.ncb 15 | *.suo 16 | *.tlb 17 | *.tlh 18 | *.bak 19 | *.[Cc]ache 20 | *.ilk 21 | *.log 22 | *.lib 23 | *.sbr 24 | *.sdf 25 | *.opensdf 26 | *.unsuccessfulbuild 27 | ipch/ 28 | obj/ 29 | [Bb]in 30 | [Dd]ebug*/ 31 | [Rr]elease*/ 32 | Ankh.NoLoad 33 | 34 | #MonoDevelop 35 | *.pidb 36 | *.userprefs 37 | 38 | #Tooling 39 | _ReSharper*/ 40 | *.resharper 41 | [Tt]est[Rr]esult* 42 | *.sass-cache 43 | 44 | #Project files 45 | [Bb]uild/ 46 | 47 | #Subversion files 48 | .svn 49 | 50 | # Office Temp Files 51 | ~$* 52 | 53 | #NuGet 54 | packages/ 55 | 56 | #ncrunch 57 | *ncrunch* 58 | *crunch*.local.xml 59 | 60 | # visual studio database projects 61 | *.dbmdl 62 | 63 | #Test files 64 | *.testsettings -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ColorMine 2 | ========= 3 | 4 | MIT Licensed .Net library intended to make working with colors easy. 5 | 6 | You can do stuff like easily convert between colors spaces like Rgb, Hsl, Xyz, Yyz, Cmy, Cmyk, and CIE*Lab. More spaces supported soon! 7 | 8 | ```c# 9 | var startingRgb = new Rgb { R = 149, G = 13, B = 12 } 10 | var cmy = startingColor.To(); 11 | ``` 12 | 13 | Online example at http://colormine.org/color-converter 14 | 15 | You can also calculate delta-e, it's currently a bit awkward but undergoing rapid development. More algorithms coming soon! 16 | 17 | CIE76 http://colormine.org/delta-e-calculator/ 18 | ```c# 19 | var deltaE = startingRgb.Compare(cmy,new Cie1976Comparison()); 20 | ``` 21 | 22 | CMC l:C http://colormine.org/delta-e-calculator/cmc 23 | ```c# 24 | var deltaE = startingRgb.Compare(cmy,new CmcComparison(lightness: 2, chroma: 1)); 25 | ``` 26 | -------------------------------------------------------------------------------- /ColorMine/Themes/Adapters/BitmapAdapter.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using System.Drawing.Imaging; 3 | using System.IO; 4 | 5 | namespace ColorMine.Themes.Adapters 6 | { 7 | internal sealed class BitmapAdapter : IImage 8 | { 9 | private readonly Bitmap _image; 10 | internal BitmapAdapter(Bitmap image) 11 | { 12 | _image = image; 13 | } 14 | 15 | public int Width 16 | { 17 | get { return _image.Width; } 18 | } 19 | 20 | public int Height 21 | { 22 | get { return _image.Height; } 23 | } 24 | 25 | public Color GetPixel(int x, int y) 26 | { 27 | return _image.GetPixel(x, y); 28 | } 29 | 30 | public void Save(Stream stream, ImageFormat format) 31 | { 32 | _image.Save(stream, format); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /ColorMine/ColorSpaces/Conversions/YxyConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using ColorMine.Utility; 3 | 4 | namespace ColorMine.ColorSpaces.Conversions 5 | { 6 | internal static class YxyConverter 7 | { 8 | internal static void ToColorSpace(IRgb color, IYxy item) 9 | { 10 | var xyz = new Xyz(); 11 | xyz.Initialize(color); 12 | 13 | item.Y1 = xyz.Y; 14 | 15 | var xDividend = xyz.X + xyz.Y + xyz.Z; 16 | item.X = xDividend.BasicallyEqualTo(0) ? 0 : xyz.X / xDividend; 17 | 18 | var y2Dividend = xyz.X + xyz.Y + xyz.Z; 19 | item.Y2 = y2Dividend.BasicallyEqualTo(0) ? 0 : xyz.Y / (xyz.X + xyz.Y + xyz.Z); 20 | } 21 | 22 | internal static IRgb ToColor(IYxy item) 23 | { 24 | var xyz = new Xyz 25 | { 26 | X = item.X*(item.Y1/item.Y2), 27 | Y = item.Y1, 28 | Z = (1 - item.X - item.Y2) * (item.Y1 / item.Y2) 29 | }; 30 | return xyz.ToRgb(); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /ColorMine.Test/Utility/DoubleExtensionTest.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | using ColorMine.Utility; 3 | 4 | namespace ColorMine.Test.Utility 5 | { 6 | public class DoubleExtensionTest 7 | { 8 | [TestClass] 9 | public class BasicallyEqualTo 10 | { 11 | [TestMethod] 12 | public void ReturnsTrueForCloseNumbers() 13 | { 14 | Assert.IsTrue(.333.BasicallyEqualTo(1.0/3,.01)); 15 | } 16 | 17 | [TestMethod] 18 | public void ReturnsFalseForFarNumbers() 19 | { 20 | Assert.IsFalse(.9.BasicallyEqualTo(.1,.001)); 21 | } 22 | 23 | [TestMethod] 24 | public void ReturnsTrueForCloseNumbersWithDefaultPrecision() 25 | { 26 | Assert.IsTrue(.33333.BasicallyEqualTo(1.0 / 3)); 27 | } 28 | 29 | [TestMethod] 30 | public void ReturnsFalseForFarNumbersWithDefaultPrecision() 31 | { 32 | Assert.IsFalse(.9.BasicallyEqualTo(.1)); 33 | } 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 ColorMine.org 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /ColorMine/Themes/PercentagePaletteInventory.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Drawing; 3 | 4 | namespace ColorMine.Themes 5 | { 6 | public sealed class PercentagePaletteInventory : ICatalog 7 | { 8 | public IDictionary Items { get; private set; } 9 | 10 | public IImage Image 11 | { 12 | set 13 | { 14 | var items = new Dictionary(); 15 | 16 | if (value.Width == 0 || value.Height == 0) 17 | { 18 | Items = items; 19 | return; 20 | } 21 | 22 | var increment = 1.0/(value.Width * value.Height); 23 | for (var y = 0; y < value.Height; y++) 24 | { 25 | for (var x = 0; x < value.Width; x++) 26 | { 27 | var color = value.GetPixel(x, y); 28 | items[color] = items.ContainsKey(color) ? items[color] + increment : increment; 29 | } 30 | } 31 | Items = items; 32 | } 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /ColorMine/ColorSpaces/Conversions/CmykConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using ColorMine.Utility; 3 | 4 | // dependent on Cmy 5 | 6 | namespace ColorMine.ColorSpaces.Conversions 7 | { 8 | internal static class CmykConverter 9 | { 10 | internal static void ToColorSpace(IRgb color, ICmyk item) 11 | { 12 | var cmy = new Cmy(); 13 | cmy.Initialize(color); 14 | 15 | var k = 1.0; 16 | if (cmy.C < k) k = cmy.C; 17 | if (cmy.M < k) k = cmy.M; 18 | if (cmy.Y < k) k = cmy.Y; 19 | item.K = k; 20 | 21 | if (k.BasicallyEqualTo(1)) 22 | { 23 | item.C = 0; 24 | item.M = 0; 25 | item.Y = 0; 26 | } 27 | else 28 | { 29 | item.C = (cmy.C - k) / (1 - k); 30 | item.M = (cmy.M - k) / (1 - k); 31 | item.Y = (cmy.Y - k) / (1 - k); 32 | } 33 | } 34 | 35 | internal static IRgb ToColor(ICmyk item) 36 | { 37 | var cmy = new Cmy 38 | { 39 | C = (item.C*(1 - item.K) + item.K), 40 | M = (item.M*(1 - item.K) + item.K), 41 | Y = (item.Y*(1 - item.K) + item.K) 42 | }; 43 | 44 | return cmy.ToRgb(); 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /ColorMine.Test/Themes/GifItemizerTest.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using ColorMine.Themes; 3 | using ColorMine.Themes.Adapters; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | 6 | namespace ColorMine.Test.Themes 7 | { 8 | public class GifItemizerTest 9 | { 10 | [TestClass] 11 | public class Itemize 12 | { 13 | private static void ColorConverted(Color startColor, Color destinationColor) 14 | { 15 | // TODO: Need to moq here, but it's difficult... 16 | var bitmap = new Bitmap(1, 1); 17 | bitmap.SetPixel(0, 0, startColor); 18 | var image = new BitmapAdapter(bitmap); 19 | 20 | var itemizer = new GifItemizer(); 21 | var inventory = itemizer.Itemize(image); 22 | 23 | Assert.IsTrue(inventory.Items.ContainsKey(destinationColor)); 24 | } 25 | 26 | [TestMethod] 27 | public void SlightlyOffRedGetsConvertedToRed() 28 | { 29 | ColorConverted(Color.FromArgb(255, 255, 0, 1),Color.FromArgb(255, 255, 0, 0)); 30 | } 31 | 32 | [TestMethod] 33 | public void SlightlyOffBlueGetsConvertedToBlue() 34 | { 35 | ColorConverted(Color.FromArgb(255, 1, 1, 255), Color.FromArgb(255, 0, 0, 255)); 36 | } 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /ColorMine/ColorSpaces/Conversions/LchConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ColorMine.ColorSpaces.Conversions 4 | { 5 | internal static class LchConverter 6 | { 7 | // http://www.brucelindbloom.com/index.html?Eqn_Lab_to_LCH.html 8 | // http://www.easyrgb.com/index.php?X=MATH&H=09#text9 9 | // http://www.colourphil.co.uk/lab_lch_colour_space.html 10 | 11 | internal static void ToColorSpace(IRgb color, ILch item) 12 | { 13 | var lab = color.To(); 14 | var h = Math.Atan2(lab.B, lab.A); 15 | 16 | // convert from radians to degrees 17 | if (h > 0) 18 | { 19 | h = (h/Math.PI)*180; 20 | } 21 | else 22 | { 23 | h = 360 - (Math.Abs(h)/Math.PI)*180; 24 | } 25 | 26 | item.L = lab.L; 27 | item.C = Math.Sqrt(Math.Pow(lab.A,2) + Math.Pow(lab.B,2)); 28 | item.H = h % 360; 29 | } 30 | 31 | internal static IRgb ToColor(ILch item) 32 | { 33 | var hRadians = (Math.PI * item.H) / 180.0; 34 | var lab = new Lab 35 | { 36 | L = item.L, 37 | A = Math.Cos(hRadians) * item.C, 38 | B = Math.Sin(hRadians) * item.C 39 | }; 40 | return lab.To(); 41 | } 42 | 43 | } 44 | } -------------------------------------------------------------------------------- /ColorMine.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ColorMine", "ColorMine\ColorMine.csproj", "{AE7DC769-4A71-49BA-BDD7-281F3E70B02A}" 5 | EndProject 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ColorMine.Test", "ColorMine.Test\ColorMine.Test.csproj", "{318DFB24-B947-4B07-AFDB-561A262EB424}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {AE7DC769-4A71-49BA-BDD7-281F3E70B02A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {AE7DC769-4A71-49BA-BDD7-281F3E70B02A}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {AE7DC769-4A71-49BA-BDD7-281F3E70B02A}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {AE7DC769-4A71-49BA-BDD7-281F3E70B02A}.Release|Any CPU.Build.0 = Release|Any CPU 18 | {318DFB24-B947-4B07-AFDB-561A262EB424}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {318DFB24-B947-4B07-AFDB-561A262EB424}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {318DFB24-B947-4B07-AFDB-561A262EB424}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {318DFB24-B947-4B07-AFDB-561A262EB424}.Release|Any CPU.Build.0 = Release|Any CPU 22 | EndGlobalSection 23 | GlobalSection(SolutionProperties) = preSolution 24 | HideSolutionNode = FALSE 25 | EndGlobalSection 26 | EndGlobal 27 | -------------------------------------------------------------------------------- /ColorMine.Test/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ColorMine.Test")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ColorMine.Test")] 13 | [assembly: AssemblyCopyright("Copyright © 2013")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("8240b1b4-7061-4f80-886f-d3e475476982")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /ColorMine/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | 9 | [assembly: AssemblyTitle("ColorMine")] 10 | [assembly: AssemblyDescription("")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("")] 13 | [assembly: AssemblyProduct("ColorMine")] 14 | [assembly: AssemblyCopyright("Copyright © 2013")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | 18 | // Setting ComVisible to false makes the types in this assembly not visible 19 | // to COM components. If you need to access a type in this assembly from 20 | // COM, set the ComVisible attribute to true on that type. 21 | 22 | [assembly: ComVisible(false)] 23 | 24 | // The following GUID is for the ID of the typelib if this project is exposed to COM 25 | 26 | [assembly: Guid("5b29e3b7-5264-4ad2-b05f-db8165f179e7")] 27 | 28 | // Version information for an assembly consists of the following four values: 29 | // 30 | // Major Version 31 | // Minor Version 32 | // Build Number 33 | // Revision 34 | // 35 | // You can specify all the values or you can default the Build and Revision Numbers 36 | // by using the '*' as shown below: 37 | // [assembly: AssemblyVersion("1.0.*")] 38 | 39 | [assembly: AssemblyVersion("1.0.0.0")] 40 | [assembly: AssemblyFileVersion("1.0.0.0")] 41 | [assembly: InternalsVisibleTo("ColorMine.Test")] -------------------------------------------------------------------------------- /ColorMine/ColorSpaces/ColorSpaces.tt: -------------------------------------------------------------------------------- 1 | <#@ template debug="true" hostspecific="true" language="C#" #> 2 | <#@ assembly name="System.Core" #> 3 | <#@ assembly name="System.Xml.dll" #> 4 | <#@ import namespace="System.Linq" #> 5 | <#@ import namespace="System.Text" #> 6 | <#@ import Namespace="System.Xml" #> 7 | <#@ import Namespace="System.IO" #> 8 | <#@ import namespace="System.Collections.Generic" #> 9 | <# 10 | var document = new XmlDocument(); 11 | var file = Host.ResolvePath("ColorSpaces.xml"); 12 | document.Load(file); 13 | var colorSpaces = document.SelectNodes("colorSpaces/colorSpace"); 14 | #> 15 | <#@ output extension=".cs" #>//Note: This is a generated file. 16 | using ColorMine.ColorSpaces.Conversions; 17 | 18 | namespace ColorMine.ColorSpaces 19 | { 20 | <# foreach (XmlNode space in colorSpaces) { 21 | var spaceName = space.Attributes["name"].Value; 22 | var points = space.SelectNodes("dataPoints/dataPoint");#> 23 | public interface I<#=spaceName#> : IColorSpace 24 | { 25 | <# foreach(XmlNode point in points) { #> 26 | double <#=point.Attributes["label"].Value#> { get; set; } 27 | <# } #> 28 | } 29 | 30 | public class <#=spaceName#> : ColorSpace, I<#=spaceName#> 31 | { 32 | <# foreach(XmlNode point in points) { #> 33 | public double <#=point.Attributes["label"].Value#> { get; set; } 34 | <# } #> 35 | 36 | public override void Initialize(IRgb color) 37 | { 38 | <#=spaceName#>Converter.ToColorSpace(color,this); 39 | } 40 | 41 | public override IRgb ToRgb() 42 | { 43 | return <#=spaceName#>Converter.ToColor(this); 44 | } 45 | } 46 | 47 | <# } #> 48 | } -------------------------------------------------------------------------------- /ColorMine.Test/ColorSpaces/ConversionTests.tt: -------------------------------------------------------------------------------- 1 | <#@ template debug="true" hostspecific="true" language="C#" #> 2 | <#@ assembly name="System.Core" #> 3 | <#@ assembly name="System.Xml.dll" #> 4 | <#@ import namespace="System.Linq" #> 5 | <#@ import namespace="System.Text" #> 6 | <#@ import Namespace="System.Xml" #> 7 | <#@ import Namespace="System.IO" #> 8 | <#@ import namespace="System.Collections.Generic" #> 9 | <# 10 | var document = new XmlDocument(); 11 | var file = Host.ResolvePath("ConversionResults.xml"); 12 | document.Load(file); 13 | var colors = document.SelectNodes("ConversionResults/*"); 14 | #> 15 | <#@ output extension=".cs" #>//Note: This is a generated file. 16 | using ColorMine.ColorSpaces; 17 | using Microsoft.VisualStudio.TestTools.UnitTesting; 18 | 19 | namespace ColorMine.Test.ColorSpaces 20 | { 21 | 22 | <# foreach (XmlNode fromSpace in colors) { var fromName = fromSpace.Name; #> 23 | public class <#= fromName #>Test 24 | { 25 | [TestClass] 26 | public class To : ColorSpaceTest 27 | { 28 | <# foreach(XmlNode test in fromSpace.ChildNodes) { 29 | var colorName = test.Attributes["Name"].Value; 30 | foreach (XmlNode toSpace in test.ChildNodes) { var toName = toSpace.Name; #> 31 | 32 | [TestMethod] 33 | public void <#= colorName #><#= fromName #>To<#= toName #>() 34 | { 35 | var knownColor = new <#= fromName #> {<# foreach (XmlNode attribute in test.Attributes) { if(attribute.Name != "Name") { #> <#= attribute.Name #> = <#= attribute.Value #>,<# } } #> }; 36 | var expectedColor = new <#= toName #> {<# foreach (XmlNode attribute in toSpace.Attributes) { if(attribute.Name != "Name") { #> <#= attribute.Name #> = <#= attribute.Value #>,<# } } #> }; 37 | 38 | ExpectedValuesForKnownColor(knownColor,expectedColor); 39 | } 40 | <# } } #> 41 | 42 | } 43 | } 44 | <# } #> 45 | } -------------------------------------------------------------------------------- /ColorMine/ColorSpaces/Conversions/XyzConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | 4 | namespace ColorMine.ColorSpaces.Conversions 5 | { 6 | internal static class XyzConverter 7 | { 8 | internal static void ToColorSpace(IRgb color, IXyz item) 9 | { 10 | var r = PivotRgb(color.R / 255.0); 11 | var g = PivotRgb(color.G / 255.0); 12 | var b = PivotRgb(color.B / 255.0); 13 | 14 | // Observer. = 2°, Illuminant = D65 15 | item.X = r*0.4124 + g*0.3576 + b*0.1805; 16 | item.Y = r*0.2126 + g*0.7152 + b*0.0722; 17 | item.Z = r*0.0193 + g*0.1192 + b*0.9505; 18 | } 19 | 20 | internal static IRgb ToColor(IXyz item) 21 | { 22 | // (Observer = 2°, Illuminant = D65) 23 | var x = item.X / 100; 24 | var y = item.Y / 100; 25 | var z = item.Z / 100; 26 | 27 | var r = x * 3.2406 + y * -1.5372 + z * -0.4986; 28 | var g = x * -0.9689 + y * 1.8758 + z * 0.0415; 29 | var b = x * 0.0557 + y * -0.2040 + z * 1.0570; 30 | 31 | r = r > 0.0031308 ? 1.055*Math.Pow(r, 1/2.4) - 0.055 : 12.92*r; 32 | g = g > 0.0031308 ? 1.055*Math.Pow(g, 1/2.4) - 0.055 : 12.92*g; 33 | b = b > 0.0031308 ? 1.055*Math.Pow(b, 1/2.4) - 0.055 : 12.92*b; 34 | 35 | return new Rgb 36 | { 37 | R = ToRgb(r), 38 | G = ToRgb(g), 39 | B = ToRgb(b) 40 | }; 41 | } 42 | 43 | private static int ToRgb(double n) 44 | { 45 | return Math.Min(255, Math.Max(0, (int) (n*255))); 46 | } 47 | 48 | private static double PivotRgb(double n) 49 | { 50 | return (n > 0.04045 ? Math.Pow((n + 0.055)/1.055, 2.4) : n/12.92)*100; 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /ColorMine/ColorSpaces/Conversions/LabConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ColorMine.ColorSpaces.Conversions 4 | { 5 | internal static class LabConverter 6 | { 7 | // Observer= 2°, Illuminant= D65 8 | private const double RefX = 95.047; 9 | private const double RefY = 100.000; 10 | private const double RefZ = 108.883; 11 | 12 | internal static void ToColorSpace(IRgb color, ILab item) 13 | { 14 | var xyz = new Xyz(); 15 | xyz.Initialize(color); 16 | 17 | var x = PivotXyz(xyz.X/RefX); 18 | var y = PivotXyz(xyz.Y/RefY); 19 | var z = PivotXyz(xyz.Z/RefZ); 20 | 21 | item.L = Math.Max(0,116*y - 16); 22 | item.A = 500*(x - y); 23 | item.B = 200*(y - z); 24 | } 25 | 26 | internal static IRgb ToColor(ILab item) 27 | { 28 | var y = (item.L + 16) / 116.0; 29 | var x = item.A / 500.0 + y; 30 | var z = y - item.B / 200.0; 31 | 32 | y = Math.Pow(y, 3) > 0.008856 ? Math.Pow(y, 3) : (y - 16/116)/7.787; 33 | x = Math.Pow(x, 3) > 0.008856 ? Math.Pow(x, 3) : (x - 16/116)/7.787; 34 | z = Math.Pow(z, 3) > 0.008856 ? Math.Pow(z, 3) : (z - 16/116)/7.787; 35 | 36 | var xyz = new Xyz 37 | { 38 | X = RefX*x, 39 | Y = RefY*y, 40 | Z = RefZ*z 41 | }; 42 | 43 | return xyz.ToRgb(); 44 | } 45 | 46 | private static double PivotXyz(double n) 47 | { 48 | var i = CubicRoot(n); 49 | return n > 0.008856 ? i : 7.787*n + 16/116; 50 | } 51 | 52 | private static double CubicRoot(double n) 53 | { 54 | return Math.Pow(n, (1.0/3.0)); 55 | } 56 | } 57 | } -------------------------------------------------------------------------------- /ColorMine.Test/ColorSpaces/ColorSpaceTest.tt: -------------------------------------------------------------------------------- 1 | <#@ template debug="true" hostspecific="true" language="C#" #> 2 | <#@ assembly name="System.Core" #> 3 | <#@ assembly name="System.Xml.dll" #> 4 | <#@ import namespace="System.Linq" #> 5 | <#@ import namespace="System.Text" #> 6 | <#@ import Namespace="System.Xml" #> 7 | <#@ import Namespace="System.IO" #> 8 | <#@ import namespace="System.Collections.Generic" #> 9 | <# 10 | var document = new XmlDocument(); 11 | var file = Host.ResolvePath("ConversionResults.xml"); 12 | document.Load(file); 13 | var colors = document.SelectNodes("ConversionResults/*"); 14 | #> 15 | <#@ output extension=".cs" #>//Note: This is a generated file. 16 | using ColorMine.ColorSpaces; 17 | using Microsoft.VisualStudio.TestTools.UnitTesting; 18 | using System; 19 | 20 | namespace ColorMine.Test.ColorSpaces 21 | { 22 | public abstract class ColorSpaceTest 23 | { 24 | <# 25 | var fromSpace = colors[0]; 26 | var fromName = fromSpace.Name; 27 | var test = fromSpace.ChildNodes[0]; 28 | var colorName = test.Attributes["Name"].Value; 29 | 30 | foreach (XmlNode toSpace in test.ChildNodes) { 31 | var toName = toSpace.Name; 32 | #> 33 | 34 | protected static void ExpectedValuesForKnownColor(IColorSpace knownColor, I<#= toName #> expectedColor) 35 | { 36 | var target = knownColor.To<<#= toName #>>(); 37 | 38 | <# foreach (XmlNode attribute in toSpace.Attributes) { if(attribute.Name != "Name") { #> 39 | Assert.IsTrue(CloseEnough(expectedColor.<#= attribute.Name #>,target.<#= attribute.Name #>),"(<#= attribute.Name #>)" + expectedColor.<#= attribute.Name #> + " != " + target.<#= attribute.Name #>); 40 | <# } }#> 41 | } 42 | <# } #> 43 | private static bool CloseEnough(double a, double b) 44 | { 45 | // Define the tolerance for variation in their values 46 | var difference = Math.Abs(a * .01); 47 | 48 | // Compare the values 49 | // The output to the console indicates that the two values are equal 50 | return Math.Abs(a - b) <= difference; 51 | } 52 | 53 | } 54 | 55 | } -------------------------------------------------------------------------------- /ColorMine/ColorSpaces/ColorSpaces.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /ColorMine/ColorSpaces/Comparisons/CmcComparison.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace ColorMine.ColorSpaces.Comparisons 4 | { 5 | public class CmcComparison : IDeltaEComparison 6 | { 7 | public const double DefaultLightness = 2.0; 8 | public const double DefaultChroma = 1.0; 9 | 10 | private readonly double _lightness; 11 | private readonly double _chroma; 12 | 13 | public CmcComparison() 14 | { 15 | _lightness = DefaultLightness; 16 | _chroma = DefaultChroma; 17 | } 18 | 19 | public CmcComparison(double lightness = DefaultLightness, double chroma = DefaultChroma) 20 | { 21 | _lightness = lightness; 22 | _chroma = chroma; 23 | } 24 | 25 | public double Compare(IColorSpace colorA, IColorSpace colorB) 26 | { 27 | var aLab = colorA.To(); 28 | var bLab = colorB.To(); 29 | 30 | var deltaL = aLab.L - bLab.L; 31 | var h = Math.Atan2(aLab.B,aLab.A); 32 | 33 | var c1 = Math.Sqrt(Math.Pow(aLab.A, 2) + Math.Pow(aLab.B, 2)); 34 | var c2 = Math.Sqrt(Math.Pow(bLab.A, 2) + Math.Pow(bLab.B, 2)); 35 | var deltaC = c1 - c2; 36 | 37 | var deltaH = Math.Sqrt(Math.Pow(aLab.A - bLab.A, 2) + Math.Pow(aLab.B - bLab.B, 2) - Math.Pow(deltaC,2)); 38 | 39 | var t = 164 <= h || h >= 345 40 | ? .56 + Math.Abs(.2*Math.Cos(h + 168.0)) 41 | : .36 + Math.Abs(.4*Math.Cos(h + 35.0)); 42 | var f = Math.Sqrt(Math.Pow(c1,4)/(Math.Pow(c1,4) + 1900.0)); 43 | 44 | var sL = aLab.L < 16 ? .511 : (.040975 * aLab.L) / (1.0 + .01765 * aLab.L); 45 | var sC = (.0638 * c1) / (1 + .0131 * c1) + .638; 46 | var sH = sC*(f*t + 1 - f); 47 | 48 | var differences = DistanceDivided(deltaL, _lightness * sL) + 49 | DistanceDivided(deltaC, _chroma * sC) + 50 | DistanceDivided(deltaH, sH); 51 | 52 | return Math.Sqrt(differences); 53 | } 54 | 55 | private static double DistanceDivided(double a, double dividend) 56 | { 57 | return Math.Pow(a / dividend, 2); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /ColorMine/ColorSpaces/ColorSpace.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using ColorMine.ColorSpaces.Comparisons; 3 | 4 | namespace ColorMine.ColorSpaces 5 | { 6 | public delegate double ComparisonAlgorithm(IColorSpace a, IColorSpace b); 7 | 8 | public interface IColorSpace 9 | { 10 | /// 11 | /// Initialize settings from an Rgb object 12 | /// 13 | /// System.Drawing.Color 14 | void Initialize(IRgb color); 15 | 16 | /// 17 | /// Convert the color space to a Rgb, you should probably using the "To" method instead. 18 | /// 19 | /// System.Drawing.Color object 20 | IRgb ToRgb(); 21 | 22 | /// 23 | /// Convert any IColorSpace to any other IColorSpace 24 | /// 25 | /// IColorSpace type to convert to 26 | /// 27 | T To() where T : IColorSpace, new(); 28 | 29 | /// 30 | /// Determine how close two IColorSpaces are to each other using a passed in algorithm 31 | /// 32 | /// Other IColorSpace to compare to 33 | /// Algorithm to use for comparison 34 | /// the distance in 3d space as double 35 | double Compare(IColorSpace compareToValue, IColorSpaceComparison comparer); 36 | } 37 | 38 | internal interface IColorConvertable 39 | { 40 | 41 | } 42 | 43 | public abstract class ColorSpace : IColorSpace 44 | { 45 | public abstract void Initialize(IRgb color); 46 | public abstract IRgb ToRgb(); 47 | 48 | public double Compare(IColorSpace compareToValue, IColorSpaceComparison comparer) 49 | { 50 | return comparer.Compare(this, compareToValue); 51 | } 52 | 53 | public T To() where T : IColorSpace, new() 54 | { 55 | if (typeof (T) == GetType()) 56 | { 57 | return (T) MemberwiseClone(); 58 | } 59 | 60 | var newColorSpace = new T(); 61 | newColorSpace.Initialize(ToRgb()); 62 | 63 | return newColorSpace; 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /ColorMine.Test/Themes/Adapters/BitmapAdapterTest.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using System.Drawing.Imaging; 3 | using System.IO; 4 | using ColorMine.Themes.Adapters; 5 | using Microsoft.VisualStudio.TestTools.UnitTesting; 6 | 7 | namespace ColorMine.Test.Themes.Adapters 8 | { 9 | class BitmapAdapterTest 10 | { 11 | [TestClass] 12 | public class Width 13 | { 14 | [TestMethod] 15 | public void ReturnsExpectedValue() 16 | { 17 | var bitmap = new Bitmap(10, 10); 18 | var adapter = new BitmapAdapter(bitmap); 19 | 20 | Assert.AreEqual(bitmap.Width,adapter.Width); 21 | } 22 | } 23 | 24 | [TestClass] 25 | public class Height 26 | { 27 | [TestMethod] 28 | public void ReturnsExpectedValue() 29 | { 30 | var bitmap = new Bitmap(10, 10); 31 | var adapter = new BitmapAdapter(bitmap); 32 | 33 | Assert.AreEqual(bitmap.Height,adapter.Height); 34 | } 35 | } 36 | 37 | [TestClass] 38 | public class GetPixel 39 | { 40 | [TestMethod] 41 | public void ReturnsExpectedValue() 42 | { 43 | var color = Color.FromArgb(255, 255, 235, 205); 44 | var bitmap = new Bitmap(10, 10); 45 | bitmap.SetPixel(5, 7, color); 46 | 47 | var adapter = new BitmapAdapter(bitmap); 48 | 49 | Assert.AreEqual(color,adapter.GetPixel(5,7)); 50 | } 51 | } 52 | 53 | [TestClass] 54 | public class Save 55 | { 56 | [TestMethod] 57 | public void NoError() 58 | { 59 | var color = Color.FromArgb(255, 153, 213, 255); 60 | var bitmap = new Bitmap(1, 1); 61 | bitmap.SetPixel(0, 0, color); 62 | var adapter = new BitmapAdapter(bitmap); 63 | 64 | using(var stream = new MemoryStream()) 65 | { 66 | adapter.Save(stream,ImageFormat.Gif); 67 | var newBitmap = new Bitmap(stream); 68 | Assert.AreEqual(color,newBitmap.GetPixel(0,0)); 69 | } 70 | } 71 | 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /ColorMine.Test/Themes/PercentagePaletteInventoryTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using ColorMine.Themes; 4 | using Microsoft.VisualStudio.TestTools.UnitTesting; 5 | 6 | namespace ColorMine.Test.Themes 7 | { 8 | class PercentagePaletteInventoryTest 9 | { 10 | [TestClass] 11 | public class Image 12 | { 13 | [TestMethod] 14 | public void EmptyImageReturnsEmptyPalette() 15 | { 16 | var image = new Moq.Mock(); 17 | image.Setup(x => x.Height).Returns(0); 18 | image.Setup(x => x.Width).Returns(0); 19 | 20 | var p = new PercentagePaletteInventory 21 | { 22 | Image = image.Object 23 | }; 24 | Assert.AreEqual(0,p.Items.Count); 25 | } 26 | 27 | private const double Epsilon = .1; 28 | 29 | [TestMethod] 30 | public void RedImageReturnsRedPalette() 31 | { 32 | var image = new Moq.Mock(); 33 | image.Setup(x => x.Width).Returns(1); 34 | image.Setup(x => x.Height).Returns(1); 35 | image.Setup(x => x.GetPixel(0,0)).Returns(Color.Red); 36 | 37 | var p = new PercentagePaletteInventory 38 | { 39 | Image = image.Object 40 | }; 41 | 42 | Assert.IsTrue(Math.Abs(p.Items[Color.Red] - 1) < Epsilon); 43 | } 44 | 45 | [TestMethod] 46 | public void MixedImageReturnsMixedPalette() 47 | { 48 | var image = new Moq.Mock(); 49 | image.Setup(x => x.Width).Returns(1); 50 | image.Setup(x => x.Height).Returns(2); 51 | image.Setup(x => x.GetPixel(0, 0)).Returns(Color.Red); 52 | image.Setup(x => x.GetPixel(0, 1)).Returns(Color.Blue); 53 | 54 | var p = new PercentagePaletteInventory 55 | { 56 | Image = image.Object 57 | }; 58 | 59 | // TODO: 2 Asserts, smells bad 60 | Assert.IsTrue(Math.Abs(p.Items[Color.Red] - .5) < Epsilon); 61 | Assert.IsTrue(Math.Abs(p.Items[Color.Blue] - .5) < Epsilon); 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /ColorMine/ColorSpaces/Conversions/HslConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using ColorMine.Utility; 3 | 4 | namespace ColorMine.ColorSpaces.Conversions 5 | { 6 | internal static class HslConverter 7 | { 8 | internal static void ToColorSpace(IRgb color, IHsl item) 9 | { 10 | // TODO Losing precision 11 | var msColor = Color.FromArgb((int)color.R, (int)color.G, (int)color.B); 12 | item.H = msColor.GetHue(); 13 | item.S = msColor.GetSaturation() * 100; 14 | item.L = msColor.GetBrightness() * 100; 15 | } 16 | 17 | internal static IRgb ToColor(IHsl item) 18 | { 19 | var rangedH = item.H/360.0; 20 | var r = 0.0; 21 | var g = 0.0; 22 | var b = 0.0; 23 | var s = item.S / 100; 24 | var l = item.L/100; 25 | 26 | if (!l.BasicallyEqualTo(0)) 27 | { 28 | if (s.BasicallyEqualTo(0)) 29 | { 30 | r = g = b = l; 31 | } 32 | else 33 | { 34 | var temp2 = (l < 0.5) ? l*(1.0 + s) : l + s - (l*s); 35 | var temp1 = 2.0*l - temp2; 36 | 37 | r = GetColorComponent(temp1, temp2, rangedH + 1.0/3.0); 38 | g = GetColorComponent(temp1, temp2, rangedH); 39 | b = GetColorComponent(temp1, temp2, rangedH - 1.0/3.0); 40 | } 41 | } 42 | return new Rgb 43 | { 44 | R = 255*r, 45 | G = 255*g, 46 | B = 255*b 47 | }; 48 | } 49 | 50 | private static double GetColorComponent(double temp1, double temp2, double temp3) 51 | { 52 | temp3 = MoveIntoRange(temp3); 53 | if (temp3 < 1.0/6.0) 54 | { 55 | return temp1 + (temp2 - temp1)*6.0*temp3; 56 | } 57 | 58 | if (temp3 < 0.5) 59 | { 60 | return temp2; 61 | } 62 | 63 | if (temp3 < 2.0/3.0) 64 | { 65 | return temp1 + ((temp2 - temp1)*((2.0/3.0) - temp3)*6.0); 66 | } 67 | 68 | return temp1; 69 | } 70 | 71 | private static double MoveIntoRange(double temp3) 72 | { 73 | if (temp3 < 0.0) return temp3 + 1; 74 | if (temp3 > 1.0) return temp3 - 1; 75 | return temp3; 76 | } 77 | } 78 | } -------------------------------------------------------------------------------- /ColorMine.Test/ColorSpaces/Comparisons/Cie1976ComparisonTest.cs: -------------------------------------------------------------------------------- 1 | using ColorMine.ColorSpaces; 2 | using ColorMine.ColorSpaces.Comparisons; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | using ColorMine.Utility; 5 | 6 | namespace ColorMine.Test.ColorSpaces.Comparisons 7 | { 8 | public class Cie1976ComparisonTest 9 | { 10 | [TestClass] 11 | public class Compare 12 | { 13 | private void ReturnsExpectedValueForKnownInput(double expectedValue, IColorSpace a, IColorSpace b) 14 | { 15 | var target = new Cie1976Comparison(); 16 | var actualValue = a.Compare(b, target); 17 | Assert.IsTrue(expectedValue.BasicallyEqualTo(actualValue)); 18 | } 19 | 20 | [TestMethod] 21 | public void ReturnsZeroForSameColors() 22 | { 23 | var compareColor = new Rgb {R = 140, G = 130, B = 23}; 24 | // Todo, should be mocking!! 25 | var a = new Rgb(); 26 | a.Initialize(compareColor); 27 | 28 | var b = new Rgb(); 29 | b.Initialize(compareColor); 30 | 31 | ReturnsExpectedValueForKnownInput(0.0, a, b); 32 | } 33 | 34 | [TestMethod] 35 | public void ReturnsKnownValueForDissimilarColors() 36 | { 37 | // Todo, should be mocking!! 38 | var a = new Lab 39 | { 40 | L = 50, 41 | A = 67, 42 | B = 88 43 | }; 44 | 45 | var b = new Lab 46 | { 47 | L = 50, 48 | A = 15, 49 | B = 22 50 | }; 51 | 52 | ReturnsExpectedValueForKnownInput(84.0238, a, b); 53 | } 54 | 55 | [TestMethod] 56 | public void ReturnsKnownValueForSimilarColors() 57 | { 58 | // Todo, should be mocking!! 59 | var a = new Lab 60 | { 61 | L = 88.17, 62 | A = 67, 63 | B = 88 64 | }; 65 | 66 | var b = new Lab 67 | { 68 | L = 87.16, 69 | A = 65, 70 | B = 66 71 | }; 72 | 73 | ReturnsExpectedValueForKnownInput(22.1138, a, b); 74 | } 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /ColorMine.Test/ColorSpaces/Comparisons/CmcComparisonTest.cs: -------------------------------------------------------------------------------- 1 | using ColorMine.ColorSpaces; 2 | using ColorMine.ColorSpaces.Comparisons; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | using ColorMine.Utility; 5 | 6 | namespace ColorMine.Test.ColorSpaces.Comparisons 7 | { 8 | public class CmcComparisonTest 9 | { 10 | [TestClass] 11 | public class Compare 12 | { 13 | private void ReturnsExpectedValueForKnownInput(double expectedValue, double ratio, IColorSpace a, IColorSpace b) 14 | { 15 | var target = new CmcComparison(ratio); 16 | var actualValue = a.Compare(b, target); 17 | Assert.IsTrue(expectedValue.BasicallyEqualTo(actualValue),expectedValue + " != " + actualValue); 18 | } 19 | 20 | [TestMethod] 21 | public void ReturnsKnownValueForRedAndMaroon2() 22 | { 23 | // Todo, should be mocking!! 24 | var a = new Lab 25 | { 26 | L = 24.8290, 27 | A = 60.0930, 28 | B = 38.1800 29 | }; 30 | 31 | var b = new Lab 32 | { 33 | L = 53.2300, 34 | A = 80.1090, 35 | B = 67.2200 36 | }; 37 | 38 | ReturnsExpectedValueForKnownInput(24.143033, 2, a, b); 39 | } 40 | 41 | 42 | [TestMethod] 43 | public void ReturnsKnownValueForRedAndMaroon1() 44 | { 45 | // Todo, should be mocking!! 46 | var a = new Lab 47 | { 48 | L = 24.8290, 49 | A = 60.0930, 50 | B = 38.1800 51 | }; 52 | 53 | var b = new Lab 54 | { 55 | L = 53.2300, 56 | A = 80.1090, 57 | B = 67.2200 58 | }; 59 | 60 | ReturnsExpectedValueForKnownInput(42.330795, 1, a, b); 61 | } 62 | 63 | [TestMethod] 64 | public void ReturnsKnownValueForWhiteAndEggShell2() 65 | { 66 | // Todo, should be mocking!! 67 | var a = new Lab 68 | { 69 | L = 100, 70 | A = 0, 71 | B = 0 72 | }; 73 | 74 | var b = new Lab 75 | { 76 | L = 89.9490, 77 | A = 13.8320, 78 | B = 6.8160 79 | }; 80 | 81 | ReturnsExpectedValueForKnownInput(24.406318, 2, a, b); 82 | } 83 | 84 | [TestMethod] 85 | public void ReturnsKnownValueForWhiteAndEggShell1() 86 | { 87 | // Todo, should be mocking!! 88 | var a = new Lab 89 | { 90 | L = 100, 91 | A = 0, 92 | B = 0 93 | }; 94 | 95 | var b = new Lab 96 | { 97 | L = 89.9490, 98 | A = 13.8320, 99 | B = 6.8160 100 | }; 101 | 102 | ReturnsExpectedValueForKnownInput(25.103175, 1, a, b); 103 | } 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /ColorMine.Test/ColorSpaces/ConversionResults.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /ColorMine/colormine.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {AE7DC769-4A71-49BA-BDD7-281F3E70B02A} 8 | Library 9 | Properties 10 | ColorMine 11 | ColorMine 12 | v4.5 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | True 46 | True 47 | ColorSpaces.tt 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | TextTemplatingFileGenerator 73 | ColorSpaces.cs 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | Designer 82 | 83 | 84 | 85 | 92 | -------------------------------------------------------------------------------- /ColorMine.Test/ColorSpaces/ColorSpaceTest.cs: -------------------------------------------------------------------------------- 1 | //Note: This is a generated file. 2 | using ColorMine.ColorSpaces; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | using System; 5 | 6 | namespace ColorMine.Test.ColorSpaces 7 | { 8 | public abstract class ColorSpaceTest 9 | { 10 | 11 | protected static void ExpectedValuesForKnownColor(IColorSpace knownColor, ICmy expectedColor) 12 | { 13 | var target = knownColor.To(); 14 | 15 | Assert.IsTrue(CloseEnough(expectedColor.C,target.C),"(C)" + expectedColor.C + " != " + target.C); 16 | Assert.IsTrue(CloseEnough(expectedColor.M,target.M),"(M)" + expectedColor.M + " != " + target.M); 17 | Assert.IsTrue(CloseEnough(expectedColor.Y,target.Y),"(Y)" + expectedColor.Y + " != " + target.Y); 18 | } 19 | 20 | protected static void ExpectedValuesForKnownColor(IColorSpace knownColor, ICmyk expectedColor) 21 | { 22 | var target = knownColor.To(); 23 | 24 | Assert.IsTrue(CloseEnough(expectedColor.C,target.C),"(C)" + expectedColor.C + " != " + target.C); 25 | Assert.IsTrue(CloseEnough(expectedColor.M,target.M),"(M)" + expectedColor.M + " != " + target.M); 26 | Assert.IsTrue(CloseEnough(expectedColor.Y,target.Y),"(Y)" + expectedColor.Y + " != " + target.Y); 27 | Assert.IsTrue(CloseEnough(expectedColor.K,target.K),"(K)" + expectedColor.K + " != " + target.K); 28 | } 29 | 30 | protected static void ExpectedValuesForKnownColor(IColorSpace knownColor, IHsl expectedColor) 31 | { 32 | var target = knownColor.To(); 33 | 34 | Assert.IsTrue(CloseEnough(expectedColor.H,target.H),"(H)" + expectedColor.H + " != " + target.H); 35 | Assert.IsTrue(CloseEnough(expectedColor.S,target.S),"(S)" + expectedColor.S + " != " + target.S); 36 | Assert.IsTrue(CloseEnough(expectedColor.L,target.L),"(L)" + expectedColor.L + " != " + target.L); 37 | } 38 | 39 | protected static void ExpectedValuesForKnownColor(IColorSpace knownColor, ILab expectedColor) 40 | { 41 | var target = knownColor.To(); 42 | 43 | Assert.IsTrue(CloseEnough(expectedColor.L,target.L),"(L)" + expectedColor.L + " != " + target.L); 44 | Assert.IsTrue(CloseEnough(expectedColor.A,target.A),"(A)" + expectedColor.A + " != " + target.A); 45 | Assert.IsTrue(CloseEnough(expectedColor.B,target.B),"(B)" + expectedColor.B + " != " + target.B); 46 | } 47 | 48 | protected static void ExpectedValuesForKnownColor(IColorSpace knownColor, ILch expectedColor) 49 | { 50 | var target = knownColor.To(); 51 | 52 | Assert.IsTrue(CloseEnough(expectedColor.L,target.L),"(L)" + expectedColor.L + " != " + target.L); 53 | Assert.IsTrue(CloseEnough(expectedColor.C,target.C),"(C)" + expectedColor.C + " != " + target.C); 54 | Assert.IsTrue(CloseEnough(expectedColor.H,target.H),"(H)" + expectedColor.H + " != " + target.H); 55 | } 56 | 57 | protected static void ExpectedValuesForKnownColor(IColorSpace knownColor, IRgb expectedColor) 58 | { 59 | var target = knownColor.To(); 60 | 61 | Assert.IsTrue(CloseEnough(expectedColor.R,target.R),"(R)" + expectedColor.R + " != " + target.R); 62 | Assert.IsTrue(CloseEnough(expectedColor.G,target.G),"(G)" + expectedColor.G + " != " + target.G); 63 | Assert.IsTrue(CloseEnough(expectedColor.B,target.B),"(B)" + expectedColor.B + " != " + target.B); 64 | } 65 | 66 | protected static void ExpectedValuesForKnownColor(IColorSpace knownColor, IXyz expectedColor) 67 | { 68 | var target = knownColor.To(); 69 | 70 | Assert.IsTrue(CloseEnough(expectedColor.X,target.X),"(X)" + expectedColor.X + " != " + target.X); 71 | Assert.IsTrue(CloseEnough(expectedColor.Y,target.Y),"(Y)" + expectedColor.Y + " != " + target.Y); 72 | Assert.IsTrue(CloseEnough(expectedColor.Z,target.Z),"(Z)" + expectedColor.Z + " != " + target.Z); 73 | } 74 | 75 | protected static void ExpectedValuesForKnownColor(IColorSpace knownColor, IYxy expectedColor) 76 | { 77 | var target = knownColor.To(); 78 | 79 | Assert.IsTrue(CloseEnough(expectedColor.Y1,target.Y1),"(Y1)" + expectedColor.Y1 + " != " + target.Y1); 80 | Assert.IsTrue(CloseEnough(expectedColor.X,target.X),"(X)" + expectedColor.X + " != " + target.X); 81 | Assert.IsTrue(CloseEnough(expectedColor.Y2,target.Y2),"(Y2)" + expectedColor.Y2 + " != " + target.Y2); 82 | } 83 | private static bool CloseEnough(double a, double b) 84 | { 85 | // Define the tolerance for variation in their values 86 | var difference = Math.Abs(a * .01); 87 | 88 | // Compare the values 89 | // The output to the console indicates that the two values are equal 90 | return Math.Abs(a - b) <= difference; 91 | } 92 | 93 | } 94 | 95 | } -------------------------------------------------------------------------------- /ColorMine/ColorSpaces/ColorSpaces.cs: -------------------------------------------------------------------------------- 1 | //Note: This is a generated file. 2 | using ColorMine.ColorSpaces.Conversions; 3 | 4 | namespace ColorMine.ColorSpaces 5 | { 6 | public interface IRgb : IColorSpace 7 | { 8 | double R { get; set; } 9 | double G { get; set; } 10 | double B { get; set; } 11 | } 12 | 13 | public class Rgb : ColorSpace, IRgb 14 | { 15 | public double R { get; set; } 16 | public double G { get; set; } 17 | public double B { get; set; } 18 | 19 | public override void Initialize(IRgb color) 20 | { 21 | RgbConverter.ToColorSpace(color,this); 22 | } 23 | 24 | public override IRgb ToRgb() 25 | { 26 | return RgbConverter.ToColor(this); 27 | } 28 | } 29 | 30 | public interface IXyz : IColorSpace 31 | { 32 | double X { get; set; } 33 | double Y { get; set; } 34 | double Z { get; set; } 35 | } 36 | 37 | public class Xyz : ColorSpace, IXyz 38 | { 39 | public double X { get; set; } 40 | public double Y { get; set; } 41 | public double Z { get; set; } 42 | 43 | public override void Initialize(IRgb color) 44 | { 45 | XyzConverter.ToColorSpace(color,this); 46 | } 47 | 48 | public override IRgb ToRgb() 49 | { 50 | return XyzConverter.ToColor(this); 51 | } 52 | } 53 | 54 | public interface IHsl : IColorSpace 55 | { 56 | double H { get; set; } 57 | double S { get; set; } 58 | double L { get; set; } 59 | } 60 | 61 | public class Hsl : ColorSpace, IHsl 62 | { 63 | public double H { get; set; } 64 | public double S { get; set; } 65 | public double L { get; set; } 66 | 67 | public override void Initialize(IRgb color) 68 | { 69 | HslConverter.ToColorSpace(color,this); 70 | } 71 | 72 | public override IRgb ToRgb() 73 | { 74 | return HslConverter.ToColor(this); 75 | } 76 | } 77 | 78 | public interface ILab : IColorSpace 79 | { 80 | double L { get; set; } 81 | double A { get; set; } 82 | double B { get; set; } 83 | } 84 | 85 | public class Lab : ColorSpace, ILab 86 | { 87 | public double L { get; set; } 88 | public double A { get; set; } 89 | public double B { get; set; } 90 | 91 | public override void Initialize(IRgb color) 92 | { 93 | LabConverter.ToColorSpace(color,this); 94 | } 95 | 96 | public override IRgb ToRgb() 97 | { 98 | return LabConverter.ToColor(this); 99 | } 100 | } 101 | 102 | public interface ILch : IColorSpace 103 | { 104 | double L { get; set; } 105 | double C { get; set; } 106 | double H { get; set; } 107 | } 108 | 109 | public class Lch : ColorSpace, ILch 110 | { 111 | public double L { get; set; } 112 | public double C { get; set; } 113 | public double H { get; set; } 114 | 115 | public override void Initialize(IRgb color) 116 | { 117 | LchConverter.ToColorSpace(color,this); 118 | } 119 | 120 | public override IRgb ToRgb() 121 | { 122 | return LchConverter.ToColor(this); 123 | } 124 | } 125 | 126 | public interface IYxy : IColorSpace 127 | { 128 | double Y1 { get; set; } 129 | double X { get; set; } 130 | double Y2 { get; set; } 131 | } 132 | 133 | public class Yxy : ColorSpace, IYxy 134 | { 135 | public double Y1 { get; set; } 136 | public double X { get; set; } 137 | public double Y2 { get; set; } 138 | 139 | public override void Initialize(IRgb color) 140 | { 141 | YxyConverter.ToColorSpace(color,this); 142 | } 143 | 144 | public override IRgb ToRgb() 145 | { 146 | return YxyConverter.ToColor(this); 147 | } 148 | } 149 | 150 | public interface ICmy : IColorSpace 151 | { 152 | double C { get; set; } 153 | double M { get; set; } 154 | double Y { get; set; } 155 | } 156 | 157 | public class Cmy : ColorSpace, ICmy 158 | { 159 | public double C { get; set; } 160 | public double M { get; set; } 161 | public double Y { get; set; } 162 | 163 | public override void Initialize(IRgb color) 164 | { 165 | CmyConverter.ToColorSpace(color,this); 166 | } 167 | 168 | public override IRgb ToRgb() 169 | { 170 | return CmyConverter.ToColor(this); 171 | } 172 | } 173 | 174 | public interface ICmyk : IColorSpace 175 | { 176 | double C { get; set; } 177 | double M { get; set; } 178 | double Y { get; set; } 179 | double K { get; set; } 180 | } 181 | 182 | public class Cmyk : ColorSpace, ICmyk 183 | { 184 | public double C { get; set; } 185 | public double M { get; set; } 186 | public double Y { get; set; } 187 | public double K { get; set; } 188 | 189 | public override void Initialize(IRgb color) 190 | { 191 | CmykConverter.ToColorSpace(color,this); 192 | } 193 | 194 | public override IRgb ToRgb() 195 | { 196 | return CmykConverter.ToColor(this); 197 | } 198 | } 199 | 200 | } -------------------------------------------------------------------------------- /ColorMine.Test/ColorMine.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Debug 5 | AnyCPU 6 | {318DFB24-B947-4B07-AFDB-561A262EB424} 7 | Library 8 | Properties 9 | ColorMine.Test 10 | ColorMine.Test 11 | v4.5 12 | 512 13 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 14 | 10.0 15 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 16 | $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages 17 | False 18 | UnitTest 19 | 20 | 21 | true 22 | full 23 | false 24 | bin\Debug\ 25 | DEBUG;TRACE 26 | prompt 27 | 4 28 | 29 | 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | 37 | 38 | 39 | False 40 | Lib\Moq.dll 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | True 60 | True 61 | ColorSpaceTest.tt 62 | 63 | 64 | 65 | True 66 | True 67 | ConversionTests.tt 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | {ae7dc769-4a71-49ba-bdd7-281f3e70b02a} 79 | ColorMine 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | TextTemplatingFileGenerator 92 | ColorSpaceTest.cs 93 | 94 | 95 | TextTemplatingFileGenerator 96 | ConversionTests.cs 97 | 98 | 99 | 100 | 101 | 102 | 103 | False 104 | 105 | 106 | False 107 | 108 | 109 | False 110 | 111 | 112 | False 113 | 114 | 115 | 116 | 117 | 118 | 119 | 126 | -------------------------------------------------------------------------------- /ColorMine.Test/ColorSpaces/ConversionTests.cs: -------------------------------------------------------------------------------- 1 | //Note: This is a generated file. 2 | using ColorMine.ColorSpaces; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace ColorMine.Test.ColorSpaces 6 | { 7 | 8 | public class RgbTest 9 | { 10 | [TestClass] 11 | public class To : ColorSpaceTest 12 | { 13 | 14 | [TestMethod] 15 | public void WhiteRgbToCmy() 16 | { 17 | var knownColor = new Rgb { R = 255, G = 255, B = 255, }; 18 | var expectedColor = new Cmy { C = 0, M = 0, Y = 0, }; 19 | 20 | ExpectedValuesForKnownColor(knownColor,expectedColor); 21 | } 22 | 23 | [TestMethod] 24 | public void WhiteRgbToCmyk() 25 | { 26 | var knownColor = new Rgb { R = 255, G = 255, B = 255, }; 27 | var expectedColor = new Cmyk { C = 0, M = 0, Y = 0, K = 0, }; 28 | 29 | ExpectedValuesForKnownColor(knownColor,expectedColor); 30 | } 31 | 32 | [TestMethod] 33 | public void WhiteRgbToHsl() 34 | { 35 | var knownColor = new Rgb { R = 255, G = 255, B = 255, }; 36 | var expectedColor = new Hsl { H = 0, S = 0, L = 100, }; 37 | 38 | ExpectedValuesForKnownColor(knownColor,expectedColor); 39 | } 40 | 41 | [TestMethod] 42 | public void WhiteRgbToLab() 43 | { 44 | var knownColor = new Rgb { R = 255, G = 255, B = 255, }; 45 | var expectedColor = new Lab { L = 100, A = 0.00526, B = -.0104, }; 46 | 47 | ExpectedValuesForKnownColor(knownColor,expectedColor); 48 | } 49 | 50 | [TestMethod] 51 | public void WhiteRgbToLch() 52 | { 53 | var knownColor = new Rgb { R = 255, G = 255, B = 255, }; 54 | var expectedColor = new Lch { L = 100, C = .01166, H = 296.813, }; 55 | 56 | ExpectedValuesForKnownColor(knownColor,expectedColor); 57 | } 58 | 59 | [TestMethod] 60 | public void WhiteRgbToRgb() 61 | { 62 | var knownColor = new Rgb { R = 255, G = 255, B = 255, }; 63 | var expectedColor = new Rgb { R = 255, G = 255, B = 255, }; 64 | 65 | ExpectedValuesForKnownColor(knownColor,expectedColor); 66 | } 67 | 68 | [TestMethod] 69 | public void WhiteRgbToXyz() 70 | { 71 | var knownColor = new Rgb { R = 255, G = 255, B = 255, }; 72 | var expectedColor = new Xyz { X = 95.050, Y = 100, Z = 108.900, }; 73 | 74 | ExpectedValuesForKnownColor(knownColor,expectedColor); 75 | } 76 | 77 | [TestMethod] 78 | public void WhiteRgbToYxy() 79 | { 80 | var knownColor = new Rgb { R = 255, G = 255, B = 255, }; 81 | var expectedColor = new Yxy { Y1 = 100, X = .31272, Y2 = .32900, }; 82 | 83 | ExpectedValuesForKnownColor(knownColor,expectedColor); 84 | } 85 | 86 | [TestMethod] 87 | public void BlackRgbToCmy() 88 | { 89 | var knownColor = new Rgb { R = 0, G = 0, B = 0, }; 90 | var expectedColor = new Cmy { C = 1, M = 1, Y = 1, }; 91 | 92 | ExpectedValuesForKnownColor(knownColor,expectedColor); 93 | } 94 | 95 | [TestMethod] 96 | public void BlackRgbToCmyk() 97 | { 98 | var knownColor = new Rgb { R = 0, G = 0, B = 0, }; 99 | var expectedColor = new Cmyk { C = 0, M = 0, Y = 0, K = 1, }; 100 | 101 | ExpectedValuesForKnownColor(knownColor,expectedColor); 102 | } 103 | 104 | [TestMethod] 105 | public void BlackRgbToHsl() 106 | { 107 | var knownColor = new Rgb { R = 0, G = 0, B = 0, }; 108 | var expectedColor = new Hsl { H = 0, S = 0, L = 0, }; 109 | 110 | ExpectedValuesForKnownColor(knownColor,expectedColor); 111 | } 112 | 113 | [TestMethod] 114 | public void BlackRgbToLab() 115 | { 116 | var knownColor = new Rgb { R = 0, G = 0, B = 0, }; 117 | var expectedColor = new Lab { L = 0, A = 0, B = 0, }; 118 | 119 | ExpectedValuesForKnownColor(knownColor,expectedColor); 120 | } 121 | 122 | [TestMethod] 123 | public void BlackRgbToLch() 124 | { 125 | var knownColor = new Rgb { R = 0, G = 0, B = 0, }; 126 | var expectedColor = new Lch { L = 0, C = 0, H = 0, }; 127 | 128 | ExpectedValuesForKnownColor(knownColor,expectedColor); 129 | } 130 | 131 | [TestMethod] 132 | public void BlackRgbToRgb() 133 | { 134 | var knownColor = new Rgb { R = 0, G = 0, B = 0, }; 135 | var expectedColor = new Rgb { R = 0, G = 0, B = 0, }; 136 | 137 | ExpectedValuesForKnownColor(knownColor,expectedColor); 138 | } 139 | 140 | [TestMethod] 141 | public void BlackRgbToXyz() 142 | { 143 | var knownColor = new Rgb { R = 0, G = 0, B = 0, }; 144 | var expectedColor = new Xyz { X = 0, Y = 0, Z = 0, }; 145 | 146 | ExpectedValuesForKnownColor(knownColor,expectedColor); 147 | } 148 | 149 | [TestMethod] 150 | public void BlackRgbToYxy() 151 | { 152 | var knownColor = new Rgb { R = 0, G = 0, B = 0, }; 153 | var expectedColor = new Yxy { Y1 = 0, X = 0, Y2 = 0, }; 154 | 155 | ExpectedValuesForKnownColor(knownColor,expectedColor); 156 | } 157 | 158 | [TestMethod] 159 | public void GoldenrodRgbToCmy() 160 | { 161 | var knownColor = new Rgb { R = 218, G = 165, B = 32, }; 162 | var expectedColor = new Cmy { C = .14510, M = .35294, Y = .87451, }; 163 | 164 | ExpectedValuesForKnownColor(knownColor,expectedColor); 165 | } 166 | 167 | [TestMethod] 168 | public void GoldenrodRgbToCmyk() 169 | { 170 | var knownColor = new Rgb { R = 218, G = 165, B = 32, }; 171 | var expectedColor = new Cmyk { C = 0, M = .24312, Y = .85321, K = .14510, }; 172 | 173 | ExpectedValuesForKnownColor(knownColor,expectedColor); 174 | } 175 | 176 | [TestMethod] 177 | public void GoldenrodRgbToHsl() 178 | { 179 | var knownColor = new Rgb { R = 218, G = 165, B = 32, }; 180 | var expectedColor = new Hsl { H = 43, S = 74, L = 49, }; 181 | 182 | ExpectedValuesForKnownColor(knownColor,expectedColor); 183 | } 184 | 185 | [TestMethod] 186 | public void GoldenrodRgbToLab() 187 | { 188 | var knownColor = new Rgb { R = 218, G = 165, B = 32, }; 189 | var expectedColor = new Lab { L = 70.816, A = 8.525, B = 68.765, }; 190 | 191 | ExpectedValuesForKnownColor(knownColor,expectedColor); 192 | } 193 | 194 | [TestMethod] 195 | public void GoldenrodRgbToLch() 196 | { 197 | var knownColor = new Rgb { R = 218, G = 165, B = 32, }; 198 | var expectedColor = new Lch { L = 70.816, C = 69.291, H = 82.933, }; 199 | 200 | ExpectedValuesForKnownColor(knownColor,expectedColor); 201 | } 202 | 203 | [TestMethod] 204 | public void GoldenrodRgbToRgb() 205 | { 206 | var knownColor = new Rgb { R = 218, G = 165, B = 32, }; 207 | var expectedColor = new Rgb { R = 218, G = 165, B = 32, }; 208 | 209 | ExpectedValuesForKnownColor(knownColor,expectedColor); 210 | } 211 | 212 | [TestMethod] 213 | public void GoldenrodRgbToXyz() 214 | { 215 | var knownColor = new Rgb { R = 218, G = 165, B = 32, }; 216 | var expectedColor = new Xyz { X = 42.629, Y = 41.920, Z = 7.211, }; 217 | 218 | ExpectedValuesForKnownColor(knownColor,expectedColor); 219 | } 220 | 221 | [TestMethod] 222 | public void GoldenrodRgbToYxy() 223 | { 224 | var knownColor = new Rgb { R = 218, G = 165, B = 32, }; 225 | var expectedColor = new Yxy { Y1 = 41.920, X = .46457, Y2 = .45684, }; 226 | 227 | ExpectedValuesForKnownColor(knownColor,expectedColor); 228 | } 229 | 230 | } 231 | } 232 | public class CmyTest 233 | { 234 | [TestClass] 235 | public class To : ColorSpaceTest 236 | { 237 | 238 | [TestMethod] 239 | public void SteelBlueCmyToCmy() 240 | { 241 | var knownColor = new Cmy { C = .72549, M = .49020, Y = .29412, }; 242 | var expectedColor = new Cmy { C = .72549, M = .49020, Y = .29412, }; 243 | 244 | ExpectedValuesForKnownColor(knownColor,expectedColor); 245 | } 246 | 247 | [TestMethod] 248 | public void SteelBlueCmyToCmyk() 249 | { 250 | var knownColor = new Cmy { C = .72549, M = .49020, Y = .29412, }; 251 | var expectedColor = new Cmyk { C = .61111, M = .27778, Y = 0, K = .29412, }; 252 | 253 | ExpectedValuesForKnownColor(knownColor,expectedColor); 254 | } 255 | 256 | [TestMethod] 257 | public void SteelBlueCmyToHsl() 258 | { 259 | var knownColor = new Cmy { C = .72549, M = .49020, Y = .29412, }; 260 | var expectedColor = new Hsl { H = 207, S = 44, L = 49, }; 261 | 262 | ExpectedValuesForKnownColor(knownColor,expectedColor); 263 | } 264 | 265 | [TestMethod] 266 | public void SteelBlueCmyToLab() 267 | { 268 | var knownColor = new Cmy { C = .72549, M = .49020, Y = .29412, }; 269 | var expectedColor = new Lab { L = 52.467, A = -4.070, B = -32.198, }; 270 | 271 | ExpectedValuesForKnownColor(knownColor,expectedColor); 272 | } 273 | 274 | [TestMethod] 275 | public void SteelBlueCmyToLch() 276 | { 277 | var knownColor = new Cmy { C = .72549, M = .49020, Y = .29412, }; 278 | var expectedColor = new Lch { L = 52.467, C = 32.454, H = 262.796, }; 279 | 280 | ExpectedValuesForKnownColor(knownColor,expectedColor); 281 | } 282 | 283 | [TestMethod] 284 | public void SteelBlueCmyToRgb() 285 | { 286 | var knownColor = new Cmy { C = .72549, M = .49020, Y = .29412, }; 287 | var expectedColor = new Rgb { R = 70, G = 130, B = 180, }; 288 | 289 | ExpectedValuesForKnownColor(knownColor,expectedColor); 290 | } 291 | 292 | [TestMethod] 293 | public void SteelBlueCmyToXyz() 294 | { 295 | var knownColor = new Cmy { C = .72549, M = .49020, Y = .29412, }; 296 | var expectedColor = new Xyz { X = 18.746, Y = 20.562, Z = 46.161, }; 297 | 298 | ExpectedValuesForKnownColor(knownColor,expectedColor); 299 | } 300 | 301 | [TestMethod] 302 | public void SteelBlueCmyToYxy() 303 | { 304 | var knownColor = new Cmy { C = .72549, M = .49020, Y = .29412, }; 305 | var expectedColor = new Yxy { Y1 = 20.562, X = .21934, Y2 = .24058, }; 306 | 307 | ExpectedValuesForKnownColor(knownColor,expectedColor); 308 | } 309 | 310 | } 311 | } 312 | public class CmykTest 313 | { 314 | [TestClass] 315 | public class To : ColorSpaceTest 316 | { 317 | 318 | [TestMethod] 319 | public void DarkVioletCmykToCmy() 320 | { 321 | var knownColor = new Cmyk { C = .29858, M = 1, Y = 0, K = .17255, }; 322 | var expectedColor = new Cmy { C = .41961, M = 1, Y = .17255, }; 323 | 324 | ExpectedValuesForKnownColor(knownColor,expectedColor); 325 | } 326 | 327 | [TestMethod] 328 | public void DarkVioletCmykToCmyk() 329 | { 330 | var knownColor = new Cmyk { C = .29858, M = 1, Y = 0, K = .17255, }; 331 | var expectedColor = new Cmyk { C = .29858, M = 1, Y = 0, K = .17255, }; 332 | 333 | ExpectedValuesForKnownColor(knownColor,expectedColor); 334 | } 335 | 336 | [TestMethod] 337 | public void DarkVioletCmykToHsl() 338 | { 339 | var knownColor = new Cmyk { C = .29858, M = 1, Y = 0, K = .17255, }; 340 | var expectedColor = new Hsl { H = 282, S = 100, L = 41, }; 341 | 342 | ExpectedValuesForKnownColor(knownColor,expectedColor); 343 | } 344 | 345 | [TestMethod] 346 | public void DarkVioletCmykToLab() 347 | { 348 | var knownColor = new Cmyk { C = .29858, M = 1, Y = 0, K = .17255, }; 349 | var expectedColor = new Lab { L = 39.579, A = 76.336, B = -70.378, }; 350 | 351 | ExpectedValuesForKnownColor(knownColor,expectedColor); 352 | } 353 | 354 | [TestMethod] 355 | public void DarkVioletCmykToLch() 356 | { 357 | var knownColor = new Cmyk { C = .29858, M = 1, Y = 0, K = .17255, }; 358 | var expectedColor = new Lch { L = 39.579, C = 103.828, H = 317.325, }; 359 | 360 | ExpectedValuesForKnownColor(knownColor,expectedColor); 361 | } 362 | 363 | [TestMethod] 364 | public void DarkVioletCmykToRgb() 365 | { 366 | var knownColor = new Cmyk { C = .29858, M = 1, Y = 0, K = .17255, }; 367 | var expectedColor = new Rgb { R = 148, G = 0, B = 211, }; 368 | 369 | ExpectedValuesForKnownColor(knownColor,expectedColor); 370 | } 371 | 372 | [TestMethod] 373 | public void DarkVioletCmykToXyz() 374 | { 375 | var knownColor = new Cmyk { C = .29858, M = 1, Y = 0, K = .17255, }; 376 | var expectedColor = new Xyz { X = 23.970, Y = 10.999, Z = 62.487, }; 377 | 378 | ExpectedValuesForKnownColor(knownColor,expectedColor); 379 | } 380 | 381 | [TestMethod] 382 | public void DarkVioletCmykToYxy() 383 | { 384 | var knownColor = new Cmyk { C = .29858, M = 1, Y = 0, K = .17255, }; 385 | var expectedColor = new Yxy { Y1 = 10.99, X = .24596, Y2 = .11286, }; 386 | 387 | ExpectedValuesForKnownColor(knownColor,expectedColor); 388 | } 389 | 390 | } 391 | } 392 | public class HslTest 393 | { 394 | [TestClass] 395 | public class To : ColorSpaceTest 396 | { 397 | 398 | [TestMethod] 399 | public void AliceBlueHslToCmy() 400 | { 401 | var knownColor = new Hsl { H = 208, S = 100, L = 97, }; 402 | var expectedColor = new Cmy { C = .06, M = .028, Y = 0, }; 403 | 404 | ExpectedValuesForKnownColor(knownColor,expectedColor); 405 | } 406 | 407 | [TestMethod] 408 | public void AliceBlueHslToCmyk() 409 | { 410 | var knownColor = new Hsl { H = 208, S = 100, L = 97, }; 411 | var expectedColor = new Cmyk { C = .06, M = .028, Y = 0, K = 0, }; 412 | 413 | ExpectedValuesForKnownColor(knownColor,expectedColor); 414 | } 415 | 416 | [TestMethod] 417 | public void AliceBlueHslToHsl() 418 | { 419 | var knownColor = new Hsl { H = 208, S = 100, L = 97, }; 420 | var expectedColor = new Hsl { H = 208, S = 100, L = 97, }; 421 | 422 | ExpectedValuesForKnownColor(knownColor,expectedColor); 423 | } 424 | 425 | [TestMethod] 426 | public void AliceBlueHslToLab() 427 | { 428 | var knownColor = new Hsl { H = 208, S = 100, L = 97, }; 429 | var expectedColor = new Lab { L = 97.179, A = -1.3688, B = -4.358, }; 430 | 431 | ExpectedValuesForKnownColor(knownColor,expectedColor); 432 | } 433 | 434 | [TestMethod] 435 | public void AliceBlueHslToLch() 436 | { 437 | var knownColor = new Hsl { H = 208, S = 100, L = 97, }; 438 | var expectedColor = new Lch { L = 97.179, C = 4.5683, H = 252.551, }; 439 | 440 | ExpectedValuesForKnownColor(knownColor,expectedColor); 441 | } 442 | 443 | [TestMethod] 444 | public void AliceBlueHslToRgb() 445 | { 446 | var knownColor = new Hsl { H = 208, S = 100, L = 97, }; 447 | var expectedColor = new Rgb { R = 240, G = 248, B = 255, }; 448 | 449 | ExpectedValuesForKnownColor(knownColor,expectedColor); 450 | } 451 | 452 | [TestMethod] 453 | public void AliceBlueHslToXyz() 454 | { 455 | var knownColor = new Hsl { H = 208, S = 100, L = 97, }; 456 | var expectedColor = new Xyz { X = 87.553, Y = 92.880, Z = 107.921, }; 457 | 458 | ExpectedValuesForKnownColor(knownColor,expectedColor); 459 | } 460 | 461 | [TestMethod] 462 | public void AliceBlueHslToYxy() 463 | { 464 | var knownColor = new Hsl { H = 208, S = 100, L = 97, }; 465 | var expectedColor = new Yxy { Y1 = 92.880, X = .30363, Y2 = .32210, }; 466 | 467 | ExpectedValuesForKnownColor(knownColor,expectedColor); 468 | } 469 | 470 | } 471 | } 472 | public class LabTest 473 | { 474 | [TestClass] 475 | public class To : ColorSpaceTest 476 | { 477 | 478 | [TestMethod] 479 | public void RedLabToCmy() 480 | { 481 | var knownColor = new Lab { L = 53.233, A = 80.109, B = 67.220, }; 482 | var expectedColor = new Cmy { C = 0.0039, M = .99970, Y = 1, }; 483 | 484 | ExpectedValuesForKnownColor(knownColor,expectedColor); 485 | } 486 | 487 | [TestMethod] 488 | public void RedLabToCmyk() 489 | { 490 | var knownColor = new Lab { L = 53.233, A = 80.109, B = 67.220, }; 491 | var expectedColor = new Cmyk { C = 0.0039, M = .99970, Y = 1, K = 0, }; 492 | 493 | ExpectedValuesForKnownColor(knownColor,expectedColor); 494 | } 495 | 496 | [TestMethod] 497 | public void RedLabToHsl() 498 | { 499 | var knownColor = new Lab { L = 53.233, A = 80.109, B = 67.220, }; 500 | var expectedColor = new Hsl { H = 0, S = 100, L = 50, }; 501 | 502 | ExpectedValuesForKnownColor(knownColor,expectedColor); 503 | } 504 | 505 | [TestMethod] 506 | public void RedLabToLab() 507 | { 508 | var knownColor = new Lab { L = 53.233, A = 80.109, B = 67.220, }; 509 | var expectedColor = new Lab { L = 53.233, A = 80.109, B = 67.220, }; 510 | 511 | ExpectedValuesForKnownColor(knownColor,expectedColor); 512 | } 513 | 514 | [TestMethod] 515 | public void RedLabToLch() 516 | { 517 | var knownColor = new Lab { L = 53.233, A = 80.109, B = 67.220, }; 518 | var expectedColor = new Lch { L = 53.33, C = 104.575, H = 40, }; 519 | 520 | ExpectedValuesForKnownColor(knownColor,expectedColor); 521 | } 522 | 523 | [TestMethod] 524 | public void RedLabToRgb() 525 | { 526 | var knownColor = new Lab { L = 53.233, A = 80.109, B = 67.220, }; 527 | var expectedColor = new Rgb { R = 255, G = 0, B = 0, }; 528 | 529 | ExpectedValuesForKnownColor(knownColor,expectedColor); 530 | } 531 | 532 | [TestMethod] 533 | public void RedLabToXyz() 534 | { 535 | var knownColor = new Lab { L = 53.233, A = 80.109, B = 67.220, }; 536 | var expectedColor = new Xyz { X = 41.240, Y = 21.260, Z = 1.930, }; 537 | 538 | ExpectedValuesForKnownColor(knownColor,expectedColor); 539 | } 540 | 541 | [TestMethod] 542 | public void RedLabToYxy() 543 | { 544 | var knownColor = new Lab { L = 53.233, A = 80.109, B = 67.220, }; 545 | var expectedColor = new Yxy { Y1 = 21.260, X = 0.64007, Y2 = .32997, }; 546 | 547 | ExpectedValuesForKnownColor(knownColor,expectedColor); 548 | } 549 | 550 | } 551 | } 552 | public class LchTest 553 | { 554 | [TestClass] 555 | public class To : ColorSpaceTest 556 | { 557 | 558 | [TestMethod] 559 | public void MaroonLchToCmy() 560 | { 561 | var knownColor = new Lch { L = 24.829, C = 60.093, H = 38.180, }; 562 | var expectedColor = new Cmy { C = .5215, M = .99993, Y = 1, }; 563 | 564 | ExpectedValuesForKnownColor(knownColor,expectedColor); 565 | } 566 | 567 | [TestMethod] 568 | public void MaroonLchToCmyk() 569 | { 570 | var knownColor = new Lch { L = 24.829, C = 60.093, H = 38.180, }; 571 | var expectedColor = new Cmyk { C = 0, M = .984, Y = 1, K = .49804, }; 572 | 573 | ExpectedValuesForKnownColor(knownColor,expectedColor); 574 | } 575 | 576 | [TestMethod] 577 | public void MaroonLchToHsl() 578 | { 579 | var knownColor = new Lch { L = 24.829, C = 60.093, H = 38.180, }; 580 | var expectedColor = new Hsl { H = 0, S = 100, L = 50, }; 581 | 582 | ExpectedValuesForKnownColor(knownColor,expectedColor); 583 | } 584 | 585 | [TestMethod] 586 | public void MaroonLchToLab() 587 | { 588 | var knownColor = new Lch { L = 24.829, C = 60.093, H = 38.180, }; 589 | var expectedColor = new Lab { L = 25.531, A = 48.055, B = 38.059, }; 590 | 591 | ExpectedValuesForKnownColor(knownColor,expectedColor); 592 | } 593 | 594 | [TestMethod] 595 | public void MaroonLchToLch() 596 | { 597 | var knownColor = new Lch { L = 24.829, C = 60.093, H = 38.180, }; 598 | var expectedColor = new Lch { L = 24.829, C = 60.093, H = 38.180, }; 599 | 600 | ExpectedValuesForKnownColor(knownColor,expectedColor); 601 | } 602 | 603 | [TestMethod] 604 | public void MaroonLchToRgb() 605 | { 606 | var knownColor = new Lch { L = 24.829, C = 60.093, H = 38.180, }; 607 | var expectedColor = new Rgb { R = 125, G = 0.02, B = 0, }; 608 | 609 | ExpectedValuesForKnownColor(knownColor,expectedColor); 610 | } 611 | 612 | [TestMethod] 613 | public void MaroonLchToXyz() 614 | { 615 | var knownColor = new Lch { L = 24.829, C = 60.093, H = 38.180, }; 616 | var expectedColor = new Xyz { X = 8.902, Y = 4.589, Z = .417, }; 617 | 618 | ExpectedValuesForKnownColor(knownColor,expectedColor); 619 | } 620 | 621 | [TestMethod] 622 | public void MaroonLchToYxy() 623 | { 624 | var knownColor = new Lch { L = 24.829, C = 60.093, H = 38.180, }; 625 | var expectedColor = new Yxy { Y1 = 21.260, X = 0.64007, Y2 = .32997, }; 626 | 627 | ExpectedValuesForKnownColor(knownColor,expectedColor); 628 | } 629 | 630 | } 631 | } 632 | } --------------------------------------------------------------------------------