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);
}
}
}