我正在寻找一个算法之间的HSL颜色转换为RGB。

在我看来,HSL不是很广泛地使用,所以我没有太多的运气寻找一个转换器。


当前回答

Java版本:

/*
Converts color from HSL/A format to RGB/A format
0 <= h <= 360
0 <= s, l, a <= 1
Based on: https://en.wikipedia.org/wiki/HSL_and_HSV#:~:text=%5Bedit%5D-,HSL%20to%20RGB%5Bedit%5D,-Given%20a%20color
 */
public RGB toRGB(double h, double s, double l, Double a) {
    double c = (1 - Math.abs(2 * l - 1)) * s;
    double x = c * (1 - Math.abs((h / 60) % 2 - 1));
    double m = l - c / 2;
    int[] RGBTag = Arrays.stream(getRGBTag(c, x)).mapToInt(e -> (int)Math.round((e + m) * 255)).toArray();
    return RGB(RGBTag[0], RGBTag[1], RGBTag[2], a);

}

private double[] getRGBTag(double c, double x) {
    if (h < 60) {
        return new double[] {c, x, 0};
    } else if (h < 120) {
        return new double[] {x, c, 0};
    } else if (h < 180) {
        return new double[] {0, c, x};
    } else if (h < 240) {
        return new double[] {0, x, c};
    } else if (h < 300) {
        return new double[] {x, 0, c};
    }
    return new double[] {c, 0, x};
}

其他回答

Unity3D c#代码来自Mohsen的回答。

以下是Mohsen用c#编写的针对Unity3D的回答。它改编自上面Alec Thilenius给出的c#答案。

using UnityEngine;
using System.Collections;

public class ColorTools {

    /// <summary>
    /// Converts an HSL color value to RGB.
    /// Input: Vector4 ( X: [0.0, 1.0], Y: [0.0, 1.0], Z: [0.0, 1.0], W: [0.0, 1.0] )**strong text**
    /// Output: Color ( R: [0.0, 1.0], G: [0.0, 1.0], B: [0.0, 1.0], A: [0.0, 1.0] )
    /// </summary>
    /// <param name="hsl">Vector4 defining X = h, Y = s, Z = l, W = a. Ranges [0, 1.0]</param>
    /// <returns>RGBA Color. Ranges [0.0, 1.0]</returns>
    public static Color HslToRgba(Vector4 hsl)
    {
        float r, g, b;

        if (hsl.y == 0.0f)
            r = g = b = hsl.z;
        else
        {
            var q = hsl.z < 0.5f ? hsl.z * (1.0f + hsl.y) : hsl.z + hsl.y - hsl.z * hsl.y;
            var p = 2.0f * hsl.z - q;
            r = HueToRgb(p, q, hsl.x + 1.0f / 3.0f);
            g = HueToRgb(p, q, hsl.x);
            b = HueToRgb(p, q, hsl.x - 1.0f / 3.0f);
        }

        return new Color(r, g, b, hsl.w);
    }

    // Helper for HslToRgba
    private static float HueToRgb(float p, float q, float t)
    {
        if (t < 0.0f) t += 1.0f;
        if (t > 1.0f) t -= 1.0f;
        if (t < 1.0f / 6.0f) return p + (q - p) * 6.0f * t;
        if (t < 1.0f / 2.0f) return q;
        if (t < 2.0f / 3.0f) return p + (q - p) * (2.0f / 3.0f - t) * 6.0f;
        return p;
    }

    /// <summary>
    /// Converts an RGB color value to HSL.
    /// Input: Color ( R: [0.0, 1.0], G: [0.0, 1.0], B: [0.0, 1.0], A: [0.0, 1.0] )
    /// Output: Vector4 ( X: [0.0, 1.0], Y: [0.0, 1.0], Z: [0.0, 1.0], W: [0.0, 1.0] )
    /// </summary>
    /// <param name="rgba"></param>
    /// <returns></returns>
    public static Vector4 RgbaToHsl(Color rgba)
    {

        float max = (rgba.r > rgba.g && rgba.r > rgba.b) ? rgba.r : 
            (rgba.g > rgba.b) ? rgba.g : rgba.b;
        float min = (rgba.r < rgba.g && rgba.r < rgba.b) ? rgba.r : 
            (rgba.g < rgba.b) ? rgba.g : rgba.b;

        float h, s, l;
        h = s = l = (max + min) / 2.0f;

        if (max == min)
            h = s = 0.0f;
        else
        {
            float d = max - min;
            s = (l > 0.5f) ? d / (2.0f - max - min) : d / (max + min);

            if (rgba.r > rgba.g && rgba.r > rgba.b)
                h = (rgba.g - rgba.b) / d + (rgba.g < rgba.b ? 6.0f : 0.0f);

            else if (rgba.g > rgba.b)
                h = (rgba.b - rgba.r) / d + 2.0f;

            else
                h = (rgba.r - rgba.g) / d + 4.0f;

            h /= 6.0f;
        }

        return new Vector4(h, s, l, rgba.a);
    }

}

如果你正在寻找一些完全符合HSL和RGB的CSS语义的东西,你可以使用css3规范中指定的算法,它如下:

HOW TO RETURN hsl.to.rgb(h, s, l): 
   SELECT: 
      l<=0.5: PUT l*(s+1) IN m2
      ELSE: PUT l+s-l*s IN m2
   PUT l*2-m2 IN m1
   PUT hue.to.rgb(m1, m2, h+1/3) IN r
   PUT hue.to.rgb(m1, m2, h    ) IN g
   PUT hue.to.rgb(m1, m2, h-1/3) IN b
   RETURN (r, g, b)

HOW TO RETURN hue.to.rgb(m1, m2, h): 
   IF h<0: PUT h+1 IN h
   IF h>1: PUT h-1 IN h
   IF h*6<1: RETURN m1+(m2-m1)*h*6
   IF h*2<1: RETURN m2
   IF h*3<2: RETURN m1+(m2-m1)*(2/3-h)*6
   RETURN m1

我相信这是这里其他一些答案的来源。

对于所有说Garry Tan解决方案转换不正确从RGB到HSL和回来。这是因为他在代码中遗漏了数字的一部分。 我纠正了他的代码(javascript)。 对不起,俄语的链接,但在英语缺席- HSL-wiki

function toHsl(r, g, b)
{
    r /= 255.0;
    g /= 255.0;
    b /= 255.0;
    var max = Math.max(r, g, b);
    var min = Math.min(r, g, b);
    var h, s, l = (max + min) / 2.0;

    if(max == min)
    {
        h = s = 0; 
    }
    else
    {
        var d = max - min;
        s = (l > 0.5 ? d / (2.0 - max - min) : d / (max + min));

        if(max == r && g >= b)
        {
            h = 1.0472 * (g - b) / d ;
        }
        else if(max == r && g < b)
        {
            h = 1.0472 * (g - b) / d + 6.2832;
        }
        else if(max == g)
        {
            h = 1.0472 * (b - r) / d + 2.0944;
        }
        else if(max == b)
        {
            h = 1.0472 * (r - g) / d + 4.1888;
        }
    }
    return {
        str: 'hsl(' + parseInt(h / 6.2832 * 360.0 + 0.5) + ',' + parseInt(s * 100.0 + 0.5) + '%,' + parseInt(l * 100.0 + 0.5) + '%)',
        obj: { h: parseInt(h / 6.2832 * 360.0 + 0.5), s: parseInt(s * 100.0 + 0.5), l: parseInt(l * 100.0 + 0.5) }
    };
};

H, S, L在[0,1]范围内:

ConvertHslToRgb: function (iHsl)
{
    var min, sv, sextant, fract, vsf;

    var v = (iHsl.l <= 0.5) ? (iHsl.l * (1 + iHsl.s)) : (iHsl.l + iHsl.s - iHsl.l * iHsl.s);
    if (v === 0)
        return { Red: 0, Green: 0, Blue: 0 };

    min = 2 * iHsl.l - v;
    sv = (v - min) / v;
    var h = (6 * iHsl.h) % 6;
    sextant = Math.floor(h);
    fract = h - sextant;
    vsf = v * sv * fract;

    switch (sextant)
    {
        case 0: return { r: v, g: min + vsf, b: min };
        case 1: return { r: v - vsf, g: v, b: min };
        case 2: return { r: min, g: v, b: min + vsf };
        case 3: return { r: min, g: v - vsf, b: v };
        case 4: return { r: min + vsf, g: min, b: v };
        case 5: return { r: v, g: min, b: v - vsf };
    }
}

维基百科上关于HSL和HSV的文章包含了一些公式。计算有点棘手,所以看一下现有的实现可能会有用。