La teinte d'une couleur

23

Vous obtenez les valeurs RVB d'une couleur. Votre tâche est simple: calculer la teinte, dans la définition la plus simple.

Supposons que les canaux avec la valeur la plus élevée, la moyenne et la plus basse sont X, Y, Z (qui sont soit rouges, verts ou bleus) et leurs valeurs sont x, y, z. La teinte de cette couleur est (h (X) -h (Y)) * (1 + (xy) / (xz)) / 2 + h (Y), où:

h(red) = 0 (or 360 if one of X or Y is blue)
h(green) = 120
h(blue) = 240

L'entrée se compose de 3 entiers de 0 à 255 qui ne sont pas tous égaux, dans un ordre cohérent. La sortie peut être des flottants ou des entiers arrondis vers le haut ou vers le bas, ce qui ne doit pas nécessairement être cohérent. Si la partie entière de la sortie est 0 ou 360, vous pouvez imprimer l'un ou l'autre.

Vous ne pouvez pas appeler de fonction intégrée pour les conversions d'espace colorimétrique, y compris les conversions implicites, par exemple lors de la manipulation d'une image.

C'est du code-golf. Le code le plus court gagne.

Exemples

Input:  0 182 255
Output: 197 (or 198)

Input:  127 247 103
Output: 110

Input:  0 0 1
Output: 240

Input:  255 165 245
Output: 307 (or 306)

modifier

Vous n'êtes pas obligé de suivre la formule exacte, mais vous n'avez qu'à donner le même résultat que la formule ci-dessus. Je voudrais également voir quelques réponses jouant la formule elle-même.

jimmy23013
la source
Faut-il d'abord convertir le sRGB en une échelle linéaire? Je pense que nous devrions, mais personne ne semble l'avoir fait jusqu'à présent.
John Dvorak
@JanDvorak La tâche consiste à calculer la teinte, dans la définition la plus simple . Dans ce cas, "le plus simple" signifie que vous devez supposer que l'entrée est déjà dans la bonne échelle et utiliser la formule exacte donnée dans la question ou tout ce qui donne le même résultat.
jimmy23013
Mais ... 24 bpp signifie généralement sRGB. Sinon, la spécification de format (vous) doit spécifier le contraire.
John Dvorak
@JanDvorak Vous devez utiliser cette définition pour RVB et la teinte.
jimmy23013
9
Il faut dire: huehuehue.
TheDoctor

Réponses:

6

Pyth, 27 octets

*60%+c-Ft.<QJxQKeSQ-KhSQyJ6

Manifestation. Harnais de test.

Fomula tirée de Wikipédia .

Essentiellement, les étapes sont les suivantes:

  1. .<QJxQKeSQ: Place la plus grande valeur au début de la liste.
  2. -Ft: Prenez la différence des deux autres valeurs.
  3. -KhSQ: Soustrayez la valeur minimale de la valeur maximale.
  4. c: Divisez 2 par 3.
  5. + ... yJ Ajoutez deux fois l'index de la valeur maximale dans la liste (0 si R, 2 si G, 4 si B).
  6. % ... 6: Mod 6, pour résoudre les problèmes de négatifs.
  7. *60: Multipliez par 60 pour convertir en degrés et imprimer.
isaacg
la source
9

C #, 188 210 206 197 191 octets

int H(int r,int g,int b){int[]a={r,g,b};System.Array.Sort(a);int x=a[2],y=a[1],c=x==g?1:(x==b?2:(y==b?3:0)),d=y==g?1:(y==b?2:(x==b?3:0));return(int)((c-d)*120*(1+(x-y)*1D/(x-a[0]))/2+d*120);}

Merci à Sok pour avoir économisé 4 octets et à SLuck49 pour en avoir économisé 15!

ProgramFOX
la source
Comme vous n'utilisez zqu'une seule fois dans le calcul de sortie et que vous ne l'utilisez pas dans les calculs précédents, vous supprimez la variable et changez la sortie en return(int)((c-d)*(1+(x-y)/(double)(x-a[0]))/2+d);, vous économisant 4 octets.
Sok
Vous pouvez facteur 120 sur la cet les daffectations et dans le retour comme celui - ci c=x==g?1:(x==b?2:(y==b?3:0)),d=y==g?1:(y==b?2:(x==b?3:0)), puis return(int)((c-d)*120*(1+(x-y)/(double)(x-a[0]))/2+d*120);pour sauver 4 octets.
SLuck49
Avez-vous vraiment besoin du casting double? Si vous le faites, vous pouvez l'utiliser à la place (x-a[0])*1Dpour enregistrer 5 autres octets.
SLuck49
@ SLuck49 Merci! Oui, j'ai vraiment besoin du casting, cela donne des résultats inexacts sinon, mais cette *1Dmultiplication est une bonne astuce!
ProgramFOX
Aussi (juste remarqué), vous pouvez supprimer l'utilisation de tous ensemble en vous qualifiant pleinement System.Arraypour 6 autres octets.
SLuck49
8

Pyth, 41 55 53 51 octets

A.)JohN,VQ*L120?qeQhSQ3j312T+/*-HKeeJhc-GheJ-GhhJ2K

Une entrée est attendue dans le formulaire r,g,b. Voici une explication:

                                                        Implicit: Q=eval(input()), evaluates to (r,g,b)
               ?qeQhSQ                                  Is b the smallest?
                      3j312T                            Choose [0,1,2] or [3,1,2] based on above
          *L120                                         Convert to [0,120,240] or [360,120,240]
       ,VQ                                              Pair -> [[r,0/360],[g,120],[b,240]]
   JohN                                                 Order by 1st element in each pair, store in J
A.)J                                                    Pop biggest from J, set G = x, H = h(X)
                                                        Output calculation:
                                       -GheJ                x - y
                                            -GhhJ           x - z
                                     hc                     Divide and increment
                                 KeeJ                       Set K = h(Y)
                              *-HK                          Multiply by (h(X) - h(Y))
                             /                   2          Integer division by 2
                            +                     K         Add h(Y)

4 octets enregistrés grâce à @Jakube et @isaacg

Sok
la source
@ jimmy23013 Fixé, merci pour le test supplémentaire
Sok
1
Quelques golfs: m*120d-> *L120, enregistrer eeJen Kligne pour enregistrer un autre octet.
isaacg
@isaacg Je ne savais pas que l' Lopérateur générait automatiquement une plage sur un int, chaque jour est un jour shcool semble-t-il: o) Merci!
Sok
8

Javascript (ES6), 145 115 108 100 97 90 octets

Renvoie des flotteurs. Attribuez à une fonction à utiliser.

(r,g,b)=>([x,y,z]=[r,g,b].sort((a,b)=>b-a),m=x-z,(x-r?x-g?r-g+4*m:b-r+2*m:g-b+6*m)/m%6*60)

30 octets enregistrés en insérant tout dans une seule séquence d'opérateur ternaire et en attendant la fin pour normaliser à 0-360.

Merci à edc65, Vasu Adari et ETHproductions pour économiser encore plus d'octets.

JSFiddle avec tests. Essayez dans Firefox.

Si la suppression de la déclaration de fonction h=n'est pas légale, ajoutez 2 octets.

DankMemes
la source
Vous pouvez supprimer «var» et certains octets.
Vasu Adari
ES6Fiddle a besoin de la déclaration var pour une raison quelconque et je ne me suis pas rendu compte que ce n'était pas nécessaire avant d'avoir essayé ES6 dans firefox
DankMemes
1
Vous pouvez économiser 6 octets en remplaçant les accolades par des parenthèses, le point-virgule par une virgule et en supprimant le return. Je pense que la suppression de la déclaration de fonction ( h=) est également légale, ramenant le total à 100.
ETHproductions
Cela peut être obsessionnel (encore une fois, tous les bons golfeurs ne sont-ils pas?;)), Mais vous pouvez économiser deux octets de plus en vous débarrassant de la parenthèse %6)*60et de son partenaire de l'autre côté. De plus, l'utilisation de la force brute sur l'ajout (au lieu d'en ajouter 6 à la fin) économiserait en fait un octet par rapport à votre configuration actuelle. (((x==r?(g-b)/m:x==g?2+(b-r)/m:4+(r-g)/m)+6)%6)*60deviendrait (x==r?6+(g-b)/m:x==g?8+(b-r)/m:10+(r-g)/m)%6*60.
ETHproductions
1
+1 pour le genre, très intelligent, c'est 90 (ou 92)(r,g,b)=>([m,_,M]=[r,g,b].sort((a,b)=>a-b),C=M-m,(M-r?M-g?r-g+4*C:b-r+2*C:g-b+6*C)/C%6*60)
edc65
6

Octave, 65 60 50 octets

Edit: 10 octets enregistrés grâce à pawel.boczarski

Une solution approximative ...

@(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360)

Essai

@(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360)
ans([0   182   255])
ans =  196.14

@(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360)
ans([127   247   103])
ans =  111.05

@(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360)
ans([0   0   1])
ans =  240.00

@(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360)
ans([255   165   245])
ans =  305.82

Octave, 107 octets

Ma solution originale (exacte) ...

Code:

function H=r(c) [b,i]=sort(c);h=60*[6*(i(1)~=3),2,4](i);H=(h(3)-h(2))*(1+(b(3)-b(2))/(b(3)-b(1)))/2+h(2);

Expliqué:

function H=r(c)
   [b,i]=sort(c);
   h=60*[6*(i(1)~=3),2,4](i);
   H=(h(3)-h(2))*(1+(b(3)-b(2))/(b(3)-b(1)))/2+h(2);

Cette fonction prend un vecteur contenant les valeurs R, G, B en entrée cet trie l'entrée en ordre croissant

  • b contient les valeurs triées [z, y, x]
  • i contient le plan RVB associé à chaque valeur de b

Le vecteur hest rempli avec les valeurs

  • 60*[6, 2, 4]= [360, 120, 240](mais 3 octets de moins)
  • sauf si la valeur la plus basse est en Blue ( i(1) == 3), auquel cas la première valeur de teinte devient nulle
  • puis utilisez (i)pour réorganiser hdans l' [h(Z), h(Y), h(X)]ordre

De là, c'est juste une transcription directe de la formule. Vous pouvez l'essayer ici .

gobelet
la source
Astuce: utilisez la notation de fonction anonyme pour presser plus d'octets: @(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360)est dix octets plus court que la définition avec functionmot-clé.
pawel.boczarski
@ pawel.boczarski Je me demandais si je pouvais supprimer complètement l'en-tête de la fonction, mais je ne sais pas si c'est légitime. Mais merci pour l'astuce! : D
bécher
@ pawel.boczarski En y repensant, j'ai toujours besoin d'un r=avant la fonction anonyme pour l'appeler, non?
bécher
Il existe de nombreuses solutions où les fonctions anonymes sont publiées. De plus, vous pouvez appeler la fonction ainsi définie comme ceci (@(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360))([127 247 103]):, ou affirmer que vous pouvez utiliser une ansvariable juste après la définition de la fonction anonyme, de sorte que l'affectation n'est pas nécessaire pour que la définition de la fonction soit complète. Dans un défi ( codegolf.stackexchange.com/questions/54945 ), une poignée de la fonction de bibliothèque Matlab existante a été publiée comme solution complète.
pawel.boczarski
@ pawel.boczarski Wow, c'est ... juste ... mal: DI aurait dû savoir que Luis serait impliqué. Je vais revenir au code d'origine et l'utiliser ansdans l'exemple. Merci encore!
bécher
5

Pyth, 55

Je sais que la réponse de @ Sok bat la mienne, mais puisque j'ai fini la mienne juste après qu'il / elle a posté, je pensais que je posterais toujours. C'était la première fois que j'utilisais Pyth, donc je suis sûr d'avoir fait des erreurs évidentes.

DlZK*120ZRKJSQFNJ=Y+YxQN)=kl@Y1+k/*-leYk+1c-eJ@J1-eJhJ2

L'entrée devrait être r, g, b. Vous pouvez l'essayer ici .

Rhyzomatic
la source
Ne fonctionne pas pour 255,165,245.
jimmy23013
5

PowerShell, 232 226 222 161 octets

Voir l'historique des révisions pour les versions précédentes

$z,$y,$x=($r,$g,$b=$args)|sort
$c=((2,(0,3)[$y-eq$b])[$x-ne$b],1)[$x-eq$g]
$d=((2,(0,3)[$x-eq$b])[$y-ne$b],1)[$y-eq$g]
(($c-$d)*120*(1+($x-$y)/($x-$z))/2+$d*120)

Hoo boy, voyons si je peux traverser ça. Depuis \ncompte la même chose que ;j'ai laissé la ligne se rompt pour plus de clarté.

La première ligne prend trois entrées $argset les stocke dans $r, $g, $b. Nous n'utiliserons vraiment que $bplus tard, mais nous avons besoin des trois pour que les |sorttravaux fonctionnent correctement. Cela fait$z, $y, $x le plus petit au plus grand des arguments d'entrée.

Les deux lignes suivantes sont configurées $cet $den utilisant plusieurs appels d'index dans un tableau pour définir les nombres de manière appropriée. Travaillant de l'extérieur vers l'intérieur, si $xest -equal $g(c'est- à -dire que le vert était le plus grand), nous définissons $c=1... sinon, si$x est -not equal à $b(c.- à -d., Le bleu n'était pas le plus grand) $cest l'un 0ou l' autre ou 3dépend si le bleu était le deuxième plus grand ... autre, $c=2. Ensembles logiques similaires $d.

Nous calculons et imprimons ensuite la sortie avec ce qui suit, qui est juste l'algorithme du défi joué un peu.

(($c-$d)*120*(1+($x-$y)/($x-$z))/2+$d*120)
AdmBorkBork
la source
1
Je ne connais pas PowerShell, alors corrigez-moi si je me trompe ... Vous n'utilisez pas $zlors du calcul de $cou $d, et vous ne l'utilisez qu'une seule fois dans le calcul de sortie, alors pouvez-vous vous débarrasser $zcomplètement et le remplacer par $a[0]?
Sok
4

Rubis, 117 96 94 octets

Code:

h=->r,g,b{z,y,x=[r,g,b].sort;v=x-z.to_f;({r=>(g-b)/v,g=>2+(b-r)/v,b=>4+(r-g)/v}[x]%6*60).to_i}
  • Enregistré 21 octets en supprimant () et en utilisant les variables r, g, b.
  • Prendre un module de 6 pour convertir une valeur négative et le multiplier par 60 pour convertir en degrés qui ont économisé 2 octets.

Exemples:

irb(main):274:0> h.call 0,182,255
=> 197
irb(main):275:0> h.call 127,247,103
=> 110
irb(main):276:0> h.call 0,0,1
=> 240
irb(main):277:0> h.call 255,165,245
=> 306
Vasu Adari
la source
3

SWI-Prolog, 133 octets

a(L,H):-L=[R,G,B],max_list(L,X),min_list(L,Y),member(X:I:J:U,[R:G:B:0,G:B:R:2,B:R:G:4]),Z is 60*(U+(I-J)/(X-Y)),(Z<0,H is Z+360;H=Z).

Exemple: a([255,165,245],Hue). sortiesHue = 306.666666666666 .

Cela utilise la formule suivante:

  • Max = max(R,G,B), Min = min(R,G,B) .
  • Si Max = R, U = 0. Sinon , si Max = G, U = 2. AutreU = 4 .
  • Si Max = R, I = Get J = B. Sinon , si Max = G, I = Bet J = R. Sinon I = Ret J = G.
  • Z = U + (I - J)/(Max - Min)
  • Hueest soit Zou Z + 360si Z < 0.
Fatalize
la source
L'arrondi est facultatif.
jimmy23013
@ jimmy23013 Mis à jour, merci.
Fatalize
3

Perl 5, 138 132 119 octets

Code:

($m,$c,$M)=sort@A=($R,$G,$B)=@ARGV;print 60*(6+$M>$m?($G>$c?$B-$R:$B>$c?$R-$G:$G-$B)/($M-$m)+($G>$c?2:$B>$c?4:0):0)%360

Remarques:

Certes, Perl ne peut pas gagner un tel défi avec tout le golf Pyth'oresque. Mais je me demandais si cela était possible avec une seule étape de calcul. Merci au module qui a bien fonctionné. :)

Tester:

$ perl hue.pl 0 182 255
197
$ perl hue.pl 127 247 103
110
$ perl hue.pl 0 0 1
240
$ perl hue.pl 255 165 245
307
LukStorms
la source
comparer à la valeur moyenne au lieu du maximum rasé quelques octets. (== versus>)
LukStorms
1

C ++ 276 octets

#include <iostream>
int H(int r,int g,int b){int m,n=120,o=240,l=r>g?r>b?g>b?m=r-b,o=n,n=-n,r-g:m=r-g,r-b:m=b-g,o+=n,n=-n,b-r:g>b?r>b?(m=g-b,o=0,g-r):m=g-r,n=-n,g-b:(m=b-r,o-=n,b-g);return (int)n*((float)l/m+1)/2+o;}int main(){int r,g,b;std::cin>>r>>g>>b;std::cout<<H(r,g,b);}
EvgeniyZh
la source
Un conseil: vous pouvez laisser la Hfonction seule dans la réponse, car dans le code-golf, une fonction autonome est une réponse légitime, équivalente à un programme complet, vide méta discussion: meta.codegolf.stackexchange.com/questions/2419/… . Cela rendra votre réponse plus compétitive (économisez 100 octets dans votre cas). Vous êtes toujours encouragé à laisser la version "complète" du programme sous la solution pour simplifier les tests.
pawel.boczarski
Le deuxième cas de test 127 247 103renvoie une valeur non valide -120au lieu de 110.
pawel.boczarski
1

R, 125 octets

Très similaire à la solution Octave de bécher. Sortie en virgule flottante.

Code:

h=function(x){
  o=seq(3)[order(-x)];
  y=c(60*c(6*(o[3]!=3),2,4)[o],x[o]);
  return((y[1]-y[2])*(1+(y[4]-y[5])/(y[4]-y[6]))/2+y[2]);
}

Exemples:

> h(c(0,182,255))
[1] 197.1765
> h(c(127,247,103))
[1] 110
> h(c(0,0,1))
[1] 240
> h(c(255,165,245))
[1] 306.6667
popojan
la source
1

Python, 154 octets

def h(c):r=c[:];c.sort();c=c[::-1];x,y,z=c;i,j=[120if n==r[1]else 240if n==r[2]else 0if z==r[2]else 360for n in[x,y]];print ((i-j)*(1+(x-y+0.)/(x-z))/2)+j

Accepte une liste de valeurs. Je ne sais pas si cela peut être décomposé davantage. Ici, il n'est pas golfé:

def hue(color):
 rgb=color[:]  # copy list
 color.sort()  # sort list
 color=color[::-1]  # reverse sort
 x,y,z=color   # pull out x,y,z

 # The line 
 #   i,j=[120if n==r[1]else 240if n==r[2]else 0if z==r[2]else 360for n in[x,y]]
 # is basically the following, twice, once for x/hx and the second time for y/hy

 if x==rgb[1]: # if x is green
  hx = 120
 else:
  if x==rgb[2]: # if x is blue
   hx = 240
  else:
   if z==rgb[2]: # if z is blue and x is red
    hx = 0
   else:       # if x is red and y is blue
    hx = 1

 print ((hx-hy)*(1+(x-y+0.)/(x-z))/2)+hy  # calculate, print
Zaxvo
la source
0

JavaScript 108

Méthode alternative.

function H(r,g,b){a=[r,g,b].sort(),M=a[2],c=M-a[0],h=M==r?(g-b)/c%6:M==g?(b-r)/c+2:(r-g)/c+4
return h*60|0;}

JavaScript 194

Utilisation de la méthode d'exemple.

Array.prototype.i=[].indexOf
function H(r,g,b,a){a=[r,g,b].sort(),i=[a.i(r),a.i(g),a.i(b)],x=[i[2]?360:0,120,240],hx=x[i.i(2)]|0,hy=x[i.i(1)]|0
return (hx-hy)*(1+(a[2]-a[1])/(a[2]-a[0]))/2+hy|0}

var input = document.getElementById("input").innerHTML;
var output = document.getElementById("output");
var html = "";

input.replace(/(\d+)\,(\d+)\,(\d+)/g, function(m, r, g, b) {
  html += H(r, g, b) + "\n";
});

output.innerHTML = html;
<pre id="input">
0,182,255
127,247,103
0,0,1
255,165,245
</pre>

<pre id="output">

</pre>

marteau-de-loup
la source