Valeurs HSL à RVB

17

L'objectif principal du modèle de couleur RVB (rouge vert bleu) est la détection, la représentation et l'affichage d'images dans des systèmes électroniques, tels que des téléviseurs et des ordinateurs

HSL (Hue Saturation Lightness) est un modèle de couleur alternatif, conçu dans les années 1970 par des chercheurs en infographie pour s'aligner plus étroitement avec la façon dont la vision humaine perçoit les attributs de couleur

Voici les articles wiki pour RGB et HSL . Il est courant que les programmes graphiques fassent les calculs en HSL, puis les convertissent au format préféré pour la plupart des écrans: RVB.

La tâche consiste à écrire une fonction / un programme qui prend HSL comme entrée et génère RVB.

Vous pouvez choisir votre représentation préférée pour les E / S, tant qu'elle est cohérente entre elles.

Par exemple, ils peuvent être un tableau / tuple avec 3 éléments ou un objet avec 3 propriétés nommées h,s et l, mais je vais accepter d' autres variations intelligentes, comme la réception de la HSL comme un entier (perte de précision) et délivrer un entier rgb.

L'entrée peut être supposée sûre en termes de plage et de format, que vous pouvez tous deux décider. Je suggère fortement soit les gammes 0-1 0-1 0-1ou 0-360 0-100 0-100pour hsl, et 0-1 0-1 0-1ou0-255 0-255 0-255 pour rgb.

Chaque réponse est requise pour spécifier les deux ci-dessus, et mettez différentes variations dans vos réponses si vous êtes particulièrement fier d'eux, même si elles n'ont pas moins de caractères que vos autres variantes. Mettez le plus petit sur le dessus.

Pseudo cas de test pour 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

Les formules de conversion peuvent être trouvées ici :

C'est une belle façon de visualiser la conversion:

remorquage
la source
Votre gamme suggérée pour Hde 0-360est [0,360), serait - il mieux écrit 0-359?
Jonathan Allan
3
@JonathanAllan Je pense que cela pourrait sembler un peu plus confus, pour moi, ce qui suggère que 395.1 n'est pas une entrée possible. Si quoi que ce soit, l'utilisation de la a-bnotation est mauvaise en soi lorsqu'il s'agit de valeurs non entières, mais je dirais que c'est correct de garder la question plus lisible. Si quelqu'un d'autre se plaint, je vais y repenser, alors merci de l'avoir signalé
Towc
Ouais, d'accord sur le point 359.1 - peut-être juste utiliser la notation standard d' [0,360)alors :)
Jonathan Allan
surpris de ne voir aucune réponse glsl;)
Towc

Réponses:

8

JavaScript (ES6), 98 95 94 octets

Prend H en [0,360) et S / L en [0,1) . Sorties R , G et B sous forme de tableau de 3 flottants en [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))

Cas de test

Cet extrait de code convertit les résultats en [0,255] .

Comment?

Code d'initialisation

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)

Code principal

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

Permutations de (0, C, X)

La partie légèrement délicate consiste à générer la permutation correcte de (0, C, X) en fonction de l'angle de la composante de teinte. Comme le montre la figure suivante, chaque valeur de colonne est sélectionnée dans la même séquence de cycles de la période 6 , en commençant à différents décalages. Dans le code ci-dessus, nous utilisons - ~ H au lieu de seulement + H car nous devons contraindre H à un entier. D'où les décalages (5,3,1) au lieu de (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
la source
La prise Hen charge [0,6)et la sortie en [0,1]économiseraient-elles quelques octets?
Jonathan Allan
@JonathanAllan Ah, je n'ai pas remarqué que le format d'E / S était lâche. Merci!
Arnauld
4

Mathematica, 155 octets

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


Essayez-le en ligne!

J42161217
la source
1
Ou tu sais, ça. : P
totalement humain
1
@totallyhuman Je ne pense pas que ce soit vrai, tout comme HueHSB (AKA HSV) et non HSL (voir les figures 2a et 2b sur la page Wikipédia liée).
Jonathan Allan,
1
Jenny - si c'est vrai, il n'y a aucune raison de ne pas l'afficher comme nombre d'octets avec votre non-construit ci-dessous!
Jonathan Allan
1
@JonathanAllan Oh, il en est ainsi. C'est un peu ennuyeux de voir comment ça RGBColorexiste mais HSLColorpas. > _>
totalement humain
Existe-t-il une version non golfée de cela?
user76284
4

Python 2 , 32 octets

from colorsys import*;hls_to_rgb

Essayez-le en ligne!

Cette fonctionnalité est en fait intégrée à Python via l' hls_to_rgbintérieur ducolorsys bibliothèque. Le format des entrées de mine est une plage de 0 à 1 de HLS (au lieu de HSL, les deux sont des acronymes communs pour la même chose [bien que HSL soit plus courant]). Et le mien produit des valeurs RVB dans un tuple avec une plage de 0 à 1.

Crédits

Merci à Jonathan Allan d'avoir souligné que je dois juste l'importer (et ensuite m'aider à réduire le nombre d'octets).

Neil
la source
Je pense que cela ne peut être que de 31 octets car cela from colorsys import hls_to_rgbnous donne une fonction qui peut être réutilisée. Modifier - faites que 21 comme from colorsys import*.
Jonathan Allan
1
@JonathanAllan Merci, mis à jour.
Neil
En fait probablement juste import colorsyspour 15!
Jonathan Allan
@JonathanAllan Nice, mis à jour à nouveau.
Neil
1
aussi vrai que cela puisse être, je pense que cela affecte un peu trop l'esprit du golf de code: /
towc
4

C ++, 228 221 octets

-7 octets grâce à 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)}

Les arguments sont tous deux des tableaux qui ont une taille minimale de 3 éléments (c'est float hsl[3]-à- dire etint rgb[3]

D'accord. Maintenant, comment ça marche? Quel est ce long tableau?

Eh bien, ce n'est pas un long tableau, c'est un inttableau. Blague à part, le tableau indique de combien de positions nous décalons à droite CX et 0 lorsque nous voulons sélectionner la permutation correcte, + 2. Vous vous souvenez comment R ', G' et B 'sont sélectionnés?

Comment R ', G' et B 'sont sélectionnés

Disons que nous avons un ordre "normal" qui est {C, X, 0}

Maintenant, lorsque la première permutation (c'est-à-dire {C, X, 0}) est sélectionnée, vous ne devez pas déplacer, ce qui est exactement la même chose que le décalage à droite de 0. Ainsi, les 3 premiers éléments du tableau sont 0,0 et 0

Pour la deuxième permutation ({X, C, 0}), nous devons décaler à droite C de 1 et décaler à gauche X de -1, de sorte que les quatrième, cinquième et sixième éléments du tableau sont 1, -1 et 0

Etc...

Dans le cas des 3ème et 4ème permutations, j'ai besoin de décaler à gauche le 0 par 2, donc à droite de -2. Puisqu'il y a plus de 2 nombres négatifs, j'ajoute plutôt 2 à chaque élément du tableau et soustrais 2 au moment de l'exécution (pour des raisons de golf, pour n'avoir que des nombres entiers dans le tableau).

HatsuPointerKun
la source
221 octets: pastebin.com/C8WaSSpb
Zacharý
4

Python 2 , 119 112 octets

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]

Essayez-le en ligne!

Prend l'entrée comme H=[0,6[, S=[0,1], L=[0,1]

TFeld
la source
3

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

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>

Prend l'entrée comme un angle et deux pourcentages. J'évalue l'extrait HTML <p id=p>et la fonction de flèche JavaScript. Je ne sais pas ce que les navigateurs d'arrondi utilisent, donc mes réponses peuvent différer légèrement des vôtres.

Neil
la source
2

Swift 4, 218 octets

Accepte les valeurs HSL dans la plage [0,1] comme arguments et renvoie un tableau contenant les valeurs RVB dans la même plage:

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'idée est de convertir d'abord l'entrée HSL en HSB, puis d'utiliser le constructeur HSB de l'objet couleur intégré dans Cocoa pour récupérer les valeurs RVB.

La version UIKit a exactement la même longueur, car les seuls remplacements sont:

  • CocoaUIKit
  • NSColorUIColor

Non golfé:

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

L'extrait suivant peut être utilisé pour tester, en remplaçant simplement les valeurs h, set 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)

Malheureusement, je ne peux pas fournir de lien vers un sandbox en ligne, car ils fonctionnent tous sous Linux, qui n'inclut pas Cocoa.

xoudini
la source
2

GLSL (GL_ES) 160 144 134 131 octets

La teinte est dans la plage 0-6 (enregistre 3 octets)
Sat, light et rgb sont 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);}

Essayez-le sur le livre des shaders

Outil de sélection de couleurs utilisé sur un écran d'impression pour tester la sortie qui était correcte,
sauf une petite erreur sur 202 19 39 → 81 104 118, qui a donné 80 104 118

PrincePolka
la source
1

R , 88 octets

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

Essayez-le en ligne!

Cette fonction prend en entrée les valeurs H, S et L en tant que valeurs de plage 0-1 et sort les valeurs RVB en tant que valeurs de plage 0-255. Il convertit la représentation HSL en une représentation HSV, puis utilise hsv()pour convertir la représentation HSV en une couleur R (c'est-à-dire une représentation hexadécimale - #rrggbb), puis utilise col2rgb()pour convertir la couleur R en valeurs RVB.

duckmayr
la source
1

Gelée ,  39  32 octets

-1 grâce à caird coinheringaahing ( %2est juste )
-1 et / ou inspiration pour -4 grâce à caird coinheringaahing aussi!

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

Un programme complet prenant trois arguments de ligne de commande:

  • L, H, SDans les intervalles [0,1), [0,6)et [0,1)respectivement

qui imprime une liste donnant le format RVB

  • [R, G, B] avec chacune des trois valeurs de la plage [0,1]

Remarque: Hpeut également envelopper comme vous le [0,360)feriez.

Essayez-le en ligne!

Comment?

Ḥ;Ḃ’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
la source
Oups, bien sûr. Merci!
Jonathan Allan