简体   繁体   中英

HSL to RGB colorspace function that I've written not working properly

I have written an HSL to RGB function, based on a few tutorials I found online, and mostly based on a Lua library called Colors , however, it doesn't work properly. Could you help me get it up and running?

Here's the code:

float Hue2RGB(float m1, float m2, float hue)
    {
        if (hue < 0) { hue += 1; };
        if (hue > 1) { hue -= 1; };

        if (hue * 6 < 1)
        {
            return m1 + (m2 - m1) * hue * 6;
        }
        else if (hue * 2 < 1)
        {
            return m2;
        }
        else if (hue * 3 < 2)
        {
            return m1 + (m2 - m1) * (2 / 3 - hue) * 6;
        }
        else
            return m1;
    }

color_RGB HSL2RGB(color_HSL color)
    {
        color.H = color.H / 360;
        float m1, m2;
        if (color.L <= 0.5)
        {
            m2 = color.L * (color.S + 1);
        }
        else
        {
            m2 = color.L + color.S - color.L * color.S;
        }

        m1 = color.L * 2 - m2;

        color_RGB return_color;
        return_color.R = Hue2RGB(m1, m2, color.H + 1 / 3);
        return_color.G = Hue2RGB(m1, m2, color.H);
        return_color.B = Hue2RGB(m1, m2, color.H - 1 / 3);
        return_color.a = 1.0;

        return return_color;
    }

I have an RGB to HSL that works properly, so I use that to test this function. Here's the result that I see in my debugger:

{R=0.294117659 G=0.0980392247 B=0.125490203 ...}

Convert to HSL

{H=351.600006 S=0.499999970 L=0.196078449 }

Convert to RGB again:

{R=0.0980392098 G=0.0980392098 B=0.0980392098 ...}

I've been struggling with this problem for a few days now, and this website I hear helps people. Thank you.

PS: Here's my other function, RGB to HSL. I have tested it, many times, it works properly:

color_HSL RGB2HSL(color_RGB color)
    {
        float min = std::fmin(std::fmin(color.R, color.G), color.B);
        float max = std::fmax(std::fmax(color.R, color.G), color.B);

        float delta = max - min;

        float H = 0, S = 0, L = ((min + max) / 2);

        if (L > 0 && L < 0.5)
        {
            S = delta / (max + min);
        }
        if (L > 0.5 && L < 1)
        {
            S = delta / (2 - max - min);
        }

        if (delta > 0)
        {

            if (max == color.R && max != color.G) { H += (color.G - color.B) / delta; }
            if (max == color.G && max != color.B) { H += 2 + (color.B - color.R) / delta; }
            if (max == color.R && max != color.R) { H += 4 + (color.R - color.G) / delta; }

            H = H / 6;
        }

        if (H < 0) { H += 1; };
        if (H > 1) { H -= 1; };

        color_HSL return_color;
        return_color.H = H * 360;
        return_color.S = S;
        return_color.L = L;

        return return_color;
    }

In C++ (or C) the result of a division operator is not automatically an floating point value. I the divided and and the divisor both have an integral data type, then the result of the division is integral, too. At leas one side of the division has to be a floating point type, to gain a floating point result. See Arithmetic operators for a detailed information about the conversion rules of binary arithmetic operations.

1 , 2 and 3 are integer literal s, so the data type of this constants is an integral data type ( int ).

Altogether, while the result of 1 / 3 is 0 and the result of 2 / 3 is 0, the result of 1.0 / 3.0 is 0.333333 and the result of 2.0 / 3.0 is 0.666667 .

Note this rule does not just apply to the division i applies to any other arithmetic operation, too. But in case of eg subtraction, addition, multiplication it doesn't matter, because these operations generate (mathematically) integral results, when they are applied to (mathematically) integral values.

This means, that the following expressions does not do what you expect it to do:

m1 + (m2 - m1) * (2 / 3 - hue) * 6
color.H + 1 / 3

Because they are the same as:

m1 + (m2 - m1) * (0 - hue) * 6
color.H + 0

Change the integral constants to floating point constants, to solve your issue. The working functions may look like this:

float Hue2RGB(float m1, float m2, float hue)
{
    hue = hue < 0 ? hue+1 : hue > 1 ? hue-1 : hue;

    if (hue * 6 < 1)
        return m1 + (m2 - m1) * hue * 6;
    else if (hue * 2 < 1)
        return m2;
    else if (hue * 3 < 2)
        return m1 + (m2 - m1) * (2.0 / 3.0 - hue) * 6;
    else
        return m1;
}

color_RGB HSL2RGB(color_HSL color)
{
    color.H = color.H / 360;

    float m2 = color.L <= 0.5 ? color.L * (color.S + 1) : color.L + color.S - color.L * color.S;
    float m1 = color.L * 2 - m2;

    color_RGB return_color;
    return_color.R = Hue2RGB(m1, m2, color.H + 1.0 / 3.0);
    return_color.G = Hue2RGB(m1, m2, color.H);
    return_color.B = Hue2RGB(m1, m2, color.H - 1.0 / 3.0);
    return_color.a = 1.0;

    return return_color;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM