18

If I had a RGB decimal such as 255, 165, 0, what could I do to convert this to CMYK?

For example:

>>> red, green, blue = 255, 165, 0
>>> rgb_to_cmyk(red, green, blue)
(0, 35, 100, 0)
Hairr
  • 1,088
  • 2
  • 11
  • 19

7 Answers7

26

Here's a Python port of a Javascript implementation.

RGB_SCALE = 255
CMYK_SCALE = 100


def rgb_to_cmyk(r, g, b):
    if (r, g, b) == (0, 0, 0):
        # black
        return 0, 0, 0, CMYK_SCALE

    # rgb [0,255] -> cmy [0,1]
    c = 1 - r / RGB_SCALE
    m = 1 - g / RGB_SCALE
    y = 1 - b / RGB_SCALE

    # extract out k [0, 1]
    min_cmy = min(c, m, y)
    c = (c - min_cmy) / (1 - min_cmy)
    m = (m - min_cmy) / (1 - min_cmy)
    y = (y - min_cmy) / (1 - min_cmy)
    k = min_cmy

    # rescale to the range [0,CMYK_SCALE]
    return c * CMYK_SCALE, m * CMYK_SCALE, y * CMYK_SCALE, k * CMYK_SCALE
Laurent LAPORTE
  • 21,958
  • 6
  • 58
  • 103
Mr Fooz
  • 109,094
  • 6
  • 73
  • 101
14

The accepted answer provided a nice way to go from RGB to CMYK but question title also includes

vice versa

So here's my contribution for conversion from CMYK to RGB:

def cmyk_to_rgb(c, m, y, k, cmyk_scale, rgb_scale=255):
    r = rgb_scale * (1.0 - c / float(cmyk_scale)) * (1.0 - k / float(cmyk_scale))
    g = rgb_scale * (1.0 - m / float(cmyk_scale)) * (1.0 - k / float(cmyk_scale))
    b = rgb_scale * (1.0 - y / float(cmyk_scale)) * (1.0 - k / float(cmyk_scale))
    return r, g, b

Unlike patapouf_ai's answer, this function doesn't result in negative rgb values.

Laurent LAPORTE
  • 21,958
  • 6
  • 58
  • 103
db7638
  • 410
  • 6
  • 17
11

But converting full image RGB2CMYK or vice versa is as simple as

from PIL import Image
image = Image.open(path_to_image)

if image.mode == 'CMYK':
    rgb_image = image.convert('RGB')

if image.mode == 'RGB':
    cmyk_image = image.convert('CMYK')
Temak
  • 2,929
  • 36
  • 49
8

Following up on Mr. Fooz's implementation.

There are two possible implementations of CMYK. There is the one where the proportions are with respect to white space (which is used for example in GIMP) and which is the one implemented by Mr. Fooz, but there is also another implementation of CMYK (used for example by LibreOffice) which gives the colour proportions with respect to the total colour space. And if you wish to use CMYK to model the mixing of paints or inks, than the second one might be better because colours can just be linearly added together using weights for each colour (0.5 for a half half mixture).

Here is the second version of CMYK with back conversion:

rgb_scale = 255
cmyk_scale = 100


def rgb_to_cmyk(r,g,b):
    if (r == 0) and (g == 0) and (b == 0):
        # black
        return 0, 0, 0, cmyk_scale

    # rgb [0,255] -> cmy [0,1]
    c = 1 - r / float(rgb_scale)
    m = 1 - g / float(rgb_scale)
    y = 1 - b / float(rgb_scale)

    # extract out k [0,1]
    min_cmy = min(c, m, y)
    c = (c - min_cmy) 
    m = (m - min_cmy) 
    y = (y - min_cmy) 
    k = min_cmy

    # rescale to the range [0,cmyk_scale]
    return c*cmyk_scale, m*cmyk_scale, y*cmyk_scale, k*cmyk_scale

def cmyk_to_rgb(c,m,y,k):
    """
    """
    r = rgb_scale*(1.0-(c+k)/float(cmyk_scale))
    g = rgb_scale*(1.0-(m+k)/float(cmyk_scale))
    b = rgb_scale*(1.0-(y+k)/float(cmyk_scale))
    return r,g,b
patapouf_ai
  • 17,605
  • 13
  • 92
  • 132
  • `cmyk_to_rgb` gives negative values e.g. c=100, m=100, y=100, k=100 => r=-255, g=-255, b=-255. Second, why do you need self at all? – gkcn Oct 10 '15 at 19:35
  • @gkcn thanks, indeed there shouldn't be a "self" (in my own code it's in a class, that is where there is a self, I just forgot to remove it in my copy-paste). – patapouf_ai Oct 11 '15 at 18:49
  • @gkcn c=100, m=100, y=100, k=100 is not a valid cmyk value, that is why. – patapouf_ai Oct 11 '15 at 18:49
5

Using a CMYK conversion like the one given in the accepted answer (at the time of this writing) is not accurate for most practical purposes.

CMYK is based on how four kinds of ink form colors on paper; however, color mixture of inks is considerably complex, more so than the mixture of "lights" used to form colors in the RGB color model.

As CMYK is useful, above all, when printing images, any conversion to CMYK needs to take the printing condition into account, including what printer and what paper is used for printing. An accurate conversion to CMYK for printing purposes is not trivial and requires calibrating the printer and measuring CMYK patches on a test sheet, among other things.

There is no meaning for CMYK colors that is as ubiquitous as sRGB is for RGB, as illustrated by the International Color Consortium's page of CMYK characterization data.

See also my color article on this subject.

Peter O.
  • 32,158
  • 14
  • 82
  • 96
2

For this conversion to be useful, you need a color management system, with profiles describing the RGB system and the CMYK system being converted.

http://en.wikipedia.org/wiki/CMYK_color_model#Conversion

Here is a discussion of how to solve this problem using ICC profiles:

How can one perform color transforms with ICC profiles on a set of arbitrary pixel values (not on an image data structure)?

Here is a link to pyCMS, which uses ICC color profiles to do the conversion:

http://www.cazabon.com/pyCMS/

Community
  • 1
  • 1
steveha
  • 74,789
  • 21
  • 92
  • 117
1

I tried using the back computation provided by bisounours_tronconneuse and it failed for CMYK (96 63 0 12). Result should be : like this

Converting w3schools javascript (code here) to python, the below code now returns correct results:

def cmykToRgb(c, m, y, k) :
    c=float(c)/100.0
    m=float(m)/100.0
    y=float(y)/100.0
    k=float(k)/100.0
    r = round(255.0 - ((min(1.0, c * (1.0 - k) + k)) * 255.0))
    g = round(255.0 - ((min(1.0, m * (1.0 - k) + k)) * 255.0))
    b = round(255.0 - ((min(1.0, y * (1.0 - k) + k)) * 255.0))
    return (r,g,b)
JimT
  • 113
  • 6