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
Post a Comment