Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does PIL image.convert("RGB") convert images to sRGB or AdobeRGB?

I want to batch convert images from various modes such as RGBa, CMYK etc to sRGB using PIL in Python.

However, I am not sure and can't find it anywhere whether

image.convert("RGB") 

converts the image to sRGB or Adobe RGB. My intuition says that it converts to sRGB.

If it converts to sRGB and I pass in Adobe RGB image to the convert function, would it successfully convert to sRGB?

like image 225
Sabih Avatar asked May 31 '18 10:05

Sabih


1 Answers

By default PIL is agnostic about color spaces (like sRGB and Adobe RGB).

As you might know, RGB is simply three 8-bit values for red, green and blue. CMYK is four 8-bit values. When you use Image.convert('RGB') it just converts each pixel to the triple 8-bit value. So it fundamentally changes the mode of how image is represented and stored.

sRGB and Adobe RGB, on the other hand, are just RGB color spaces. Basically, these are rules for how to render those three values on your monitor, printer or any other physical output device. Such rules can be added to JPEG files in form of ICC profiles by such software as Photoshop, for example. But PIL normally will not attach any ICC profile when you just use Image.save.

In order to check if your image embeds ICC profile, you can look for key 'icc_profile' in dictionary image.info like this image.info.get('icc_profile', None).

In order to save JPEG images preserving ICC profile with PIL you could use something like this:

img.save('image.jpg',
         format = 'JPEG',
         quality = 100,
         icc_profile = img.info.get('icc_profile',''))

In order to convert any RGB JPEG image from its color space to sRGB, you could use this function:

import io
from PIL import Image
from PIL import ImageCms

def convert_to_srgb(img):
    '''Convert PIL image to sRGB color space (if possible)'''
    icc = img.info.get('icc_profile', '')
    if icc:
        io_handle = io.BytesIO(icc)     # virtual file
        src_profile = ImageCms.ImageCmsProfile(io_handle)
        dst_profile = ImageCms.createProfile('sRGB')
        img = ImageCms.profileToProfile(img, src_profile, dst_profile)
    return img

So your code for conversion to single RGB color space might look like:

img = Image.open('image_AdobeRGB.jpg')
img_conv = convert_to_srgb(img)
if img.info.get('icc_profile', '') != img_conv.info.get('icc_profile', ''):
    # ICC profile was changed -> save converted file
    img_conv.save('image_sRGB.jpg',
                  format = 'JPEG',
                  quality = 100,
                  icc_profile = img_conv.info.get('icc_profile',''))

NOTE: you might want to use slightly lower quality than 100.

Example input (Adobe RGB JPEG):

Adobe RGB JPG

Example output (sRGB JPEG):

sRGB JPG

like image 82
Andriy Makukha Avatar answered Oct 10 '22 01:10

Andriy Makukha