RGB to HSL / HSL to RGB in C#

This seems to be something difficult to find, but extremely useful for creating colour schemes that look nice.  I needed to create my own colour class for persistent storage reasons.  The technique below works just as easily by replacing the ColorRGB references with a simple ::System.Drawing.Color.  My Color class provides operators to convert to and from System.Drawing.Color

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

}

}

This function will take an HSL value in the ranges of 0-1 and return a color object.  I use this function all the time.

// Given H,S,L in range of 0-1

// Returns a Color (RGB struct) in range of 0-255

public static ColorRGB HSL2RGB(double h, double sl, double l)

{

double v;

double r,g,b;

r = l;   // default to gray

g = l;

b = l;

v = (l <= 0.5) ? (l * (1.0 + sl)) : (l + sl - l * sl);

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;

}

}

ColorRGB rgb;

rgb.R = Convert.ToByte(r * 255.0f);

rgb.G = Convert.ToByte(g * 255.0f);

rgb.B = Convert.ToByte(b * 255.0f);

return rgb;

}

To be honest – I haven’t yet needed to convert an RGB into an HSL, but if I did – this is what I would do

// Given a Color (RGB Struct) in range of 0-255

// Return H,S,L in range of 0-1

public static void      RGB2HSL (ColorRGB rgb, out double h, out double s, out double l)

{

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;

h = 0; // default to black

s = 0;

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;

}

vm = v - m;

s = vm;

if (s > 0.0)

{

s /= (l <= 0.5) ? (v + m ) : (2.0 - v - m) ;

}

else

{

return;

}

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;

}

Any comments or suggestions should be sent to ProgrammingTips@GeekyMonkey.com