Der Farbton einer Farbe

23

Sie erhalten die RGB-Werte einer Farbe. Ihre Aufgabe ist einfach: in der einfachsten Definition den Farbton zu berechnen.

Angenommen, die Kanäle mit dem höchsten, mittleren und niedrigsten Wert sind X, Y, Z (entweder rot, grün oder blau) und ihre Werte sind x, y, z. Der Farbton dieser Farbe ist (h (X) -h (Y)) * (1 + (xy) / (xz)) / 2 + h (Y), wobei:

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

Die Eingabe besteht aus 3 Ganzzahlen von 0 bis 255, die in einer konsistenten Reihenfolge nicht alle gleich sind. Die Ausgabe kann floaten oder ganze Zahlen sein, die entweder auf- oder abgerundet werden, was nicht konsistent sein muss. Wenn der ganzzahlige Teil der Ausgabe 0 oder 360 ist, können Sie einen von ihnen drucken.

Sie können keine integrierten Funktionen für Farbraumkonvertierungen aufrufen, einschließlich impliziter Konvertierungen, z. B. während Sie ein Bild bearbeiten.

Das ist Code-Golf. Kürzester Code gewinnt.

Beispiele

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)

Bearbeiten

Sie müssen nicht die exakte Formel befolgen, sondern müssen nur das gleiche Ergebnis wie die obige Formel liefern. Ich möchte auch einige Antworten sehen, die die Formel selbst Golf spielen.

jimmy23013
quelle
Sollten wir zuerst von sRGB in eine lineare Skala konvertieren? Ich denke, wir sollten, aber bisher scheint es niemand zu geben.
John Dvorak
@JanDvorak Die Aufgabe besteht darin, den Farbton in der einfachsten Definition zu berechnen . In diesem Fall bedeutet "am einfachsten", dass Sie davon ausgehen sollten, dass sich die Eingabe bereits in der richtigen Skala befindet, und die in der Frage angegebene exakte Formel verwenden oder alles, was zum gleichen Ergebnis führt.
Jimmy23013
Aber ... 24 bpp bedeutet normalerweise sRGB. Andernfalls sollte die Formatspezifikation (Sie) etwas anderes angeben.
John Dvorak
@JanDvorak Sie sollten diese Definition für RGB und den Farbton verwenden.
Jimmy23013
9
Es muss gesagt werden: huehuehue.
TheDoctor

Antworten:

6

Pyth, 27 Bytes

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

Demonstration. Kabelbaum testen.

Fomula aus Wikipedia .

Im Wesentlichen sind die Schritte:

  1. .<QJxQKeSQ: Bringe den größten Wert an den Anfang der Liste.
  2. -Ft: Nehmen Sie die Differenz der beiden anderen Werte.
  3. -KhSQ: Den Minimalwert vom Maximalwert abziehen.
  4. c: 2 durch 3 teilen.
  5. + ... yJ Addieren Sie den doppelten Index des Maximalwerts in der Liste (0, wenn R, 2, wenn G, 4, wenn B).
  6. % ... 6: Mod 6, um Probleme mit Negativen zu beheben.
  7. *60: Mit 60 multiplizieren, um in Grad umzurechnen und zu drucken.
isaacg
quelle
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);}

Danke an Sok für das Speichern von 4 Bytes und an SLuck49 für das Speichern von 15!

ProgramFOX
quelle
Da Sie zdie Ausgabeberechnung nur einmal verwenden und in den vorhergehenden Berechnungen nicht verwenden, können Sie die Variable entfernen und die Ausgabe in ändern return(int)((c-d)*(1+(x-y)/(double)(x-a[0]))/2+d);, wodurch Sie 4 Byte sparen.
Sok
Sie können 120 aus dem Faktor cund dZuweisungen und in die Rückgabe wie diese c=x==g?1:(x==b?2:(y==b?3:0)),d=y==g?1:(y==b?2:(x==b?3:0))und dann return(int)((c-d)*120*(1+(x-y)/(double)(x-a[0]))/2+d*120);4 Byte zu speichern.
SLuck49,
Brauchen Sie die Besetzung auch wirklich dazu double? In diesem Fall können Sie stattdessen (x-a[0])*1Dweitere 5 Byte speichern.
SLuck49,
@ SLuck49 Danke! Ja, ich brauche die Besetzung tatsächlich, sonst gibt es ungenaue Ergebnisse, aber diese *1DMultiplikation ist ein netter Trick!
ProgramFOX
Außerdem können Sie (soeben bemerkt) die Verwendung von all together löschen, indem Sie sich System.Arrayfür weitere 6 Bytes qualifizieren.
SLuck49,
8

Pyth, 41 55 53 51 Bytes

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

Eingaben werden im Formular erwartet r,g,b. Hier ist eine Erklärung:

                                                        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 Bytes gespart, dank @Jakube und @isaacg

Sok
quelle
@ jimmy23013 Behoben, danke für den zusätzlichen Testfall
Sok
1
Ein paar Golf spielt: m*120d-> *L120Speichern , eeJum Kein weiteres Byte inline zu speichern.
isaacg
@isaacg Ich wusste nicht, dass der LOperator einen Bereich auf einem Int automatisch generiert, jeder Tag ist ein Shcool-Tag, wie es scheint: o) Danke!
Sok
8

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

Gibt floats zurück. Weisen Sie eine zu verwendende Funktion zu.

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

Es wurden 30 Bytes gespart, indem alles in eine einzelne ternäre Operatorsequenz eingefügt und bis zum Ende gewartet wurde, um auf 0-360 zu normalisieren.

Dank edc65, Vasu Adari und ETHproductions, die noch mehr Bytes eingespart haben.

JSFiddle mit Tests. Versuchen Sie es in Firefox.

Wenn das Entfernen der Funktionsdeklaration h=nicht zulässig ist, fügen Sie 2 Byte hinzu.

DankMemes
quelle
Sie können 'var' und einige Bytes entfernen.
Vasu Adari
ES6Fiddle benötigt die var-Deklaration aus irgendeinem Grund und mir war nicht klar, dass dies nicht notwendig war, bis ich ES6 in Firefox
ausprobierte
1
Sie können 6 Bytes sparen, indem Sie die geschweiften Klammern durch Klammern, das Semikolon durch ein Komma ersetzen und das entfernen return. Ich h=
halte
Das mag besessen sein (sind das dann auch nicht alle guten Golfer?;)), Aber Sie könnten zwei weitere Bytes sparen, indem Sie die Klammer %6)*60und den Partner auf der anderen Seite loswerden . Außerdem würde die Verwendung von Brute Force für die Addition (anstatt 6 am Ende hinzuzufügen) tatsächlich ein Byte gegenüber Ihrer aktuellen Konfiguration sparen. (((x==r?(g-b)/m:x==g?2+(b-r)/m:4+(r-g)/m)+6)%6)*60würde werden (x==r?6+(g-b)/m:x==g?8+(b-r)/m:10+(r-g)/m)%6*60.
ETHproductions
1
+1 für die Art, sehr klug, Dies ist 90 (oder 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

Oktave, 65 60 50 Bytes

Bearbeiten: 10 Bytes dank pawel.boczarski gespeichert

Eine ungefähre Lösung ...

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

Testlauf

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

Oktave, 107 Bytes

Meine ursprüngliche (exakte) Lösung ...

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

Erklärt:

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

Diese Funktion nimmt einen Vektor als Eingabe, der die R-, G- und B-Werte enthält, cund sortiert die Eingabe in aufsteigender Reihenfolge

  • b enthält die sortierten Werte [z, y, x]
  • i enthält die RGB-Ebene, die jedem Wert in b zugeordnet ist

Der Vektor hwird mit den Werten gefüllt

  • 60*[6, 2, 4]= [360, 120, 240](aber 3 Bytes kürzer)
  • Es sei denn, der niedrigste Wert ist in Blau ( i(1) == 3). In diesem Fall wird der erste Farbtonwert zu Null
  • verwenden Sie dann (i)neu zu ordnen hin [h(Z), h(Y), h(X)]Ordnung

Von dort ist es nur eine direkte Transkription der Formel. Sie können es hier ausprobieren .

Becherglas
quelle
Hinweis: Verwenden Sie die anonyme Funktionsnotation, um mehr Bytes zu komprimieren: @(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360)ist zehn Bytes kürzer als die Definition mit dem functionSchlüsselwort.
pawel.boczarski
@ pawel.boczarski Ich habe mich gefragt, ob ich den Funktionsheader überhaupt beseitigen kann, aber ich weiß nicht, ob das legitim ist. Aber danke für den Tipp! : D
Becher
@pawel.boczarski Rückblickend brauche ich noch eine r=vor der anonymen Funktion, um sie aufzurufen, oder?
Becher
Es gibt viele Lösungen, bei denen anonyme Funktionen bereitgestellt werden. Darüber hinaus können Sie die so definierte Funktion auch so aufrufen: (@(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360))([127 247 103])oder argumentieren, dass Sie die ansVariable direkt nach der Definition der anonymen Funktion verwenden können, sodass die Zuweisung nicht erforderlich ist, damit die Funktionsdefinition vollständig ist. In einer Herausforderung ( codegolf.stackexchange.com/questions/54945 ) wurde ein Handle der vorhandenen Matlab-Bibliotheksfunktion als vollständige Lösung veröffentlicht.
pawel.boczarski
@ pawel.boczarski Wow, das ist ... nur ... böse: DI hätte wissen sollen, dass Luis involviert sein würde. Ich werde auf den ursprünglichen Code zurückgreifen und ihn ansim Beispiel verwenden. Danke noch einmal!
Becher
5

Pyth, 55

Ich weiß, dass @ Soks Antwort meine übertrifft, aber da ich meine direkt nach dem Posten beendet habe, dachte ich, ich würde immer noch posten. Ich habe Pyth zum ersten Mal verwendet, daher habe ich sicher einige offensichtliche Fehler gemacht.

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

Die Eingabe wird erwartet r, g, b. Sie können es hier ausprobieren .

Rhyzomatisch
quelle
Funktioniert nicht für 255,165,245.
Jimmy23013
5

PowerShell, 232 226 222 161 Bytes

Siehe Revisionsverlauf für frühere Versionen

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

Hallo Junge, mal sehen, ob ich das durchgehen kann. Da gilt \ndas gleiche wie; Verlassen der Zeile zur Verdeutlichung ein.

Die erste Zeile nimmt die Eingabe als drei $argsund speichert sie in $r, $g, $b. Wir werden es wirklich erst $bspäter benutzen , aber wir brauchen alle drei, damit es |sortangemessen funktioniert. Dies macht $z, $y, $xdas kleinste zum größten der Eingabeargumente.

Die nächsten beiden Zeilen werden eingerichtet $cund $dmithilfe mehrerer Index-in-ein-Array-Aufrufe, um die Zahlen entsprechend festzulegen. Arbeiten von außen nach innen, wenn $xes -eqangebracht ist$g (dh grün die größte war), stellen wir $c=1... sonst, wenn $xist -not equal zu $b(dh blau war nicht der größte) $cist entweder 0oder 3je nachdem , ob blau die zweite war größte ... sonst $c=2. Ähnliche Logiksätze$d .

Wir berechnen und drucken dann die Ausgabe mit dem folgenden Wert, der nur der Algorithmus aus der Herausforderung ist, die ein wenig gespielt wurde.

(($c-$d)*120*(1+($x-$y)/($x-$z))/2+$d*120)
AdmBorkBork
quelle
1
Ich kenne PowerShell nicht. Korrigieren Sie mich, wenn ich mich irre. Sie verwenden $zbeim Berechnen nicht $coder $dund Sie verwenden es nur einmal in der Ausgabeberechnung. Können Sie es also $zvollständig entfernen und durch ersetzen $a[0]?
Sok
4

Rubin, 117 96 94 Bytes

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}
  • 21 Byte durch Entfernen ()und Verwenden der Variablen r, g, b eingespart.
  • Nehmen Sie den Modul 6, um den negativen Wert umzuwandeln, und multiplizieren Sie ihn mit 60, um ihn in Grad umzuwandeln, der 2 Bytes einspart.

Beispiele:

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

Beispiel: a([255,165,245],Hue).AusgängeHue = 306.666666666666 .

Dies verwendet die folgende Formel:

  • Max = max(R,G,B), Min = min(R,G,B).
  • Wenn Max = R, U = 0. Else , wenn Max = G, U = 2. Else U = 4.
  • Wenn Max = R, I = Gund J = B. Sonst wenn Max = G, I = Bund J = R. Sonst I = Rund J = G.
  • Z = U + (I - J)/(Max - Min)
  • Hueist entweder Zoder Z + 360wenn Z < 0.
Tödlich
quelle
Die Rundung ist optional.
Jimmy23013
@ jimmy23013 Aktualisiert, danke.
Fatalize
3

Perl 5, 138 132 119 Bytes

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

Bemerkungen:

Sicher kann Perl eine solche Herausforderung nicht mit all dem Pyth'oresque-Golfen gewinnen. Aber ich habe mich gefragt, ob dies mit nur einem Rechenschritt möglich ist. Dank des Moduls hat das gut geklappt. :)

Prüfung:

$ 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
quelle
Vergleich mit dem Mittelwert anstelle des Maximums einige Bytes rasiert. (== 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
quelle
Ein Hinweis: Sie könnten die HFunktion in der Antwort in Ruhe lassen, da in Code-Golf eine Standalone-Funktion eine legitime Antwort ist, die einem vollständigen Programm entspricht . Dies wird Ihre Antwort wettbewerbsfähiger machen (sparen Sie 100 Bytes in Ihrem Fall). Sie werden weiterhin aufgefordert, die "vollständige" Programmversion unter der Lösung zu belassen, um das Testen zu vereinfachen.
pawel.boczarski
Der zweite Testfall 127 247 103liefert einen ungültigen Wert -120anstelle von 110.
pawel.boczarski
1

R, 125 Bytes

Sehr ähnlich zu Beakers Octave-Lösung. Gleitkomma-Ausgabe.

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

Beispiele:

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

Akzeptiert eine Liste von Werten. Ich bin mir nicht sicher, ob dies weiter abgebaut werden kann. Hier ist es 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
quelle
0

JavaScript 108

Alternative Methode.

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

Verwenden Sie die Beispielmethode.

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>

Wolfhammer
quelle