# From Rgb to Cmyk

Given 3 bytes or RGB as input, calculate the nearest CMYK values, and output them.

• create either a function with parameters and return value or a program that operates on stdin/stdout
• use the color profile of your choice, but provide a reference
• input may be either separate numeric values in range [0;255] or a 6 digit hex string
• output should be separate numeric values ranging either [0;1] or [0;100]
• standard code golf: no loopholes, shortest code wins
• extravagant ideas are welcome

sample data:

input             output
108,174,106       [0.3793103448275862, 0.0, 0.3908045977011494, 0.3176470588235294]
0,0,0             0,0,0,1
170,255,238       33,0,7,0
0x0088ff          1,0.4667,0,0
[250,235,215]     [0,6,14,1.96]
#123456           .7907,.3953,0,.6627

• Uncalibrated mapping is fine and probably the easiest
• No input validation required; floats are allowed (ranging from 0 to 255), but may also be rounded
• Output format should be either clearly commented or obvious; i.e.:
1. CMYK in that order
2. does not matter if percentage [0;100] or pure numbers [0;1]
• Testing should include the trivial example [0,0,0].

This site has the most digits of online tools that I could find. Does anyone know a tool that gives more than 4 digits?

• Could you give some example inputs/outputs? – Kevin Cruijssen Jun 30 '16 at 7:21
• @KevinCruijssen Just a side note, but I don't think that's how you use ±... – Leaky Nun Jun 30 '16 at 7:23
• Welcome to the site! This is a decent challenge, but it's a little bit unclear. I'm voting to close as unclear what you're asking, but if you explain the algorithm to convert them and provide some test-cases, I will retract my vote. – DJMcMayhem Jun 30 '16 at 15:18
• @KevinCruijssen In the adverb section, it says South African. It's not used that way in standard English. We use ~. – mbomb007 Jun 30 '16 at 16:24
• The close vote message is a bit misleading, because it stems from our Q&A roots, but it was indeed "put on hold as unclear what you're asking". There were a couple of requests for clarification in the comments which weren't addressed: specifically whether inputs and outputs as floats between 0 and 1 are allowed (or whether it has to be integers from 0 to 255), how the conversion actually works, and whether you could include some test cases. – Martin Ender Jul 1 '16 at 13:30

# Dyalog APL, 16 15 bytes

1-⊢(÷,255÷⍨⊢)⌈/


1 minus 1-
X divided by ÷ Y, followed by , 255 dividing 255÷⍨ Y ⊢, where
X is itself ⊢ (i.e. the list of RGB values), and
Y is the max /⌈ (of the RGB values).

TryAPL!

Credits:
∘ Formula picture by Leaky Nun.
∘ -1 byte by ngn.

• When is PPCG getting MathJax? – Neil Jun 30 '16 at 11:45
• – Adám Jun 30 '16 at 12:07
• +1 for ⍨! Nice emoticon – programmer5000 May 9 '17 at 20:47
• @programmer5000 Thank you. You'll find that one in pretty much all my code-golfs. It swaps the arguments of the function to its left. Other APL emoticons are ⍣ and ⍤. I hope we'll get ⍥ and ⍢ soon. – Adám May 9 '17 at 20:49
• @Adám ಠ would make me happy! – programmer5000 May 9 '17 at 20:52

# C#, 888685 84 bytes

(r,g,b)=>{float[]a={r,g,b,1};var j=a.Max();a[3]=j*j/255;return a.Select(x=>1-x/j);};


output for 108,174,106:

0.3793104
0
0.3908046
0.3176471


Since OP allows function I submitted only the lambda. You can find a running demo on .NetFiddle. I am not a golfer, I post for fun. Also, it is my first answer \o/. Feel free to comment any improvement :)

Kudos to Leaky Nun for the formula.

caveat: it doesn´t work for [0,0,0] (thank you Titus)

• 1.0-x/j? You surely can't do 1-x/j? – Erik the Outgolfer Jun 30 '16 at 11:18
• @EʀɪᴋᴛʜᴇGᴏʟғᴇʀ yes I can! It was a rest from an experience. The goal was to auto cast to double. I remove it. – aloisdg Jun 30 '16 at 11:20
• You don't need it for subtraction anyways. Also, you don't seem to re-use a[3], and you don't seem to specify a fixed size for a, so you can do {r,g,b} and a[3]=j*j (because, anyways, 1 * a = a). – Erik the Outgolfer Jun 30 '16 at 11:25
• @EʀɪᴋᴛʜᴇGᴏʟғᴇʀ I am reusing a with the select(). If I use a[3] like this I will out of range and throw, wont I? – aloisdg Jun 30 '16 at 11:29
• Great first answer and welcome to PPCG! If you want to display your language and bytes in a larger font like the other answers (which is usually the standard here), you can add a # in front of the line. :) – Kevin Cruijssen Jun 30 '16 at 14:15

# Python, 46 bytes

lambda*c:[1-i/max(c)for i in c]+[1-max(c)/255]


Requires input to be floats in Python 2, fairly sure it doesn't in 3.

## JavaScript (ES6), 58 51 bytes

a=>[...a.map(e=>1-e/m||1,m=Math.max(...a)),1-m/255]


Accepts an array [R, G, B] (add 7 bytes for separate parameters) and returns an array [C, M, Y, K] using the uncalibrated colour mapping.

• Are you sure with the order CYMK on your second answer? looks like CMYK to me. – Titus Jul 1 '16 at 18:09
• 2) Do you know why spreading of a mixes up its content? This is weird. 3) Have you tested [0,0,0]? No exception in ES, but looks like a division by zero. – Titus Jul 1 '16 at 18:22
• Sorry, they were both CMY, that was my fault. Now also fixed the [0,0,0] cases. – Neil Jul 1 '16 at 20:17
• 4) Try [...a,m=Math.max(...a)] in your array solution. 5) Can you golf the other one further using an array as input? Consider using a.0 etc. instead of .map. – Titus Jul 1 '16 at 20:22
• @Titus I've come up with a completely new approach now which actually prefers CMYK order and saves 7 bytes too! – Neil Jul 1 '16 at 20:38

## Mathematica, 3628 33 bytes

List@@ColorConvert[{##}/255,"CMYK"]&


After liberalization of I/O formats, golfed further: List@@#~ColorConvert~"CMYK"&

Anonymous function, that does what is asked.

The old function takes three arguments from 0 to 255 (anything beyond this range will be automatically clipped to this range) and returns an array of "CMYK" values between 0. and 1.

Example (for old function):

List @@ ColorConvert[{##}/255, "CMYK"] &[108, 174, 106]

{0.37931, 0., 0.390805, 0.320313}


Since arrays are allowed as input, 33 bytes:

List@@ColorConvert[#/255,"CMYK"]&


Of course the built-in function handles {0, 0, 0} properly and returns {0, 0, 0, 1}.

• 1) To clarify: input values must be in [0;255]. will edit the question in a minute, 2) Please test [0,0,0]. 3) Shouldn´t that be /255? – Titus Jul 1 '16 at 19:00
• @Titus you're right, its 255, can't address all issues at the moment though, I'll fix things at earliest convenience – LLlAMnYP Jul 1 '16 at 19:12
• @Titus fixed it – LLlAMnYP Jul 4 '16 at 7:07

# Pyth, 24211824 21 bytes

Life is a round trip, indeed.

=cR255Q+mc--1dK-1JeSQJQK
=cR255Q+mc-JeSQdJQ-1J
+mc-JeSQdJQ-1cJ255
+mc-JeSQd+J^T_15Q-1cJ255
+m-1?JeSQcdJ1Q-1cJ255


Test suite.

Sample input: 108,174,106

Sample output: [0.3793103448275862, 0.0, 0.3908045977011494, 0.3176470588235294]

Sample input: 0,0,0

Sample output: [0, 0, 0, 1.0]

Formula used:

Old formula: http://i.stack.imgur.com/ZtPD6.gif

Old formula: http://i.stack.imgur.com/Nqi9F.gif

• nice golfing. care for a breakdown? – Titus Sep 2 '16 at 7:30

# Bash + ImageMagick, 69 bytes

convert "xc:$1[1x1]" -colorspace cmyk txt:-|grep -o '([^)]*)'|head -1  Example: $ ./rgb2cmyk.sh "#6CAE6A"
(38%,0%,39%,32%)

$./rgb2cmyk.sh "#000000" (0%,0%,0%,100%)$ ./rgb2cmyk.sh "#AAFFEE"
(33%,0%,7%,0%)

$./rgb2cmyk.sh "#0088ff" (100%,47%,0%,0%)$ ./rgb2cmyk.sh "#FAEBD7"
(0%,6%,14%,2%)

$./rgb2cmyk.sh "#123456" (79%,40%,0%,66%)  ## Lithp, 114 bytes #R,G,B::((var J(max R G B))(if(!= 0 J)((list(- 1(/ R J))(- 1(/ G J))(- 1(/ B J))(- 1(/ J 255))))((list 0 0 0 1))))  Try it online! • Saved 6 bytes (forgot that max takes any number of arguments) I'm not quite sure this is right. The first two results with the sample data are correct, but the rest are not (see the Try it online.) Uses the implementation described nicely as follows: # SmileBASIC, 73 72 bytes INPUT R,G,B J=MAX(R,G,B)IF!J THEN?0,0,0,1 ELSE?1-R/J,1-G/J,1-B/J,1-J/255  Could be much shorter. • Did you mean to write J=MAX(R,G,B) ? – Andrakis Feb 9 '17 at 11:46 • Yes, thank you. – 12Me21 Feb 9 '17 at 15:44 # PHP 7, 123110 105 bytes Input as RGB color 100 240 75 $j=max($h=$argv);echo strtr(@(1-$h[1]/$j).",".@(1-$h[2]/$j).",".@(1-$h[3]/$j).",".(1-$j/255),["NAN"=>0]);  Outputs CMYK values as decimal in 0...1 range. Saved lots of bytes thanks to Titus. Sample usage: php -r '$j=max($h=$argv...' 100 240 75
0.58333333333333,0,0.6875,0.058823529411765

php -r '$j=max($h=$argv...' 255 255 255 0,0,0,0 php -r '$j=max($h=$argv...' 0 255 0
1,0,1,0

php -r '$j=max($h=$argv...' 0 0 0 0,0,0,1  Test online Input as HEX color #123456, 202 bytes $h=str_split(substr($argv[1],-6),2);$j=max($r=hexdec($h[0]),$g=hexdec($h[1]),$b=hexdec($h[2]));echo z($r,$j),",",z($g,$j),",",z($b,$j),",",1-$j/255;function z($c,$y){return is_nan(@($c/$y))?0:1-$c/$y;}  54 bytes for function to prevent division by zero, probably golfable or removable. Gets as input RGB color as HEX #123456 and outputs CMYK as decimal in 0...1 range. Sample usage: php -r '$h=str_split...' '#000000'
0,0,0,1

php -r '$h=str_split...' '#ffffff' 0,0,0,0 php -r '$h=str_split...' '#123456'
0.7906976744186,0.3953488372093,0,0.66274509803922

php -r '$h=str_split...' '#ffff00' 0,0,1,0  • separate numeric values means you can just take $h=$argv; and use $h[1] instead of $h[0] etc. I like the NAN trick; but doesn´t that yield warnings? strtr is probably shorter than str_replace, and NAN needs no qotation (will yield Notices, but those are not displayed in the default config). – Titus Feb 9 '17 at 15:49 • Also, please provide the PHP version this works in. It does not in PHP 7 (where 1/0 results in INF) nor in PHP 5 (1/0 => false). – Titus Feb 9 '17 at 15:53 • @Titus Thanks for the very interesting $argv array tip in command line! I added the PHP version. It works with NAN because when you use str_replace it converts implicitly the number to string so it outputs NAN, in fact if you check at this link, you will see that it outputs NAN because of str_replace("INF" instead of str_replace("NAN". I couldn't make it work using strtr. I added the @ to suppress the warnings. – Mario Feb 10 '17 at 14:19
• I found my mistake: $n/0 is INF, but 0/0 is NAN (also in PHP 7.0). You can save 4 bytes with str_replace(NAN,0,$s) or 6 bytes with strtr($s,["NAN"=>0). – Titus Feb 10 '17 at 15:08 • @Titus great thanks, I couldn't figure out how to properly use strtr(); – Mario Feb 10 '17 at 16:11 # C, 155 bytes #define C(x) 1-x/(j>0?j:1) #define F float i=0;F j;f(F r,F g,F b){j=(r>g?r:g)>b?(r>g?r:g):b;for(;i++<4;)printf("%f\n",i>1?i>2?i>3?1-j/255:C(b):C(g):C(r));}  I'm trying to figure out how it's possible golf more. ## Usage: #define C(x) 1-x/(j>0?j:1) #define F float i=0;F j;f(F r,F g,F b){j=(r>g?r:g)>b?(r>g?r:g):b;for(;i++<4;)printf("%f\n",i>1?i>2?i>3?1-j/255:C(b):C(g):C(r));} main(){ f(108,174,106); }  ### Output: 0.379310 0.000000 0.390805 0.317647  • 1) +3: mistake: function should return the result, not print it. (sorry I just saw that) 2) +4: error: i is not declared. 3) +0: error: your ternary operators seem off. shouldn´t that be i>0?i>1?i>2 – Titus Jul 1 '16 at 22:25 • but there is some golfing potential; I found -25 bytes in ANSI C, and another -19 in C99. 2 bytes are here: j>0?,17 in getting rid of the loop, and 6 in splitting up the j definition. – Titus Jul 1 '16 at 22:35 • add another +3 for the function: it returns something else than int, so a return type is required (F *). But I found another byte to golf away in C99. – Titus Jul 2 '16 at 0:24 • @Titus If I'm not mistaken, j>0?j:1 can be j+!j to achieve -3 bytes. – Albert Renshaw Feb 8 '17 at 23:52 • And I think the C macro is incorrect: 1-x/1 for j==0? I think that should be 1-(j>0?x/j:1). – Titus Feb 11 '17 at 10:34 ## Hoon, 110 bytes => rs |* a/* =+ [s=(cury sub .1) j=(roll a max)] (welp (turn a |*(* (s (min .1 (div +< j))))) (s (div j .255)))  Use the single precision floating-point library. Create a new generic function that takes a. Set s to sub curried with .1 for later, and j to folding over a with max. Map over a by dividing each element with j, finding the minimum of that and 1 to normalize NaN, then subtract 1 with s. Add 1-j/255 to the end of that list. > =f => rs |* a/* =+ [s=(cury sub .1) j=(roll a max)] (welp (turn a |*(* (s (min .1 (div +< j))))) (s (div j .255))) > (f (limo ~[.108 .174 .106])) [i=.3.7931037e-1 t=[i=.0 t=[i=.3.908046e-1 .3.1764704e-1]]] > (f (limo ~[.0 .0 .0])) [i=.0 t=[i=.0 t=[i=.0 .1]]]  • Can you provide a TiO please. – Titus Feb 11 '17 at 10:29 • @Titus: Hoon doesn't have a TiO site, unfortunately. – RenderSettings Feb 12 '17 at 2:03 # PHP, not competing I was just too tempted to post my own. RGB input, 74 bytes for(;$i++<4;)echo$i<4?($j=max($argv))?1-$argv[$i]/$j:0:1-$j/255,","[$i>3];


or 68 bytes with a trailing comma in the output: remove [$i>3]. Run with php -r '<code>' <red-value> <green-value> <blue-value>. HEX input, 100 bytes foreach($a=array_map(hexdec,str_split($argv[1],2))as$c)echo($j=max($a))?1-$c/$j:0,",";echo 1-$j/255;  Run with php -nr '<code>' RRGGBB. That approach would take 75 bytes for RGB input: replace foreach($a=array_map...as$c) with foreach($a=$argv as$c)if(\$i++).