HSL到RGB值


17

RGB(红色绿色蓝色)颜色模型的主要目的是用于感测,表示和显示电子系统(例如电视和计算机)中的图像

HSL(色相饱和度亮度)是一种替代颜色模型,由计算机图形学研究人员在1970年代设计,可以更紧密地与人类视觉感知色彩属性的方式保持一致。

这是RGBHSL的Wiki文章。图形程序通常在HSL中进行计算,然后转换为大多数屏幕的首选格式:RGB。

任务是编写一个将HSL作为输入并输出RGB的函数/程序。

您可以选择I / O的首选表示形式,只要它们之间是一致的即可。

例如,它们可以是具有3个元素的数组/元组,也可以是具有3个名为hs和的属性的对象l,但是我将接受其他巧妙的变化,例如将hsl作为整数接收(丢失精度)并输出rgb整数。

可以认为输入的范围和格式是安全的,您都可以决定两者。我强烈建议该范围,0-1 0-1 0-1或者0-360 0-100 0-100对于hsl,0-1 0-1 0-1或者0-255 0-255 0-255对于rgb。

每个答案都必须同时指定以上两者,并且如果您对它们特别满意,请在答案中放入各种变化形式,即使它们的字符数少于其他变体形式也是如此。将最小的放在上面。

伪测试用例0-360 0-100 0-1000-255 0-255 0-255

h   s   l   → r   g   b

0   0   0   → 0   0   0
90  56  17  → 43  68  19
202 19  39  → 81  104 118
72  55  26  → 88  103 30

转换公式可以在这里找到:

这是可视化转换的一种好方法:


您的建议范围内H0-360[0,360),它会更好写成0-359
乔纳森·艾伦,

3
@JonathanAllan我认为对于我来说,这似乎更令人困惑,这表明395.1不是可能的输入。如果有的话,a-b在处理非整数值时,使用表示法本身是错误的,但是我想让问题更具可读性是可以的。如果有人抱怨,我会重新考虑,因此感谢您指出
towc

是的,在359.1点上达成了共识-也许只是使用当时的标准符号即可[0,360):)
Jonathan Allan

惊讶地看到没有glsl答案;)
towc

Answers:


8

JavaScript(ES6),98 95 94字节

注意到ħ[0360)小号 / 大号[0,1) 。输出RGB[0,1)中3个浮点的数组。

(H,S,L)=>[5,3,1].map(i=>A(L*2)*S*([1,Y,0,0,Y,1][(i-~H)%6]-.5)+L,Y=(A=n=>n>1?2-n:n)((H/=60)%2))

测试用例

此摘要将结果转换回[0,255]

怎么样?

初始化代码

Y = (                  // we compute Y = 1 - |(H/60) mod 2 - 1| = X / C
  A = n =>             // A = function that returns 1 - |n - 1|
    n > 1 ?            //   first compare n with 1
      2 - n            //     which allows to simplify the formula to either 2 - n
    :                  //   or
      n                //     just n
)((H /= 60) % 2)       // divide H by 60 and compute Y = A(H % 2)

主要代号

[5, 3, 1].map(i =>     // for each i in (5, 3, 1):
  A(L * 2) * S * (     //   compute (1 - |2L - 1|) * S (this is C), and multiply it by:
    [1, Y, 0, 0, Y, 1] //     either 0, 1 or Y (let's call this factor K), picked from
    [(i - ~H) % 6]     //     a cyclic sequence of period 6, using i and ~H (-6 ≤ ~H ≤ -1)
    - .5               //     minus 1/2
  )                    //   this gives: C(K - 1/2) = CK - C/2, where CK = 0, C or X
  + L                  //   we add L, leading to CK - C/2 + L = CK + m
)                      // end of map() --> returns [R, G, B]

(0,C,X)的排列

稍微棘手的部分是根据色相分量的角度生成(0,C,X)的正确排列。如下图所示,每个列值都是从周期6的相同循环序列中选取的,起始于不同的偏移量。在上面的代码中,我们使用-〜H而不是+ H,因为我们需要将H强制为整数。因此,偏移量是(5,3,1)而不是(0,4,2)

                       C,X,0,0,X,C,C,X,0,0,X,C, ...
 +------> C,X,0,0,X,C  <--------->                  offset = 0, (0 - 1) mod 6 = 5
 | +----> X,C,C,X,0,0          <--------->          offset = 4, (4 - 1) mod 6 = 3
 | | +--> 0,0,X,C,C,X      <--------->              offset = 2, (2 - 1) mod 6 = 1
 | | |
(C,X,0) for   0 ≤ H <  60
(X,C,0) for  60 ≤ H < 120
(0,C,X) for 120 ≤ H < 180
(0,X,C) for 180 ≤ H < 240
(X,0,C) for 240 ≤ H < 300
(C,0,X) for 300 ≤ H < 360

将采取H[0,6)和输出[0,1]节省一些字节?
乔纳森·艾伦,

@JonathanAllan啊,我没有注意到I / O格式松散。谢谢!
Arnauld

4

Mathematica,155个字节

(x~Clear~c;d=Piecewise@Table[{(P=Permutations)[P@{c,x,0}][[42,i]],(i-1)<=#<i*p},{i,6}];c=(1-Abs[2#3-1])#2;x=c(1-Abs[Mod[#/(p=60),2]-1]);m=#3-c/2;(m+d)255)&


在线尝试!



1
@totallyhuman我认为这与HueHSB(AKA HSV)而非HSL是不对的(请参见链接的Wikipedia页面上的图2a和2b)。
乔纳森·艾伦

1
珍妮-如果正确的话,没有理由不将其作为字节数发布到下面的非内置文件中!
乔纳森·艾伦

1
@JonathanAllan哦,是的。它的RGBColor存在有点烦人,但HSLColor不存在。> _>
totallyhuman 2015年

有没有这个版本的版本?
user76284

4

Python 2,32字节

from colorsys import*;hls_to_rgb

在线尝试!

实际上,此功能是通过库hls_to_rgb内部内置在Python 中的colorsys。我的输入格式是HLS的0-1范围(而不是HSL,两者都是同一事物的通用首字母缩写[尽管HSL更常见])。我的输出在一个元组中输出RGB值,范围从0到1。

学分

感谢Jonathan Allan指出我只需要导入它(然后进一步帮助我减少字节数)。


我认为这只能是31个字节,from colorsys import hls_to_rgb因为这给了我们可以重用的功能。编辑-将该21设置为from colorsys import*
乔纳森·艾伦,

1
@JonathanAllan谢谢,更新了。
尼尔,

实际上可能只import colorsys需要15个!
乔纳森·艾伦,

@JonathanAllan Nice,再次更新。
尼尔,

1
但是可能确实如此,我认为这会影响代码高尔夫的精神:/
towc

4

C ++,228221字节

-7个字节,感谢Zacharý

#define S(o,n)r[t[int(h[0])/60*3+o]+o-2]=(n+h[2]-c/2)*255;
void C(float*h,int*r){float g=2*h[2]-1,c=(g<0?1+g:1-g)*h[1],a=int(h[0])%120/60.f-1;int t[]={2,2,2,3,1,2,3,3,0,4,2,0,4,1,1,2,3,1};S(0,c)S(1,c*(a<0?1+a:1-a))S(2,0)}

这两个参数都是两个数组,其最小大小为3个元素(即float hsl[3]int rgb[3]

好的。现在,如何运作?那长数组是什么?

好吧,这不是一个长数组,而是一个int数组。除了开玩笑,该数组指示当我们要选择正确的排列+ 2时,我们将CX和0右移了多少个位置。还记得如何选择R',G'和B'吗?

如何选择R',G'和B'

假设我们有一个{C,X,0}的“正常”订单

现在,当选择第一个排列(即{C,X,0})时,您无需移动,这与右移0完全相同。因此,数组的前3个元素为0,0和0

对于第二个排列({X,C,0}),我们需要将C右移1,将X左移-1,因此数组的第四,第五和第六个元素分别是1,-1和0

等等...

对于第3和第4个置换,我需要将0左移2,所以将右移-2。由于有2个以上的负数,所以我宁愿在数组中的每个元素上加2并在运行时减去2(出于打高尔夫球的原因,数组中只有整数)。


221个字节:pastebin.com/C8WaSSpb
扎卡里

4

Python 2中119个 112字节

def f(h,s,l):c=(1-abs(2*l-1))*s;m=l-c/2;x=c*(1-abs(h%2-1))+m;c+=m;return[c,m,x,c,m,x,m,c,x,m][7-int(h)*5%9:][:3]

在线尝试!

输入为 H=[0,6[, S=[0,1], L=[0,1]


3

HTML + JavaScript(ES6),8 + 88 = 96字节

f=
(h,s,l)=>(p.style.color=`hsl(${h},${s}%,${l}%)`,getComputedStyle(p).color.match(/\d+/g))
<div oninput=o.textContent=f(h.value,s.value,l.value)>H: <input type=number min=0 max=360 value=0 id=h>°<br>S: <input type=number min=0 max=100 value=0 id=s>%<br>L: <input type=number min=0 max=100 value=0 id=l>%<pre id=o>0,0,0</pre>
<p id=p>

将输入作为角度和两个百分比。我正在为HTML代码段<p id=p>和JavaScript箭头函数评分。我不知道舍入浏览器使用什么,因此我的答案可能与您的答案略有不同。


2

斯威夫特4,218字节

接受[0,1]范围内的HSL值作为参数,并返回包含相同范围内RGB值的数组:

import Cocoa;typealias F=CGFloat;func f(h:F,s:F,l:F)->[F]{var r=F(),g=F(),b=F(),x=s*min(1-l,l),n=2*x/max(l+x,1e-9);NSColor(hue:h,saturation:n,brightness:l+x,alpha:1).getRed(&r,green:&g,blue:&b,alpha:nil);return[r,g,b]}

这个想法是首先将输入从HSL转换为HSB,然后使用Cocoa中内置颜色对象的HSB构造函数检索RGB值。

UIKit版本的长度完全相同,唯一的替代是:

  • CocoaUIKit
  • NSColorUIColor

取消高尔夫:

#if os(iOS)
    import UIKit
    typealias Color = UIColor
#elseif os(OSX)
    import Cocoa
    typealias Color = NSColor
#endif

typealias F = CGFloat

func f(h: F,s: F,l: F) -> [F] {
    var r = F(), g = F(), b = F()

    let x = s * min(1 - l, l)
    let n = 2 * x / max(l + x, 1e-9)

    let color = Color(hue: h, saturation: n, brightness: l + x, alpha: 1)
    color.getRed(&r, green: &g,blue: &b, alpha: nil)

    return [r, g, b]
}

下面的代码段可以被用于测试,通过只更换的值hs以及l

let h: CGFloat = 0
let s: CGFloat = 0
let l: CGFloat = 0

let result = f(h: h/360, s: s/100, l: l/100).map { Int(round($0*255)) }
print(result)

不幸的是,由于它们都运行在不包含Cocoa的Linux上,因此我无法提供到在线沙箱的链接。


2

GLSL(GL_ES) 160144134 131字节

色相在0-6的范围内(节省3个字节)
饱和度,亮度和RGB为0-1

vec3 f(vec3 c){return mix(c.bbb,mix(clamp(vec3(-1,2,2)-abs(c.r-vec3(3,2,4))*vec3(-1,1,1),0.,1.),vec3(c.b>.5),abs(.5-c.b)*2.),c.g);}

在着色器书上尝试

在打印屏幕上使用了颜色选择器工具来测试输出是否正确,
除了202 19 39→81 104 118上的一个小错误,该错误给出80 104 118


1

R,88字节

function(h,s,l){v=(2*l+s*(1-abs(2*l-1)))/2;col2rgb(hsv(h,ifelse(v==0,v,(2*(v-l))/v),v))}

在线尝试!

此功能将H,S和L值作为0-1范围值输入,并输出RGB值作为0-255范围值。它将HSL表示转换为HSV表示,然后用于hsv()将HSV表示转换为R颜色(即十六进制表示-#rrggbb),然后用于col2rgb()将R颜色转换为RGB值。


1

果冻 39  32 字节

-1得益于caird coinheringaahing%2只是
-1和/或灵感来自-4得益于caird coinheringaahing

Ḥ;Ḃ’ACש"⁵×\;0+³_®H¤⁴Ḟị336Œ?¤¤œ?

包含三个命令行参数的完整程序:

  • LHS在范围[0,1)[0,6)[0,1)分别

打印一个列表,给出RGB格式为

  • [R, G, B] 范围内的三个值 [0,1]

注意:H也可以像包装一样包裹[0,360)

在线尝试!

怎么样?

Ḥ;Ḃ’ACש"⁵×\;0+³_®H¤⁴Ḟị336Œ?¤¤œ? - Main link: number, L (in [0,1]); number, H (in [0,6))
Ḥ                                - double                 =     2L
  Ḃ                              - modulo by 2            =              H%2
 ;                               - concatenate            = [   2L   ,   H%2]

   ’                             - decrement              = [   2L-1 ,   H%2-1]
    A                            - absolute               = [  |2L-1|,  |H%2-1|]
     C                           - complement             = [1-|2L-1|,1-|H%2-1|]
                                 -                        = [C/S     ,C/X]
         ⁵                       - 3rd program argument   = S  (in [0,1])
        "                        - zip with:
      ×                          -   multiplication       = [C,C/X]
       ©                         -   (copy the result, C, to the register)
           \                     - cumulative reduce with:
          ×                      -   multiplication       = [C, C/X*C] = [C,X]
            ;0                   - concatenate zero       = [C,X,0]
               ³                 - 1st program argument   = L
              +                  - add (vectorises)       = [C+L,X+L,L]
                   ¤             - nilad followed by link(s) as a nilad:
                 ®               -   recall from register = C
                  H              -   halve                = C/2
                _                - subtract               = [C+L-C/2,X+L-C/2,L-C/2]
                             ¤   - nilad followed by link(s) as a nilad:
                    ⁴            -   2nd program argument = H
                     Ḟ           -   floor                = floor(H)
                            ¤    -   nilad followed by link(s) as a nilad:
                       336       -     literal 336
                          Œ?     -     Shortest permutation of natural numbers with a
                                 -     lexicographical index of 336 in all permutations
                                 -     thereof            = [3,5,6,4,2,1]
                      ị          -   index into (1-indexed & modular)
                              œ? - get that permutation of [C+L-C/2,X+L-C/2,L-C/2]
                                 - implicit print

糟糕,当然。谢谢!
乔纳森·艾伦,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.