c# - RGB to HSL and back, calculation problems -


i'm trying convert rgb hsl , want convert hsl rgb, have written class if rgb->hsl->rgb try if works different value.

example case: if create hslcolor object doing hslcolor mytestconversion = hslcolor.fromrgb(colors.green); , color expectedgreenhere = mytestconversion.torgb() different color colors.green while original input goes wrong..

this code i'm using:

public class hslcolor {     public float hue;     public float saturation;     public float luminosity;      public hslcolor(float h, float s, float l)     {         hue = h;         saturation = s;         luminosity = l;     }      public static hslcolor fromrgb(color clr)     {         return fromrgb(clr.r, clr.g, clr.b);     }      public static hslcolor fromrgb(byte r, byte g, byte b)     {         float _r = (r / 255f);         float _g = (g / 255f);         float _b = (b / 255f);          float _min = math.min(math.min(_r, _g), _b);         float _max = math.max(math.max(_r, _g), _b);         float _delta = _max - _min;          float h = 0;         float s = 0;         float l = (float)((_max + _min) / 2.0f);          if (_delta != 0)         {             if (l < 0.5f)             {                 s = (float)(_delta / (_max + _min));             }             else             {                 s = (float)(_delta / (2.0f - _max - _min));             }              float _delta_r = (float)(((_max - _r) / 6.0f + (_delta / 2.0f)) / _delta);             float _delta_g = (float)(((_max - _g) / 6.0f + (_delta / 2.0f)) / _delta);             float _delta_b = (float)(((_max - _b) / 6.0f + (_delta / 2.0f)) / _delta);              if (_r == _max)             {                 h = _delta_b - _delta_g;             }             else if (_g == _max)             {                 h = (1.0f / 3.0f) + _delta_r - _delta_b;             }             else if (_b == _max)             {                 h = (2.0f / 3.0f) + _delta_g - _delta_r;             }              if (h < 0) h += 1.0f;             if (h > 1) h -= 1.0f;         }          return new hslcolor(h, s, l);     }      private float hue_2_rgb(float v1, float v2, float vh)     {         if (vh < 0) vh += 1;         if (vh > 1) vh -= 1;         if ((6 * vh) < 1) return (v1 + (v2 - v1) * 6 * vh);         if ((2 * vh) < 1) return (v2);         if ((3 * vh) < 2) return (v1 + (v2 - v1) * ((2 / 3) - vh) * 6);         return (v1);     }      public color torgb()     {         color clr = new color();         float var_1, var_2;          if (saturation == 0)         {             clr.r = (byte)(luminosity * 255);             clr.g = (byte)(luminosity * 255);             clr.b = (byte)(luminosity * 255);         }         else         {             if (luminosity < 0.5) var_2 = luminosity * (1 + saturation);             else var_2 = (luminosity + saturation) - (saturation * luminosity);              var_1 = 2 * luminosity - var_2;              clr.r = (byte)(255 * hue_2_rgb(var_1, var_2, hue + (1 / 3)));             clr.g = (byte)(255 * hue_2_rgb(var_1, var_2, hue));             clr.b = (byte)(255 * hue_2_rgb(var_1, var_2, hue - (1 / 3)));         }          return clr;     } } 

used reference: easyrgb color math

besides precision issues think actual algorithm incorrect. should fromrgb:

    public static hslcolor fromrgb(byte r, byte g, byte b)     {         float _r = (r / 255f);         float _g = (g / 255f);         float _b = (b / 255f);          float _min = math.min(math.min(_r, _g), _b);         float _max = math.max(math.max(_r, _g), _b);         float _delta = _max - _min;          float h = 0;         float s = 0;         float l = (float)((_max + _min) / 2.0f);          if (_delta != 0)         {             if (l < 0.5f)             {                 s = (float)(_delta / (_max + _min));             }             else             {                 s = (float)(_delta / (2.0f - _max - _min));             }               if (_r == _max)             {                 h = (_g - _b) / _delta;             }             else if (_g == _max)             {                 h = 2f + (_b - _r) / _delta;             }             else if (_b == _max)             {                 h = 4f + (_r - _g) / _delta;             }         }          return new hslcolor(h, s, l);     } 

the next thing need understand we're taking integer rgb values 0 255 , converting them decimal values 0 1. hsl need converted normal degree/percent/percent you're used to. h value returned should 0 6 convert degrees multiply 60. h can negative if add 360;

            //convert degrees             h = h * 60f;             if (h < 0) h += 360; 

s , l need multiplied 100 give percentage 0 100.

update

this code should hsl rgb. assumes hsl values still in decimal format. also, used double instead of float in code below better precision.

    public color torgb()     {         byte r, g, b;         if (saturation == 0)         {             r = (byte)math.round(luminosity * 255d);             g = (byte)math.round(luminosity * 255d);             b = (byte)math.round(luminosity * 255d);         }         else         {             double t1, t2;             double th = hue / 6.0d;              if (luminosity < 0.5d)             {                 t2 = luminosity * (1d + saturation);             }             else             {                 t2 = (luminosity + saturation) - (luminosity * saturation);             }             t1 = 2d * luminosity - t2;              double tr, tg, tb;             tr = th + (1.0d / 3.0d);             tg = th;             tb = th - (1.0d / 3.0d);              tr = colorcalc(tr, t1, t2);             tg = colorcalc(tg, t1, t2);             tb = colorcalc(tb, t1, t2);             r = (byte)math.round(tr * 255d);             g = (byte)math.round(tg * 255d);             b = (byte)math.round(tb * 255d);         }         return color.fromargb(r, g, b);     }     private static double colorcalc(double c, double t1, double t2)     {          if (c < 0) c += 1d;         if (c > 1) c -= 1d;         if (6.0d * c < 1.0d) return t1 + (t2 - t1) * 6.0d * c;         if (2.0d * c < 1.0d) return t2;         if (3.0d * c < 2.0d) return t1 + (t2 - t1) * (2.0d / 3.0d - c) * 6.0d;         return t1;     } 

Comments

Popular posts from this blog

java - SNMP4J General Variable Binding Error -

windows - Python Service Installation - "Could not find PythonClass entry" -

Determine if a XmlNode is empty or null in C#? -