El tono de un color

23

Se le dan los valores RGB de un color. Su tarea es simple: calcular el tono, en la definición más simple.

Digamos que los canales con el valor más alto, medio y más bajo son X, Y, Z (que son rojos, verdes o azules) y sus valores son x, y, z. El tono de este color es (h (X) -h (Y)) * (1 + (xy) / (xz)) / 2 + h (Y), donde:

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

La entrada consta de 3 enteros de 0 a 255 que no son todos iguales, en ningún orden consistente. La salida puede ser flotante o números enteros redondeados hacia arriba o hacia abajo, lo que no tiene que ser consistente. Si la parte entera de la salida es 0 o 360, puede imprimir cualquiera de ellos.

No puede llamar a las incorporaciones para conversiones de espacio de color, incluidas las conversiones implícitas, como al manipular una imagen.

Este es el código de golf. El código más corto gana.

Ejemplos

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)

Editar

No tiene que seguir la fórmula exacta, pero solo tiene que dar el mismo resultado que la fórmula anterior. También me gustaría ver algunas respuestas jugando a la fórmula en sí.

jimmy23013
fuente
¿Deberíamos convertir de sRGB a una escala lineal primero? Creo que deberíamos, pero nadie parece tener hasta ahora.
John Dvorak
@ JanDvorak La tarea es calcular el tono, en la definición más simple . En este caso, "más simple" significa que debe suponer que la entrada ya está en la escala correcta y usar la fórmula exacta dada en la pregunta o cualquier cosa que dé el mismo resultado.
jimmy23013
Pero ... 24 bpp generalmente significa sRGB. Si no, la especificación de formato (usted) debe especificar lo contrario.
John Dvorak
@ JanDvorak Debe usar esta definición para RGB y el matiz.
jimmy23013
99
Hay que decir: huehuehue.
TheDoctor

Respuestas:

6

Pyth, 27 bytes

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

Demostración. Prueba de arnés.

Fócula tomada de Wikipedia .

Esencialmente, los pasos son:

  1. .<QJxQKeSQ: Roate el valor más grande al frente de la lista.
  2. -Ft: Tome la diferencia de los otros dos valores.
  3. -KhSQ: Resta el valor mínimo del valor máximo.
  4. c: Divide 2 entre 3.
  5. + ... yJ Agregue dos veces el índice del valor máximo en la lista (0 si R, 2 si G, 4 si B).
  6. % ... 6: Mod 6, para solucionar problemas con negativos.
  7. *60: Multiplique por 60 para convertir a grados e imprima.
isaacg
fuente
9

C #, 188 210 206 197 191 bytes

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

¡Gracias a Sok por guardar 4 bytes y a SLuck49 por guardar 15!

ProgramFOX
fuente
Como solo usa zuna vez en el cálculo de salida, y no lo usa en los cálculos anteriores, elimina la variable y cambia la salida a return(int)((c-d)*(1+(x-y)/(double)(x-a[0]))/2+d);, ahorrándole 4 bytes.
Sok
Usted puede factorizar 120 de la cy de dlas tareas y en el retorno de esta manera c=x==g?1:(x==b?2:(y==b?3:0)),d=y==g?1:(y==b?2:(x==b?3:0))y luego return(int)((c-d)*120*(1+(x-y)/(double)(x-a[0]))/2+d*120);de salvar 4 bytes.
SLuck49
¿También realmente necesitas el elenco double? Si lo hace, puede usar esto (x-a[0])*1Dpara guardar otros 5 bytes.
SLuck49
@ SLuck49 ¡Gracias! Sí, realmente necesito el yeso, de lo contrario, da resultados inexactos, ¡pero esa *1Dmultiplicación es un buen truco!
ProgramFOX
También también (acabo de notar) puede eliminar el uso todos juntos al calificar completamente System.Arraypara otros 6 bytes.
SLuck49
8

Pyth 41 55 53 51 bytes

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

Se espera la entrada en el formulario r,g,b. Aquí hay una explicación:

                                                        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)

Guardado 4 bytes, gracias a @Jakube y @isaacg

Sok
fuente
@ jimmy23013 Solucionado, gracias por el caso de prueba adicional
Sok
1
Un par de campos de golf: m*120d-> *L120, guardar eeJen Klínea para guardar otro byte.
isaacg
@isaacg No sabía que el Loperador generaba un rango en un int automáticamente, cada día es un día de escuela parece: o) ¡Gracias!
Sok
8

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

Devuelve flotadores. Asignar a una función para usar.

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

Ahorró 30 bytes al alinear todo en una única secuencia de operador ternario y esperar hasta el final para normalizar a 0-360.

Gracias a edc65, Vasu Adari y ETHproductions por guardar aún más bytes.

JS Violín con pruebas. Prueba en Firefox.

Si eliminar la declaración de función h=no es legal, agregue 2 bytes.

DankMemes
fuente
Puede eliminar 'var' y algunos bytes.
Vasu Adari
ES6Fiddle necesita la declaración var por alguna razón y no me di cuenta de que no era necesario hasta que probé ES6 en firefox
DankMemes
1
Puede guardar 6 bytes reemplazando las llaves con paréntesis, el punto y coma con una coma y eliminando el return. Creo que eliminar la declaración de función ( h=) también es legal, lo que reduce el total a 100.
ETHproductions
Esto puede ser obsesivo (una vez más, ¿no son todos buenos golfistas?;)), Pero podría ahorrar dos bytes más al deshacerse del paréntesis %6)*60y su compañero en el otro lado. Además, el uso de la fuerza bruta en la suma (en lugar de sumar 6 al final) en realidad ahorraría un byte sobre su configuración actual. (((x==r?(g-b)/m:x==g?2+(b-r)/m:4+(r-g)/m)+6)%6)*60se convertiría (x==r?6+(g-b)/m:x==g?8+(b-r)/m:10+(r-g)/m)%6*60.
ETHproductions
1
+1 para el tipo, muy inteligente, esto es 90 (o 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

Octava, 65 60 50 bytes

Editar: Guardado 10 bytes gracias a pawel.boczarski

Una solución aproximada ...

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

Prueba de funcionamiento

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

Octava, 107 bytes

Mi solución original (exacta-ish) ...

Código:

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

Explicado:

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

Esta función toma un vector que contiene los valores R, G, B como entrada cy ordena la entrada en orden ascendente

  • b contiene los valores ordenados [z, y, x]
  • i contiene el plano RGB asociado con cada valor en b

El vector hse rellena con los valores.

  • 60*[6, 2, 4]= [360, 120, 240](pero 3 bytes más corto)
  • a menos que el valor más bajo esté en azul ( i(1) == 3), en cuyo caso el primer valor de tono se convierte en cero
  • luego use (i)para reorganizar hen [h(Z), h(Y), h(X)]orden

A partir de ahí, es solo una transcripción directa de la fórmula. Puedes probarlo aquí .

cubilete
fuente
Sugerencia: utilice la notación de función anónima para exprimir más bytes: @(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360)es diez bytes más corta que la definición con la functionpalabra clave.
pawel.boczarski
@ pawel.boczarski Me preguntaba si podría eliminar por completo el encabezado de la función, pero no sé si eso es legítimo. ¡Pero gracias por el consejo! : D
vaso
@ pawel.boczarski Mirando hacia atrás, todavía necesito una r=función anónima antes de poder llamarla, ¿verdad?
vaso
Hay muchas soluciones donde se publican funciones anónimas. Además, puede llamar a la función así definida incluso de esta manera: (@(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360))([127 247 103])o argumentar que puede usar la ansvariable justo después de que se definió la función anónima, de modo que la asignación no es necesaria para que la definición de la función se complete. En un desafío ( codegolf.stackexchange.com/questions/54945 ) se publicó un identificador de la función de biblioteca Matlab existente como solución completa.
pawel.boczarski
@ pawel.boczarski Wow, eso es ... simplemente ... malvado: DI debería haber sabido que Luis estaría involucrado. Volveré al código original y lo usaré ansen la muestra. ¡Gracias de nuevo!
vaso
5

Pyth, 55

Sé que la respuesta de @ Sok supera a la mía, pero como terminé la mía justo después de que él / ella publicara, pensé que aún publicaría. Esta fue mi primera vez usando Pyth, así que estoy seguro de que cometí algunos errores obvios.

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

Se espera que la entrada sea r, g, b. Puedes probarlo aquí .

Rhyzomatic
fuente
No funciona para 255,165,245.
jimmy23013
5

PowerShell, 232 226 222 161 Bytes

Ver historial de revisiones para versiones anteriores

$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, veamos si puedo atravesar esto. Ya que\n cuenta lo mismo ;que dejé, la línea se interrumpe para mayor claridad.

La primera línea toma la entrada como tres $argsy los almacena en $r, $g, $b. Realmente solo lo usaremos $bmás tarde, pero necesitamos los tres para que |sortfuncione adecuadamente. Esto hace$z, $y, $x el argumento de entrada menor a mayor.

Las siguientes dos líneas se configuran $cy $dutilizan múltiples llamadas de índice en una matriz para establecer los números de manera adecuada. Trabajando desde afuera hacia adentro, si $xes -equal a $g(es decir, el verde era el más grande), nos propusimos $c=1... otra cosa, si $xes -not equal a $b(es decir, el azul no era el más grande) $cestá bien 0o 3dependiendo de si el azul era el segundo más grande ... otra cosa, $c=2. Conjuntos lógicos similares$d .

Luego calculamos e imprimimos la salida con lo siguiente, que es solo el algoritmo del desafío jugado un poco.

(($c-$d)*120*(1+($x-$y)/($x-$z))/2+$d*120)
AdmBorkBork
fuente
1
No conozco PowerShell, así que corrígeme si me equivoco ... No lo usas $zal calcular $co $d, y solo lo usas una vez en el cálculo de salida, entonces ¿puedes deshacerte por $zcompleto y reemplazarlo por $a[0]?
Sok
4

Ruby, 117 96 94 bytes

Código:

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}
  • Se guardaron 21 bytes al eliminar ()y usar r, g, b variables.
  • Tomando un módulo de 6 para convertir el valor negativo y multiplicándolo por 60 para convertir a grados que ahorraron 2 bytes.

Ejemplos:

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
fuente
3

SWI-Prolog, 133 bytes

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

Ejemplo: a([255,165,245],Hue). salidasHue = 306.666666666666 .

Esto usa la siguiente fórmula:

  • Max = max(R,G,B), Min = min(R,G,B) .
  • Si Max = R, U = 0. Si no Max = G,U = 2 . De lo contrario U = 4.
  • Si Max = R, I = Gy J = B. Si no Max = G, I = By J = R. De lo contrario I = Ry J = G.
  • Z = U + (I - J)/(Max - Min)
  • Huees Zo Z + 360si Z < 0.
Fatalizar
fuente
El redondeo es opcional.
jimmy23013
@ jimmy23013 Actualizado, gracias.
Fatalize el
3

Perl 5, 138 132 119 bytes

Código:

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

Observaciones:

Seguramente Perl no puede ganar tal desafío con todo el golf Pyth'oresque. Pero me preguntaba si esto era posible con solo 1 paso de cálculo. Gracias al módulo que funcionó muy bien. :)

Prueba:

$ 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
fuente
en comparación con el valor medio en lugar del máximo afeitado algunos bytes. (== versus>)
LukStorms
1

C ++ 276 bytes

#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
fuente
Una sugerencia: puede dejar la Hfunción sola en la respuesta, ya que en code-golf una función independiente es una respuesta legítima, equivalente a un programa completo, ver meta discusión: meta.codegolf.stackexchange.com/questions/2419/… . Esto hará que su respuesta sea más competitiva (ahorre 100 bytes en su caso). Todavía se le recomienda dejar la versión "completa" del programa bajo la solución para simplificar las pruebas.
pawel.boczarski
El segundo caso de prueba 127 247 103produce un valor no válido en -120lugar de 110.
pawel.boczarski
1

R, 125 bytes

Muy similar a la solución Octave del vaso de precipitados. Salida en coma flotante.

Código:

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

Ejemplos:

> 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
fuente
1

Python, 154 bytes

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

Acepta una lista de valores. No estoy seguro si esto puede desglosarse aún más. Aquí no tiene 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
fuente
0

JavaScript 108

Metodo alternativo.

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

Usando el método de ejemplo.

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>

martillo de lobo
fuente