using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; namespace ImageProcessing { public struct ColorRGB { public byte R; public byte G; public byte B; public ColorRGB(Color value) { this.R = value.R; this.G = value.G; this.B = value.B; } public static implicit operator Color(ColorRGB rgb) { Color c = Color.FromArgb(rgb.R, rgb.G, rgb.B); return c; } public static explicit operator ColorRGB(Color c) { return new ColorRGB(c); } } public struct ColorHSL { public double H; public double S; public double L; public ColorHSL(double h, double s, double l) { this.L = l; this.S = s; this.H = h; } } public class ColorTools { /// /// Given H,S,L, alph in range of 0-1 /// /// /// /// /// /// Returns a Color (RGB struct) in range of 0-255 public static Color HSL2RGB(double h, double s, double l, double alpha) { double v; double r, g, b; r = l; // default to gray g = l; b = l; v = (l <= 0.5) ? (l * (1.0 + s)) : (l + s - l * s); if (v > 0) { double m; double sv; int sextant; double fract, vsf, mid1, mid2; m = l + l - v; sv = (v - m) / v; h *= 6.0; sextant = (int)h; fract = h - sextant; vsf = v * sv * fract; mid1 = m + vsf; mid2 = v - vsf; switch (sextant) { case 0: r = v; g = mid1; b = m; break; case 1: r = mid2; g = v; b = m; break; case 2: r = m; g = v; b = mid1; break; case 3: r = m; g = mid2; b = v; break; case 4: r = mid1; g = m; b = v; break; case 5: r = v; g = m; b = mid2; break; case 6: r = v; g = mid1; b = m; break; } } Byte R = Convert.ToByte(r * 255.0f); Byte G = Convert.ToByte(g * 255.0f); Byte B = Convert.ToByte(b * 255.0f); Byte A = Convert.ToByte(alpha * 255.0f); return Color.FromArgb(A, R, G, B); } // Given a Color (RGB Struct) in range of 0-255 // Return H,S,L in range of 0-1 public static ColorHSL RGB2HSL(byte r, byte g, byte b) { ColorRGB rgb = new ColorRGB(); rgb.R = r; rgb.G = g; rgb.B = b; return ColorTools.RGB2HSL(rgb); } public static ColorHSL RGB2HSL(ColorRGB rgb) { double r = rgb.R / 255.0; double g = rgb.G / 255.0; double b = rgb.B / 255.0; double v; double m; double vm; double r2, g2, b2; double h = 0; // default to black double s = 0; double l = 0; v = Math.Max(r, g); v = Math.Max(v, b); m = Math.Min(r, g); m = Math.Min(m, b); l = (m + v) / 2.0; if (l <= 0.0) { return new ColorHSL(h, s, l); } vm = v - m; s = vm; if (s > 0.0) { s /= (l <= 0.5) ? (v + m) : (2.0 - v - m); } else { return new ColorHSL(h, s, l); } r2 = (v - r) / vm; g2 = (v - g) / vm; b2 = (v - b) / vm; if (r == v) { h = (g == m ? 5.0 + b2 : 1.0 - g2); } else if (g == v) { h = (b == m ? 1.0 + r2 : 3.0 - b2); } else { h = (r == m ? 3.0 + g2 : 5.0 - r2); } h /= 6.0; return new ColorHSL(h, s, l); } } }