题
我正在尝试将RGB转换为HSL,并且我也想从HSL转换为RGB,我已经为其写了一堂课,但是如果我做RGB-> HSL-> RGB,请尝试如果工作起作用,我会得到不同的值。
示例案例: 如果您通过执行创建HSLColor对象 HSLColor MyTestConversion = HSLColor.FromRGB(Colors.Green);
然后做 Color ExpectedGreenHere = MyTestConversion.ToRGB()
你得到的颜色与 Colors.Green
虽然这是原始输入,所以出了点问题。
这是我正在使用的代码:
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;
}
}
使用的参考:EasyRGB颜色数学
解决方案
除了精确的问题,我认为您的实际算法是不正确的。这应该是您的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的百分比。
更新
此代码应该使您从HSL到RGB。它假设HSL值仍处于小数格式。另外,我使用Double而不是在下面的代码中浮动,以获得更好的精度。
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;
}
其他提示
常见的错误。你有
public static HSLColor FromRGB(Byte R, Byte G, Byte B) { float _R = (R / 255); float _G = (G / 255); float _B = (B / 255);
准确地告诉我,r的值可能导致_r不为0。(提示:只有一个)。
编辑:您在torgb()中遇到了相同的问题,有1/3。
我在您的代码中看到的问题如下:
float _R = (R / 255);
您基本上是在这里进行整数部门,因此您失去了很多精度。
尝试将其更改为:
float _R = (R / 255f);
(对于其他2行也是如此)。
另外,为了提高精度,最好使用double而不是浮动。
不隶属于 StackOverflow