How can I convert RGB to CMYK and vice versa in python?

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

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

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

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.

Tags:

Python

Colors