Why are CMYK colors in Pillow out of 250 instead of 100?

CMYK color values are typically set as percentages out of 100, for example CMYK(100, 0, 70, 50) makes dark green.

However it seems in Pillow one must multiply each value by 2.5 to get the same color. In the images below, the top and bottom “Hello World” text is set using the following code:

myImageDraw.text((20, 20), "Hello World", fill=(250, 0, 175, 125), font=ImageFont.truetype(montserratRegular, 300))
myImageDraw.text((20, 300), "Hello World", fill=(100, 0, 70, 50), font=ImageFont.truetype(montserratRegular, 300))

For reference I’ve included an image of the text created in a separate design program with the color set as CMYK(100, 0, 70, 50). As you can see it matches the top text created by pillow (values multiplied by 2.5), instead of 2.5.

I’m trying to figure out why Pillow uses CMYK colors as percentages of 250 instead of 100.

Hello World text in two shades of green created in Python and Pillow

Hello World text created in Adobe InDesign


CMYK traditionally uses 0-100 because it measures ink coverage percentages. But in software, that’s not super useful and doesn’t make the best use of memory.

Pillow, like a lot of color software is using 8-bit color here. This means you have values from 0 to 255 or 8-bits per channel.

Pillow’s concepts documentation here is explicit:

Each pixel uses the full range of the bit depth. So a 1-bit pixel has a range of 0-1, an 8-bit pixel has a range of 0-255 and so on.

CMYK (4×8-bit pixels, color separation)

Source: stackoverflow