O tom de uma cor

23

Você recebe os valores RGB de uma cor. Sua tarefa é simples: calcular o matiz, na definição mais simples.

Digamos que os canais com os valores mais alto, médio e mais baixo sejam X, Y, Z (que são vermelhos, verdes ou azuis) e seus valores sejam x, y, z. O matiz dessa cor é (h (X) -h (Y)) * (1 + (xy) / (xz)) / 2 + h (Y), onde:

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

A entrada consiste em 3 números inteiros de 0 a 255, que não são todos iguais, em qualquer ordem consistente. A saída pode ser flutuantes ou números inteiros arredondados para cima ou para baixo, o que não precisa ser consistente. Se a parte inteira da saída for 0 ou 360, você poderá imprimir qualquer um deles.

Você não pode chamar builtins para conversões de espaço de cores, incluindo conversões implícitas, como durante a manipulação de uma imagem.

Isso é código-golfe. O menor código vence.

Exemplos

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

Você não precisa seguir a fórmula exata, mas apenas fornecer o mesmo resultado que a fórmula acima. Eu também gostaria de ver algumas respostas jogando a fórmula em si.

jimmy23013
fonte
Devemos converter primeiro de sRGB para uma escala linear? Eu acho que deveríamos, mas ninguém parece ter até agora.
John Dvorak
@JanDvorak A tarefa é calcular o matiz, na definição mais simples . Nesse caso, "mais simples" significa que você deve assumir que a entrada já está na escala correta e usar a fórmula exata dada na pergunta ou qualquer coisa que dê o mesmo resultado.
precisa saber é o seguinte
Mas ... 24 bpp geralmente significa sRGB. Caso contrário, a especificação de formato (você) deve especificar o contrário.
John Dvorak
@ JanDvorak Você deve usar esta definição para RGB e matiz.
precisa saber é o seguinte
9
Tem que ser dito: huehuehue.
TheDoctor

Respostas:

6

Pitão, 27 bytes

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

Demonstração. Equipamento de teste.

Fomula retirado da Wikipedia .

Essencialmente, as etapas são:

  1. .<QJxQKeSQ: Posicione o maior valor na frente da lista.
  2. -Ft: Tome a diferença dos outros dois valores.
  3. -KhSQ: Subtraia o valor mínimo do valor máximo.
  4. c: Divida 2 por 3.
  5. + ... yJ Adicione duas vezes o índice do valor máximo na lista (0 se R, 2 se G, 4 se B).
  6. % ... 6: Mod 6, para corrigir problemas com negativos.
  7. *60: Multiplique por 60 para converter em graus e imprima.
isaacg
fonte
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);}

Agradecimentos a Sok por salvar 4 bytes e a SLuck49 por salvar 15!

ProgramFOX
fonte
Como você usa apenas zuma vez no cálculo da saída e não nos cálculos anteriores, elimina a variável e altera a saída para return(int)((c-d)*(1+(x-y)/(double)(x-a[0]))/2+d);, economizando 4 bytes.
Sok
Você pode factor 120 para fora do ce datribuições e para o retorno como este c=x==g?1:(x==b?2:(y==b?3:0)),d=y==g?1:(y==b?2:(x==b?3:0))e, em seguida, return(int)((c-d)*120*(1+(x-y)/(double)(x-a[0]))/2+d*120);para salvar 4 bytes.
precisa saber é o seguinte
Você também precisa mesmo do elenco double? Se você fizer isso, poderá usar isso (x-a[0])*1Dpara salvar outros 5 bytes.
precisa saber é o seguinte
@ SLuck49 Obrigado! Sim, na verdade, eu preciso do elenco, pois de outra forma, resultados imprecisos, mas essa *1Dmultiplicação é um bom truque!
ProgramFOX
Também (apenas notei), você pode descartar o uso de todos juntos, qualificando-se totalmente System.Arraypor outros 6 bytes.
precisa saber é o seguinte
8

Pyth, 41. 55 53 51 bytes

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

A entrada é esperada no formulário r,g,b. Aqui está uma explicação:

                                                        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)

Salvo 4 bytes, graças a @Jakube e @isaacg

Sok
fonte
@ jimmy23013 Corrigido, obrigado pelo caso de teste extra #
Sok
1
Alguns campos de golfe: m*120d-> *L120, salve eeJem Klinha para salvar outro byte.
Isaacg
@isaacg Eu não sabia que o Loperador gerava um intervalo em um int automaticamente, todo dia é um dia de folga, parece: o) Obrigado!
Sok
8

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

Retorna flutuadores. Atribua a uma função a ser usada.

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

Economizou 30 bytes inserindo tudo em uma única sequência de operador ternário e aguardando até o final normalizar para 0-360.

Agradecemos a edc65, Vasu Adari e ETHproductions por economizar ainda mais bytes.

JSFiddle com testes. Experimente no Firefox.

Se a remoção da declaração da função h=não for legal, adicione 2 bytes.

DankMemes
fonte
Você pode remover 'var' e alguns bytes.
Vasu Adari
ES6Fiddle precisa a declaração var por alguma razão e eu não sabia que isso não era necessário até que eu tentei ES6 no firefox
DankMemes
1
Você pode salvar 6 bytes substituindo os chavetas por parênteses, o ponto-e-vírgula por vírgula e removendo o return. Eu acredito que remover a declaração de função ( h=) também é legal, diminuindo o total para 100.
ETHproductions
Isso pode ser obsessivo (não são todos bons jogadores de golfe?;)), Mas você pode economizar mais dois bytes se livrando dos parênteses %6)*60e de seu parceiro do outro lado. Além disso, o uso de força bruta na adição (em vez de adicionar 6 no final) economizaria um byte na configuração atual. (((x==r?(g-b)/m:x==g?2+(b-r)/m:4+(r-g)/m)+6)%6)*60se tornaria (x==r?6+(g-b)/m:x==g?8+(b-r)/m:10+(r-g)/m)%6*60.
ETHproduções
1
+1 para o tipo, muito inteligente. Isso é 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

Oitava, 65 60 50 bytes

Edit: salvou 10 bytes graças a pawel.boczarski

Uma solução aproximada ...

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

Execução de teste

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

Oitava, 107 bytes

Minha solução original (exata-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 função aceita um vetor que contém os valores R, G, B como entrada c e classifica a entrada em ordem crescente

  • b contém os valores classificados [z, y, x]
  • i contém o plano RGB associado a cada valor em b

O vetor hé preenchido com os valores

  • 60*[6, 2, 4] = [360, 120, 240] (mas 3 bytes mais curto)
  • a menos que o valor mais baixo esteja em azul (i(1) == 3 ); nesse caso, o primeiro valor de matiz se torna zero
  • use (i)para reorganizar hem [h(Z), h(Y), h(X)]ordem

A partir daí, é apenas uma transcrição direta da fórmula. Você pode tentar aqui .

taça
fonte
Dica: use notação de função anônima para espremer mais bytes: @(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360)é dez bytes mais curto que a definição com a functionpalavra - chave.
pawel.boczarski
@ pawel.boczarski Eu queria saber se poderia acabar com o cabeçalho da função completamente, mas não sei se isso é legítimo. Mas obrigado pela dica! : D
proveta
@ pawel.boczarski Olhando para trás, ainda preciso de um r=antes da função anônima para chamá-la, certo?
copo
Existem muitas soluções em que funções anônimas são postadas. Além disso, você poderia chamar a função assim definida assim:: (@(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360))([127 247 103])ou argumentar que você pode usar a ansvariável logo após a definição da função anônima, para que a atribuição não seja necessária para que a definição da função seja concluída. Em um desafio ( codegolf.stackexchange.com/questions/54945 ), um identificador da função existente da biblioteca Matlab foi publicado como solução completa.
pawel.boczarski
@ pawel.boczarski Uau, isso é ... apenas ... o mal: DI deveria saber que Luis estaria envolvido. Vou reverter para o código original e usá-lo ansna amostra. Obrigado novamente!
copo
5

Pyth, 55

Eu sei que a resposta de @ Sok é melhor que a minha, mas desde que terminei a minha logo após ele postar, pensei que ainda iria postar. Esta foi a minha primeira vez usando Pyth, então tenho certeza que cometi alguns erros óbvios.

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

É esperado que a entrada seja r, g, b. Você pode tentar aqui .

Rhyzomatic
fonte
Não funciona para 255,165,245.
precisa saber é o seguinte
5

PowerShell, 232 226 222 161 bytes

Consulte o histórico de revisões para versões 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 garoto, vamos ver se consigo passar por isso. Desde \nconta o mesmo que ;eu deixei a linha quebra para maior clareza.

A primeira linha recebe a entrada como três $argse as armazena $r, $g, $b. Nós realmente iremos usar $bmais tarde, mas precisamos dos três para que |sortfuncione adequadamente. Isto faz$z, $y, $x o menor para o maior dos argumentos de entrada.

As próximas duas linhas são configuradas $ce $dusando várias chamadas de indexação em uma matriz para definir os números adequadamente. Trabalhando de fora para dentro, se $xé -equal a $g(ie, o verde era o maior), definimos $c=1... senão, se $xé -note qual para $b(ou seja, o azul não é o maior) $cé 0ou 3depende se o azul foi o segundo maior ... mais $c=2,. Conjuntos lógicos semelhantes$d .

Em seguida, calculamos e imprimimos a saída com o seguinte, que é apenas o algoritmo do desafio jogado um pouco.

(($c-$d)*120*(1+($x-$y)/($x-$z))/2+$d*120)
AdmBorkBork
fonte
1
Não sei o PowerShell, então me corrija se estiver errado ... Você não usa $zno cálculo$c ou $de apenas o utiliza uma vez no cálculo de saída, para se livrar $ztotalmente e substituí-lo 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}
  • Salva 21 bytes removendo () e usando variáveis ​​r, g, b.
  • Tomando o módulo 6 para converter o valor negativo e multiplicando-o por 60 para converter em graus que salvaram 2 bytes.

Exemplos:

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

Exemplo: a([255,165,245],Hue). saídasHue = 306.666666666666 .

Isso usa a seguinte fórmula:

  • Max = max(R,G,B), Min = min(R,G,B) .
  • Se Max = R, U = 0. Senão Max = G, seU = 2 . Outra coisa U = 4.
  • Se Max = R, I = Ge J = B. Caso contrário Max = G, se I = Be J = R. Mais I = Re J = G.
  • Z = U + (I - J)/(Max - Min)
  • Hueé um Zou Z + 360se Z < 0.
Fatalizar
fonte
O arredondamento é opcional.
precisa saber é o seguinte
@ jimmy23013 Atualizado, obrigado.
Fatalize 23/08/15
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

Observações:

Certamente Perl não pode vencer esse desafio com todo o golfe pitoresco. Mas me perguntei se isso era possível com apenas uma etapa de cálculo. Graças ao módulo que funcionou bem. :)

Teste:

$ 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
fonte
comparando com o valor do meio em vez do máximo raspado em alguns bytes. (== versus>)
LukStorms 28/08
1

Bytes C ++ 276

#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
fonte
Uma dica: você pode deixar a Hfunção sozinha na resposta, pois no code-golf uma função autônoma é uma resposta legítima, equivalente a um programa completo, vide meta-discussão: meta.codegolf.stackexchange.com/questions/2419/… . Isso tornará sua resposta mais competitiva (economize 100 bytes no seu caso). Você ainda deve deixar a versão "completa" do programa sob a solução para simplificar o teste.
pawel.boczarski
O segundo caso de teste 127 247 103gera um valor inválido em -120vez de 110.
pawel.boczarski
1

R, 125 bytes

Muito parecido com a solução Octave do copo. Saída em ponto flutuante.

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

Exemplos:

> 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
fonte
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

Aceita uma lista de valores. Não tenho certeza se isso pode ser quebrado ainda mais. Aqui é ungolfed:

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
fonte
0

JavaScript 108

Método 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 o método de exemplo.

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>

martelo de lobo
fonte