Ответ 1
Помимо проблем точности, я думаю, что ваш фактический алгоритм неверен. Это должно быть ваше 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);
}
Следующее, что вам нужно понять, это то, что мы берем целочисленные значения RGB от 0 до 255 и преобразуем их в десятичные значения от 0 до 1. Таким образом, HSL, который мы получаем, должен быть преобразован в нормальную степень/процентов/процентов, к которым вы привыкли. Возвращаемое значение H
должно быть от 0 до 6, чтобы преобразовать его в градусы, которые вы просто умножаете на 60. H
может быть иногда отрицательным, поэтому, если он просто добавляет 360;
//Convert to degrees
H = H * 60f;
if (H < 0) H += 360;
S
и L
также необходимо умножить на 100, чтобы дать вам процент от 0 до 100.
UPDATE
Этот код должен получить вас от HSL до RGB. Предполагается, что значения HSL все еще находятся в десятичном формате. Кроме того, я использовал double вместо float в коде ниже для лучшей точности.
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;
}