Valori da HSL a RGB


17

Lo scopo principale del modello di colore RGB (rosso verde blu) è il rilevamento, la rappresentazione e la visualizzazione di immagini in sistemi elettronici, quali televisori e computer

HSL (Hue Saturation Lightness) è un modello di colore alternativo, progettato negli anni '70 dai ricercatori di computer grafica per allinearsi più da vicino al modo in cui la visione umana percepisce gli attributi di creazione del colore

Ecco gli articoli wiki per RGB e HSL . È comune per i programmi di grafica eseguire i calcoli in HSL e successivamente convertirli nel formato preferito per la maggior parte degli schermi: RGB.

Il compito è quello di scrivere una funzione / programma che accetta HSL come input e output RGB.

Puoi scegliere la tua rappresentazione preferita per l'I / O, purché sia ​​coerente tra di loro.

Ad esempio, possono essere una matrice / tupla con 3 elementi o un oggetto con 3 proprietà denominate h, se l, ma accetterò altre variazioni intelligenti, come la ricezione di hsl come numero intero (perdita di precisione) e l'output di un numero intero rgb.

Si può presumere che l'input sia sicuro in termini di intervallo e formato, entrambi i quali è possibile decidere. Consiglio vivamente gli intervalli 0-1 0-1 0-1o 0-360 0-100 0-100per hsl e 0-1 0-1 0-1o 0-255 0-255 0-255per rgb.

Ogni risposta è richiesta per specificare entrambe le precedenti e inserire diverse varianti nelle risposte se ne sei particolarmente orgoglioso, anche se non hanno meno caratteri rispetto alle altre varianti. Metti il ​​più piccolo in cima.

Casi di test Pseudo per 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

Le formule per la conversione sono disponibili qui :

Questo è un bel modo per visualizzare la conversione:


L'intervallo suggerito per Hof 0-360è [0,360), sarebbe meglio scrivere come 0-359?
Jonathan Allan,

3
@JonathanAllan Penso che potrebbe sembrare un po 'più confuso, per quanto mi riguarda, il che suggerisce che 395.1 non è un possibile input. Semmai, usare la a-bnotazione è sbagliato di per sé quando si ha a che fare con valori non interi, ma direi che va bene mantenere la domanda più leggibile. Se qualcun altro si lamenta, lo ripenserò, quindi grazie per
averlo

Sì, d'accordo sul punto 359.1 - forse usa solo la notazione standard di [0,360)allora :)
Jonathan Allan il

sorpreso di non vedere risposte glsl;)
rimorchiato il

Risposte:


8

JavaScript (ES6), 98 95 94 byte

Prende H in [0,360) e S / L in [0,1) . Emette R , G e B come un array di 3 float in [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))

Casi test

Questo frammento converte i risultati in [0,255] .

Come?

Codice di inizializzazione

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)

Codice principale

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

Permutazioni di (0, C, X)

La parte leggermente complicata è generare la permutazione corretta di (0, C, X) in base all'angolo del componente tonalità. Come mostrato nella figura seguente, ciascun valore di colonna viene prelevato dalla stessa sequenza ciclica del periodo 6 , a partire da offset diversi. Nel codice sopra, stiamo usando - ~ H anziché solo + H perché dobbiamo forzare H a un numero intero. Da qui gli offset (5,3,1) anziché (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

Sarebbe prendendo Hin [0,6)e l'output a [0,1]risparmiare un po 'di byte?
Jonathan Allan,

@JonathanAllan Ah, non ho notato che il formato I / O era lento. Grazie!
Arnauld,

4

Mathematica, 155 byte

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


Provalo online!



1
@totallyhuman Non penso che sia giusto come HueHSB (AKA HSV) non HSL (vedi figure 2a e 2b nella pagina Wikipedia collegata).
Jonathan Allan,

1
Jenny - se è giusto non c'è motivo di non pubblicarlo come conteggio dei byte con il tuo non incorporato qui sotto!
Jonathan Allan,

1
@JonathanAllan Oh, così è. È un po 'fastidioso come RGBColoresiste ma HSLColornon lo fa. > _>
totalmente umano il

Esiste una versione non rigata di questo?
user76284

4

Python 2 , 32 byte

from colorsys import*;hls_to_rgb

Provalo online!

Questa funzionalità è effettivamente integrata in Python tramite l' hls_to_rgbinterno della colorsyslibreria. Il formato mine input è un intervallo 0-1 di HLS (anziché HSL, entrambi sono acronimi comuni per la stessa cosa [sebbene HSL sia più comune]). E il mio genera valori RGB in una tupla con un intervallo da 0 a 1.

Titoli di coda

Grazie a Jonathan Allan per aver sottolineato che ho solo bisogno di importarlo (e quindi aiutarmi ulteriormente a ridurre il conteggio dei byte).


Penso che questo possa essere solo di 31 byte from colorsys import hls_to_rgbpoiché da allora ci dà una funzione che può essere riutilizzata. Modifica - rendi quel 21 come from colorsys import*.
Jonathan Allan,

1
@JonathanAllan Grazie, aggiornato.
Neil,

In realtà probabilmente solo import colorsysper 15!
Jonathan Allan,

@JonathanAllan Nice, aggiornato di nuovo.
Neil,

1
per quanto vero possa essere, penso che questo influisca un po 'troppo sullo spirito del codegolfing: /
towc, il

4

C ++, 228 221 byte

-7 byte grazie a 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)}

Gli argomenti sono entrambi array che hanno una dimensione minima di 3 elementi (ie float hsl[3]eint rgb[3]

Va bene. Ora, come funziona? Cos'è quella lunga serie?

Bene, non è un array lungo, è un intarray. Scherzo a parte, l'array indica da quante posizioni spostiamo a destra CX e 0 quando vogliamo selezionare la permutazione corretta, + 2. Ricordi come sono selezionati R ', G' e B '?

Come sono selezionati R ', G' e B '

Supponiamo di avere un ordine "normale" che è {C, X, 0}

Ora, quando viene selezionata la prima permutazione (cioè {C, X, 0}), non è necessario spostare, che è esattamente la stessa cosa dello spostamento destro di 0. Quindi i primi 3 elementi dell'array sono 0,0 e 0

Per la seconda permutazione ({X, C, 0}), dobbiamo spostare a destra C di 1 e a sinistra X di -1, quindi il quarto, quinto e sesto elemento dell'array sono 1, -1 e 0

E così via...

Nel caso della 3a e 4a permutazione, ho bisogno di spostare a sinistra lo 0 di 2, quindi lo spostamento a destra di -2. Dato che ci sono più di 2 numeri negativi, piuttosto aggiungo 2 a ciascun elemento dell'array e sottraggo 2 in fase di esecuzione (per motivi di golf, per avere solo numeri interi nell'array).



4

Python 2 , 119 112 byte

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]

Provalo online!

Accetta input come H=[0,6[, S=[0,1], L=[0,1]


3

HTML + JavaScript (ES6), 8 + 88 = 96 byte

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>

Accetta input come un angolo e due percentuali. Sto segnando lo snippet HTML <p id=p>e la funzione freccia JavaScript. Non so che cosa usano i browser di arrotondamento, quindi le mie risposte potrebbero differire leggermente dalle tue.


2

Swift 4, 218 byte

Accetta i valori HSL nell'intervallo [0,1] come argomenti e restituisce un array contenente i valori RGB nello stesso intervallo:

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

L'idea è di convertire prima l'input da HSL a HSB, quindi utilizzare il costruttore HSB dell'oggetto colore incorporato in Cocoa per recuperare i valori RGB.

La versione UIKit ha la stessa identica lunghezza, in quanto le uniche sostituzioni sono:

  • CocoaUIKit
  • NSColorUIColor

Ungolfed:

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

Il seguente frammento può essere utilizzato per testare, semplicemente sostituendo i valori di h, se 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)

Sfortunatamente non posso fornire un collegamento a un sandbox online, poiché tutti funzionano su Linux, che non include Cocoa.


2

GLSL (GL_ES) 160 144 134 131 byte

La tonalità è nell'intervallo 0-6 (salva 3 byte)
Sat, luce e rgb sono 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);}

Provalo sul libro degli shader

Utilizzato lo strumento colorpicker su una schermata di stampa per testare l'output che era corretto,
tranne un piccolo errore su 202 19 39 → 81 104 118, che ha dato 80 104 118


1

R , 88 byte

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

Provalo online!

Questa funzione accetta come input i valori H, S e L come valori di intervallo 0-1 e genera i valori RGB come valori di intervallo 0-255. Converte la rappresentazione HSL in una rappresentazione HSV, quindi utilizza hsv()per convertire la rappresentazione HSV in un colore R (es. Rappresentazione esadecimale - #rrggbb), quindi utilizza col2rgb()per convertire il colore R in valori RGB.


1

Gelatina ,  39  32 byte

-1 grazie a caird coinheringaahing ( %2è solo )
-1 e / o ispirazione per -4 grazie anche a caird coinheringaahing !

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

Un programma completo che accetta tre argomenti della riga di comando:

  • L, H, SNegli intervalli [0,1), [0,6)e [0,1)rispettivamente

che stampa un elenco dando il formato RGB come

  • [R, G, B] con ciascuno dei tre valori nell'intervallo [0,1]

Nota: Hpuò anche avvolgere proprio come [0,360)farebbe.

Provalo online!

Come?

Ḥ;Ḃ’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

Oops, ovviamente. Grazie!
Jonathan Allan,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.