RGB到HSL和背部,计算题 [英] RGB to HSL and back, calculation problems

查看:142
本文介绍了RGB到HSL和背部,计算题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想RGB转换为HSL,我也想从HSL转换为RGB,
我写了一个类,但如果我这样做RGB-> HSL-> RGB尝试,如果它的工作原理我得到一个不同的值。

I'm trying to convert RGB to HSL and I also want to convert from HSL to RGB, I have written a class for it but if I do RGB->HSL->RGB to try if it works I get a different value.

示例情况:如果您通过做一个HSLColor对象 HSLColor MyTestConversion = HSLColor.FromRGB(Colors.Green);
然后执行颜色ExpectedGreenHere = MyTestConversion.ToRGB()你会得到不同的颜色比 Col​​ors.Green ,而这是原来的输入,所以出了问题。

Example case: if you create a HSLColor object by doing HSLColor MyTestConversion = HSLColor.FromRGB(Colors.Green); and then do Color ExpectedGreenHere = MyTestConversion.ToRGB() you get a different color than Colors.Green while it was the original input so something goes wrong..

这是code我使用的:

This is the 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;
    }
}

用于参考:
EasyRGB颜色数学

推荐答案

除了precision问题,我觉得你的实际的算法不正确。这应该是你FromRGB:

Besides the precision issues I think your actual algorithm is incorrect. This should be your 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 CAN实际上有时甚至是负,所以如果它只是增加360;

The next thing you need to understand is that we're taking integer RGB values from 0 to 255 and converting them to decimal values from 0 to 1. The HSL that we get back will thus need to be converted to the normal degree/percent/percent that you're used to. The H value returned should be from 0 to 6 so to convert it to degrees you just multiply by 60. H can actually be negative sometimes so if it is just add 360;

            //Convert to degrees
            H = H * 60f;
            if (H < 0) H += 360;

取值还需要乘以100,给你一个比例从0到100

S and L also need to be multiplied by 100 to give you a percentage from 0 to 100.

更新

这code应该让你从HSL为RGB。它假定HSL值仍处于十进制格式。另外,我用的双浮动,而不是在下面更好的precision的code。

This code should get you from HSL to RGB. It assumes that the HSL values are still in their decimal format. Also, I used double instead of float in the code below for 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;
    }

这篇关于RGB到HSL和背部,计算题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆