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

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


当前回答

由于circuitpython不支持colorsys(或目前移植到),如果你试图在树莓派上处理这个转换,下面的工作(受制于本线程其他地方提到的舍入精度限制):

def hslToRgb (h, s, l): #in range 0-1 for h,s,l
    if s == 0:
        r = g = b = l #achromatic
    else:
        def hue2rgb(p, q, t):
            if t < 0: t += 1
            if t > 1: t -= 1
            if t < 1.0 / 6.0: return p + (q - p) * 6 * t
            if t < 1.0 / 2.0: return q
            if t < 2.0 / 3.0: return p + (q - p) * ((2.0 / 3.0) - t) * 6
            return p
        if l < 0.5:
            q = l * (1 + s)
        else:
            q = l + s - l * s
        p = 2 * l - q
        r = hue2rgb(p, q, h + 1.0/3.0)
        g = hue2rgb(p, q, h)
        b = hue2rgb(p, q, h - 1.0/3.0)
    return [round(r * 255), round(g * 255), round(b * 255)]

其他回答

我从Brandon Mathis的HSL Picker源代码中得到了这个。

它最初是用CoffeeScript编写的。我使用在线转换器将其转换为JavaScript,并拿出验证用户输入是否为有效RGB值的机制。这个答案适用于我的用例,因为我发现这篇文章上投票最多的答案不能产生有效的HSL值。

注意,它返回一个hsla值,表示不透明/透明。0是完全透明的,1是完全不透明的。

function rgbToHsl(rgb) {
  var a, add, b, diff, g, h, hue, l, lum, max, min, r, s, sat;
  r = parseFloat(rgb[0]) / 255;
  g = parseFloat(rgb[1]) / 255;
  b = parseFloat(rgb[2]) / 255;
  max = Math.max(r, g, b);
  min = Math.min(r, g, b);
  diff = max - min;
  add = max + min;
  hue = min === max ? 0 : r === max ? ((60 * (g - b) / diff) + 360) % 360 : g === max ? (60 * (b - r) / diff) + 120 : (60 * (r - g) / diff) + 240;
  lum = 0.5 * add;
  sat = lum === 0 ? 0 : lum === 1 ? 1 : lum <= 0.5 ? diff / add : diff / (2 - add);
  h = Math.round(hue);
  s = Math.round(sat * 100);
  l = Math.round(lum * 100);
  a = parseFloat(rgb[3]) || 1;
  return [h, s, l, a];
}

PHP -简短但精确

在这里,我将我的JS答案(数学细节在那里)重写为PHP -你可以在这里运行它

function hsl2rgb($h,$s,$l) 
{
  $a = $s * min($l, 1-$l);
  $k = function($n,$h) { return ($n+$h/30)%12;};
  $f = function($n) use ($h,$s,$l,$a,$k) { 
      return $l - $a * max( min($k($n,$h)-3, 9-$k($n,$h), 1),-1);
  };
  return [ $f(0), $f(8), $f(4) ];
}   

我需要一个非常轻的重量,它不是100%,但它足够接近一些用例。

float3 Hue(float h, float s, float l)
{
    float r = max(cos(h * 2 * UNITY_PI) * 0.5 + 0.5, 0);
    float g = max(cos((h + 0.666666) * 2 * UNITY_PI) * 0.5 + 0.5, 0);
    float b = max(cos((h + 0.333333) * 2 * UNITY_PI) * 0.5 + 0.5, 0);
    float gray = 0.2989 * r + 0.5870 * g + 0.1140 * b;
    return lerp(gray, float3(r, g, b), s) * smoothstep(0, 0.5, l) + 1 * smoothstep(0.5, 1, l);
}

下面是GLSL中快速、超级简单、无分支的版本:

vec3 hsl2rgb( vec3 c ) {
    vec3 rgb = clamp(abs(mod(c.x*6.0 + vec3(0.0, 4.0, 2.0), 6.0)-3.0)-1.0, 0.0, 1.0);
    return c.z + c.y * (rgb-0.5)*(1.0-abs(2.0*c.z-1.0));
}

没有比这更短的了~


原始概念验证的链接:https://www.shadertoy.com/view/XljGzV

(免责声明:不是我的代码!)

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