// Spludlow Software // Copyright © Samuel P. Ludlow 2020 All Rights Reserved // Distributed under the terms of the GNU General Public License version 3 // Distributed WITHOUT ANY WARRANTY; without implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE // https://www.spludlow.co.uk/LICENCE.TXT // The Spludlow logo is a registered trademark of Samuel P. Ludlow and may not be used without permission // v1.14 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Drawing; using System.Data; namespace Spludlow.Drawing { public class Colour { public static string Encode(Color colour) { return String.Format("{0:x8}", colour.ToArgb()); } public static Color Decode(string hexARGB) { int argb = Int32.Parse(hexARGB, System.Globalization.NumberStyles.AllowHexSpecifier); if (argb == 0) return Color.Empty; return Color.FromArgb(argb); } public static Color FromHSV(double hue, double saturation, double value) { int hi = Convert.ToInt32(Math.Floor(hue / 60)) % 6; double f = hue / 60 - Math.Floor(hue / 60); value = value * 255; int v = Convert.ToInt32(value); int p = Convert.ToInt32(value * (1 - saturation)); int q = Convert.ToInt32(value * (1 - f * saturation)); int t = Convert.ToInt32(value * (1 - (1 - f) * saturation)); if (hi == 0) return Color.FromArgb(255, v, t, p); else if (hi == 1) return Color.FromArgb(255, q, v, p); else if (hi == 2) return Color.FromArgb(255, p, v, t); else if (hi == 3) return Color.FromArgb(255, p, q, v); else if (hi == 4) return Color.FromArgb(255, t, p, v); else return Color.FromArgb(255, v, p, q); } // Note that the inputs and outputs, except for the angle in degrees, are in the range of 0 to 1.0. public class HSV { public double H; public double S; public double V; } public class RGB { public double R; public double G; public double B; } public static double[] ToHSV(Color colour) { int round = 3; // tested; 3 is fine, 2 will give about half right otherwise each RGB may be 1 out on the byte RGB rgb = new RGB(); rgb.R = colour.R / 255.0; rgb.G = colour.G / 255.0; rgb.B = colour.B / 255.0; HSV hsv = RGBtoHSV(rgb); hsv.H = Math.Round(hsv.H, 1); // 1 fine, 0 half right hsv.S = Math.Round(hsv.S, round); hsv.V = Math.Round(hsv.V, round); return new double[] { hsv.H, hsv.S, hsv.V }; } public static HSV RGBtoHSV(RGB input) //double red, double green, double blue) { HSV result = new HSV(); double min, max, delta; min = (input.R < input.G ? input.R : input.G); min = (min < input.B ? min : input.B); max = (input.R > input.G ? input.R : input.G); max = (max > input.B ? max : input.B); result.V = max; delta = max - min; if (delta < 0.00001) { result.S = 0; result.H = 0; return result; } if (max > 0.0) { result.S = (delta / max); } else { result.S = 0.0; result.H = 0; return result; } if (input.R >= max) result.H = (input.G - input.B) / delta; else if (input.G >= max) result.H = 2.0 + (input.B - input.R) / delta; else result.H = 4.0 + (input.R - input.G) / delta; result.H *= 60.0; if (result.H < 0.0) result.H += 360.0; return result; } public static Color[] Range(int count) { Color[] colours = new Color[count]; for (int index = 0; index < count; ++index) { double hue = ((360.0) / count) * index; colours[index] = FromHSV(hue, 1, 1); } return colours; } public static void Test(int iterations) { DataTable table = Spludlow.Data.TextTable.ReadText(new string[] { "Status ColourI RI GI BI H S V ColourO RO GO BO", "String String Int32 Int32 Int32 Double Double Double String Int32 Int32 Int32", }); List colours = new List(); colours.Add(0x000000); colours.Add(0x0000FF); colours.Add(0x00FF00); colours.Add(0x00FFFF); colours.Add(0xFF0000); colours.Add(0xFF00FF); colours.Add(0xFFFF00); colours.Add(0xFFFFFF); Random rand = new Random(); for (int count = 0; count < iterations; ++count) colours.Add(rand.Next(0x1000000)); foreach (int colourValue in colours) { uint uColourValue = (uint)0xFF000000 | (uint)colourValue; Color colour = Color.FromArgb((int)uColourValue); double[] hsv = ToHSV(colour); Color outColour = FromHSV(hsv[0], hsv[1], hsv[2]); string inHex = colour.ToArgb().ToString("X8"); string outHex = outColour.ToArgb().ToString("X8"); string status = ""; if (inHex != outHex) status = "BAD"; table.Rows.Add(status, inHex, colour.R, colour.G, colour.B, hsv[0], hsv[1], hsv[2], outHex, outColour.R, outColour.G, outColour.B); } Spludlow.Log.Report("Colours HSV Convert Test", table); } } }