颜色的色调


23

您将获得颜色的RGB值。您的任务很简单:以最简单的定义计算色相。

假设具有最高,中间和最低值的通道是X,Y,Z(分别是红色,绿色或蓝色),其值分别是x,y,z。此颜色的色相为(h(X)-h(Y))*(1 +(xy)/(xz))/ 2 + h(Y),其中:

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

输入由3个从0到255的整数组成,这些整数不完全相等(以任何一致的顺序)。输出可以是浮点数,也可以是向上或向下取整的整数,而不必保持一致。如果输出的整数部分为0或360,则可以打印其中一个。

您不能为颜色空间转换(包括诸如在处理图像时进行隐式转换)调用内置函数。

这是代码高尔夫球。最短的代码胜出。

例子

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)

编辑

您不必遵循确切的公式,而只需给出与上述公式相同的结果。我也希望看到一些有关公式本身的答案。


我们是否应该首先从sRGB转换为线性比例?我认为我们应该这样做,但是到目前为止,似乎没人能做到。
约翰·德沃夏克

@JanDvorak的任务是以最简单的定义计算色相。在这种情况下,“最简单”意味着您应该假设输入已经在正确的范围内,并使用问题中给出的确切公式或给出相同结果的任何东西。
jimmy23013

但是... 24 bpp通常表示sRGB。如果不是,则格式说明(您)应该另外指定。
约翰·德沃夏克

@JanDvorak您应该将此定义用于RGB和色相。
jimmy23013 2015年

9
必须说:色调。
TheDoctor 2015年

Answers:


6

Pyth,27个字节

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

示范。 测试线束。

Fomula摘自Wikipedia

本质上,这些步骤是:

  1. .<QJxQKeSQ:将最大值放在列表的最前面。
  2. -Ft:取其他两个值的差。
  3. -KhSQ:从最大值中减去最小值。
  4. c:将2除以3。
  5. + ... yJ 将列表中最大值的索引加倍(如果R,则为0,如果G,则为2,如果B,则为4)。
  6. % ... 6:Mod 6,以解决底片问题。
  7. *60:乘以60以转换为度数,然后打印。

9

C#,188个 210 206 197 191字节

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

感谢Sok保存4个字节,感谢SLuck49保存15个字节!


由于z在输出计算中只使用一次,并且在前面的计算中不使用它,因此您无需使用变量,而是将输出更改为return(int)((c-d)*(1+(x-y)/(double)(x-a[0]))/2+d);,从而节省了4个字节。
2015年

您可以从cd分配中将120 分解为这样的返回值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)/(double)(x-a[0]))/2+d*120);保存4个字节。
SLuck49

您还真的需要强制转换double吗?如果您这样做,则可以使用它(x-a[0])*1D来节省另外5个字节。
SLuck49

@ SLuck49谢谢!是的,我实际上需要强制转换,否则它会给出不正确的结果,但是*1D乘法是一个很好的技巧!
ProgramFOX

同样(仅注意),您可以通过完全限定System.Array另外6个字节来放弃所有使用。
SLuck49

8

Pyth, 41 55 53 51字节

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

预计输入形式为r,g,b。这是一个解释:

                                                        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)

由于@Jakube和@isaacg,节省了4个字节


@ jimmy23013固定,感谢您的额外测试用例
Sok

1
参加几次高尔夫球:m*120d-> *L120保存eeJK内联以保存另一个字节。
isaacg 2015年

@isaacg我不知道L运算符会自动在int上生成一个范围,每天似乎都是很酷的一天:o)谢谢!
2015年

8

使用Javascript(ES6),145 115 108 100 97 90个字节

返回浮点数。分配给要使用的功能。

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

通过将所有内容内联到单个三元运算符序列中并等待到最后归一化为0-360,从而节省了30个字节。

感谢edc65,Vasu Adari和ETHproductions节省了更多的字节。

JSFiddle与测试。在Firefox中尝试。

如果删除函数声明h=不合法,请添加2个字节。


您可以删除“ var”和一些字节。
Vasu Adari

ES6Fiddle由于某种原因需要var声明,直到我在firefox中尝试了ES6才意识到这是没有必要的
DankMemes

1
您可以通过以下方式保存6个字节:将花括号替换为括号,将分号替换为逗号,然后删除return。我相信去除函数声明(h=)也是合法的,总数下降到100
ETHproductions

这可能是很强迫的(然后,不是所有的好高尔夫球手吗?;)),但是通过去除括号%6)*60和另一端的括号,您可以节省两个字节。另外,对加法使用蛮力(而不是在末尾加6)实际上会比当前设置节省一个字节。(((x==r?(g-b)/m:x==g?2+(b-r)/m:4+(r-g)/m)+6)%6)*60会变成(x==r?6+(g-b)/m:x==g?8+(b-r)/m:10+(r-g)/m)%6*60
ETHproductions'Aug

1
+1排序,非常聪明,这是90(或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

八度,65 60 50字节

编辑:由于pawel.boczarski保存了10个字节

一个大概的解决方案...

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

测试运行

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

八度,107字节

我原来的(精确的)解决方案...

码:

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

解释:

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

此函数将包含R,G,B值的向量作为输入,c并按升序对输入进行排序

  • b 包含排序后的值[z,y,x]
  • i 包含与b中每个值关联的RGB平面

该向量h填充了值

  • 60*[6, 2, 4]= [360, 120, 240](但短3个字节)
  • 除非最小值在Blue(i(1) == 3)中,否则第一个色相值为零
  • 然后使用(i)重新排列h[h(Z), h(Y), h(X)]

从那里开始,只是公式的直接转录。您可以在这里尝试。


提示:使用匿名函数表示法压缩更多字节:@(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360)比带有function关键字的定义短十个字节。
pawel.boczarski

@ pawel.boczarski我想知道是否可以完全取消函数头,但是我不知道这是否合法。但是谢谢你的提示!:D
烧杯

@ pawel.boczarski回望这一点,我仍然需要r=在匿名函数之前对其进行调用,对吗?
烧杯

有许多发布匿名功能的解决方案。而且,您甚至可以像这样调用这样定义的函数:(@(c)mod(atan2d(.866*c*[0;1;-1],c*[2;-1;-1]/2),360))([127 247 103]),或者争辩说您可以ans在定义匿名函数之后立即使用变量,这样就不必为完成函数定义进行赋值。在一个挑战中(codegolf.stackexchange.com/questions/54945),将现有Matlab库函数的句柄发布为完整解决方案。
pawel.boczarski

@ pawel.boczarski哇,那...只是...邪恶:DI应该知道路易斯会参与其中。我将还原为原始代码并ans在示例中使用。再次感谢!
烧杯

5

佩斯,55

我知道@Sok的答案胜过我,但是由于我在他/她发布后才完成我的发布,所以我认为我仍然会发布。这是我第一次使用Pyth,所以我确定我犯了一些明显的错误。

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

预计输入为r, g, b。您可以在这里尝试。


不适用于255,165,245
jimmy23013 2015年

5

PowerShell中,232 226 222 161个字节

查看以前版本的修订历史

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

嗨,男孩,让我们看看我是否可以解决这个问题。由于\n计数与;我离开时相同,因此为了清楚起见,将换行。

第一行将输入作为三输入$args并将其存储到中$r, $g, $b。我们实际上只会在$b以后使用,但是我们需要所有这三者,以便|sort适当地进行工作。这将使$z, $y, $x输入参数最小到最大。

接下来的两行设置$c$d通过使用多个数组索引来适当地设置数字。从外部的工作,如果$x-eqUAL到$g(即,绿色是最大的),我们设置$c=1...否则,如果$x-nOT eQUAL到$b(即,蓝色是不是最大的),$c要么0还是3取决于如果蓝色是第二大......别的,$c=2。相似的逻辑集$d

然后,我们使用以下代码计算并打印输出,这只是挑战赛的算法。

(($c-$d)*120*(1+($x-$y)/($x-$z))/2+$d*120)

1
我不了解PowerShell,如果我错了,请纠正我...您$z在计算$c或时不$d使用它,并且在输出计算中仅使用了一次,因此可以$z完全摆脱掉并替换为$a[0]吗?
2015年

4

Ruby,117 96 94字节

码:

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}
  • 通过删除()和使用r,g,b变量节省了21个字节。
  • 以6的模数转换负值,然后乘以60转换为节省2个字节的度数。

例子:

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

3

SWI-Prolog,133个字节

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

示例:a([255,165,245],Hue).输出Hue = 306.666666666666 .

这使用以下公式:

  • Max = max(R,G,B)Min = min(R,G,B)
  • 如果Max = RU = 0。否则Max = GU = 2。别的U = 4
  • 如果Max = RI = GJ = B。否则Max = GI = BJ = R。其他I = RJ = G
  • Z = U + (I - J)/(Max - Min)
  • HueZZ + 360是否Z < 0

舍入是可选的。
jimmy23013

@ jimmy23013更新,谢谢。
致命

3

Perl 5 138个 132 119字节

码:

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

备注:

当然,Perl在所有Pyth'oresque高尔夫比赛中都无法赢得这样的挑战。但是我想知道是否只有1个计算步骤就能做到这一点。得益于很好的模数。:)

测试:

$ 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

与中间值进行比较,而不是将最大值减少了一些字节。(== vs>)
LukStorms

1

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

提示:您可以H在答案中保留函数,因为在代码高尔夫球中,独立函数是合法答案,等效于完整的程序,请参见元讨论:meta.codegolf.stackexchange.com/questions/2419/…。这将使您的答案更具竞争力(在您的情况下,节省100个字节)。仍然鼓励您将解决方案的“完整”版本留在解决方案下,以简化测试。
pawel.boczarski

第二个测试用例127 247 103产生无效值,-120而不是110
pawel.boczarski

1

R,125个字节

与烧杯的Octave解决方案非常相似。浮点输出。

码:

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

例子:

> 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

1

Python,154个字节

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

接受值列表。不知道是否可以进一步分解。这里是无高尔夫球的:

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

0

JavaScript的108

替代方法。

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

使用示例方法。

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>

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.