Wartości HSL do RGB

17

Głównym celem modelu kolorów RGB (czerwony zielony niebieski) jest wykrywanie, reprezentacja i wyświetlanie obrazów w systemach elektronicznych, takich jak telewizory i komputery

HSL (Hue Saturation Lightness) to alternatywny model kolorów, zaprojektowany w latach 70. XX wieku przez badaczy grafiki komputerowej w celu ściślejszego dopasowania do sposobu, w jaki widzenie ludzkie postrzega atrybuty tworzenia kolorów

Oto artykuły wiki dla RGB i HSL . Programy graficzne często wykonują obliczenia w HSL, a później konwertują do preferowanego formatu dla większości ekranów: RGB.

Zadanie polega na napisaniu funkcji / programu, który pobiera HSL jako dane wejściowe i wyjściowe RGB.

Możesz wybrać preferowaną reprezentację dla We / Wy, o ile jest ona spójna między nimi.

Na przykład, mogą być tablicą / krotka z 3 elementów lub obiekt z 3 wymienionych właściwości h, si l, ale ja przyjąć inne pomysłowe wariacje, jak otrzymaniu HSL jako liczba całkowita (tracąc precyzji) oraz wyprowadzanie rgb całkowitą.

Można założyć, że dane wejściowe są bezpieczne w zakresie i formacie, o których można zdecydować. Zdecydowanie sugeruję albo zakresy, 0-1 0-1 0-1albo 0-360 0-100 0-100dla hsl i 0-1 0-1 0-1lub 0-255 0-255 0-255dla rgb.

Każda odpowiedź jest wymagana do określenia obu powyższych odpowiedzi i umieszczania różnych odmian w swoich odpowiedziach, jeśli jesteś z nich szczególnie dumny, nawet jeśli nie mają mniej znaków niż inne odmiany. Umieść najmniejszy na wierzchu.

Pseudo-przypadki dla 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

Formuły konwersji można znaleźć tutaj :

To dobry sposób na wizualizację konwersji:

towc
źródło
Twój sugeruje zakres Ho 0-360to [0,360), że będzie lepiej napisany jako 0-359?
Jonathan Allan,
3
@JonathanAllan Myślę, że może to wyglądać nieco bardziej mylące, co dla mnie sugeruje, że 395,1 nie jest możliwym wkładem. Jeśli już, używanie a-bnotacji samo w sobie jest niewłaściwe w przypadku wartości niecałkowitych, ale powiedziałbym, że lepiej jest zadawać pytanie bardziej czytelnym. Jeśli ktoś jeszcze narzeka, to przemyślę to, więc dziękuję za zwrócenie na to uwagi
zwróć uwagę
Tak, uzgodniono punkt 359,1 - może po prostu użyj standardowej notacji z [0,360)tego czasu :)
Jonathan Allan
zaskoczony brakiem odpowiedzi na glsl;)
towc

Odpowiedzi:

8

JavaScript (ES6), 98 95 94 bajtów

Staje H w [0,360) i S / L na [0,1) . Wyjścia R , G i B jako tablica 3 pływaków w [0,1) .

(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))

Przypadki testowe

Ten fragment przekształca wyniki z powrotem w [0,255] .

W jaki sposób?

Kod inicjalizacji

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)

Kod główny

[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]

Permutacje (0, C, X)

Nieco trudną częścią jest wygenerowanie prawidłowej permutacji (0, C, X) zgodnie z kątem elementu odcienia. Jak pokazano na poniższym rysunku, każda wartość kolumny jest wybierana z tej samej sekwencji cyklicznej okresu 6 , zaczynając od różnych przesunięć. W powyższym kodzie używamy - ~ H zamiast po prostu + H, ponieważ musimy zmusić H do liczby całkowitej. Stąd przesunięcia (5,3,1) zamiast (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
Arnauld
źródło
Byłoby biorąc Hw[0,6) i wyprowadzanie w [0,1]zaoszczędzić trochę bajtów?
Jonathan Allan,
@JonathanAllan Ah, nie zauważyłem, że format I / O jest luźny. Dzięki!
Arnauld,
4

Mathematica, 155 bajtów

(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)&


Wypróbuj online!

J42161217
źródło
1
Albo wiesz to. : P
całkowicie ludzki
1
@ totalniehuman Nie sądzę, że tak Huejest, podobnie jak HSB (AKA HSV), a nie HSL (patrz rysunki 2a i 2b na powiązanej stronie Wikipedii).
Jonathan Allan,
1
Jenny - jeśli jest w porządku, nie ma powodu, aby nie publikować, ponieważ liczba bajtów z Twoim niezbudowanym poniżej!
Jonathan Allan,
1
@JonathanAllan Och, tak jest. To trochę irytujące RGBColor, ale istnieje HSLColor. > _>
całkowicie ludzki,
Czy istnieje wersja dla graczy nieprzygotowanych do gry w golfa?
user76284,
4

Python 2 , 32 bajty

from colorsys import*;hls_to_rgb

Wypróbuj online!

Ta funkcja jest w rzeczywistości wbudowana w Pythona poprzez hls_to_rgbwnętrze colorsysbiblioteki. Format danych wejściowych kopalni ma zakres 0-1 HLS (zamiast HSL oba są powszechnymi akronimami tego samego [aczkolwiek HSL jest bardziej powszechny]). I wydobywam wartości RGB w krotce o zakresie od 0 do 1.

Kredyty

Dziękuję Jonathanowi Allanowi za wskazanie, że muszę go tylko zaimportować (a następnie pomóc mi zmniejszyć liczbę bajtów).

Neil
źródło
Myślę, że może to być tylko 31 bajtów, ponieważ from colorsys import hls_to_rgbod tego czasu daje nam funkcję, która może być ponownie użyta. Edytuj - ustaw 21 jako from colorsys import*.
Jonathan Allan,
1
@JonathanAllan Dzięki, zaktualizowano.
Neil,
Właściwie prawdopodobnie tylko import colorsysdla 15!
Jonathan Allan,
@JonathanAllan Nice, ponownie zaktualizowany.
Neil,
1
jakkolwiek by to nie było prawda, myślę, że to trochę za bardzo wpływa na ducha kodegolfa: /
towc
4

C ++, 228 221 bajtów

-7 bajtów dzięki Zacharýowi

#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)}

Oba argumenty to tablice, które mają minimalny rozmiar 3 elementów (tj. float hsl[3]Iint rgb[3]

W porządku. Jak to działa? Co to za długa tablica?

Cóż, to nie jest długa tablica, to inttablica. Żartuję, tablica wskazuje, o ile pozycji przesuwamy w prawo CX i 0, gdy chcemy wybrać prawidłową permutację, + 2. Pamiętasz, jak wybierane są R ', G' i B '?

Jak wybierane są R ', G' i B '

Powiedzmy, że mamy „normalną” kolejność {C, X, 0}

Teraz, gdy wybrana jest pierwsza permutacja (tj. {C, X, 0}), nie trzeba przesuwać, co jest dokładnie tym samym, co przesunięcie w prawo o 0. Tak więc pierwsze 3 elementy tablicy to 0,0 i 0

Dla drugiej permutacji ({X, C, 0}) musimy przesunąć w prawo C o 1, a lewe przesunięcie X o -1, więc czwarty, piąty i szósty element tablicy to 1, -1 i 0

I tak dalej...

W przypadku 3. i 4. permutacji muszę przesunąć w lewo 0 na 2, więc przesunięcie w prawo o -2. Ponieważ istnieją więcej niż 2 liczby, które są ujemne, raczej dodam 2 do każdego elementu w tablicy i odejmuję 2 w czasie wykonywania (z powodów golfowych, aby mieć tylko liczby całkowite w tablicy).

HatsuPointerKun
źródło
221 bajtów: pastebin.com/C8WaSSpb
Zacharý
4

Python 2 , 119 112 bajtów

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]

Wypróbuj online!

Pobiera dane wejściowe jako H=[0,6[, S=[0,1], L=[0,1]

TFeld
źródło
3

HTML + JavaScript (ES6), 8 + 88 = 96 bajtów

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>

Pobiera dane wejściowe jako kąt i dwa procenty. Oceniam fragment kodu HTML <p id=p>i funkcję strzałki JavaScript. Nie wiem, z czego korzystają przeglądarki zaokrąglające, więc moje odpowiedzi mogą się nieco różnić od twoich.

Neil
źródło
2

Szybkie 4, 218 bajtów

Akceptuje wartości HSL z zakresu [0,1] jako argumenty i zwraca tablicę zawierającą wartości RGB z tego samego zakresu:

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]}

Chodzi o to, aby najpierw przekonwertować dane wejściowe z HSL na HSB, a następnie użyć konstruktora HSB wbudowanego obiektu koloru w kakao, aby pobrać wartości RGB.

Wersja UIKit ma dokładnie taką samą długość, ponieważ jedynymi zamiennikami są:

  • CocoaUIKit
  • NSColorUIColor

Nie golfowany:

#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]
}

Poniższy fragment kodu mogą być używane do testowania, po prostu zastąpienie wartości h, soraz 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)

Niestety nie mogę podać linku do piaskownicy online, ponieważ wszystkie z nich działają w systemie Linux, który nie obejmuje Cocoa.

xoudini
źródło
2

GLSL (GL_ES) 160 144 134 131 bajtów

Barwa mieści się w zakresie 0–6 (zapisuje 3 bajty)
Sat, light i rgb mają wartość 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);}

Wypróbuj na książce shaderów

Użyto narzędzia do pobierania kolorów na ekranie drukowania, aby przetestować wyjście, które było prawidłowe,
z wyjątkiem małego błędu w 202 19 39 → 81 104 118, co dało 80 104 118

PrincePolka
źródło
1

R , 88 bajtów

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))}

Wypróbuj online!

Ta funkcja przyjmuje na wejściu wartości H, S i L jako wartości dystansowe 0-1 i wysyła wartości RGB jako wartości dystansowe 0-255. Konwertuje reprezentację HSL na reprezentację HSV, a następnie używa hsv()do konwersji reprezentacji HSV na kolor R (tj. Reprezentację szesnastkową - #rrggbb), a następnie używa col2rgb()do konwersji koloru R na wartości RGB.

duckmayr
źródło
1

Galaretka ,  39  32 bajtów

-1 dzięki Cairnowi coinheringaahing ( %2jest po prostu )
-1 i / lub inspiracji dla -4 dzięki Cairnowi coinheringaahing !

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

Pełny program przyjmujący trzy argumenty wiersza poleceń:

  • L, H , SW zakresach [0,1), [0,6)i [0,1)odpowiednio

która drukuje listę podającą format RGB jako

  • [R, G, B] z każdą z trzech wartości w zakresie [0,1]

Uwaga: Hmoże również zawijać tak jak [0,360)by to robił.

Wypróbuj online!

W jaki sposób?

Ḥ;Ḃ’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
Jonathan Allan
źródło
Ups, oczywiście. Dzięki!
Jonathan Allan,