Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert JPG from AdobeRGB to sRGB using PIL?

How can I detect if the JPG is AdobeRGB and if it is convert it in python to sRGB JPG.

If that is possible in PIL, that would be great. Thank you.

like image 310
miki725 Avatar asked Jun 14 '12 20:06

miki725


3 Answers

I had the same problem, I tested all answers and get wrong color in final image. @DrMeers All matrixes I've tried gave wrong result in red and blacks, so here is my solution:

The only way I found out is to read profile from image and convert using ImageCms.

from PIL import Image
from PIL import ImageCms
import tempfile

def is_adobe_rgb(img):
    return 'Adobe RGB' in img.info.get('icc_profile', '')
def adobe_to_srgb(img):
    icc = tempfile.mkstemp(suffix='.icc')[1]
    with open(icc, 'w') as f:
        f.write(img.info.get('icc_profile'))
    srgb = ImageCms.createProfile('sRGB')
    img = ImageCms.profileToProfile(img, icc, srgb)
    return img

img = Image.open('testimage.jpg')
if is_adobe_rgb(img):
    img =  adobe_to_srgb(img)
# then do all u want with image. crop, rotate, save etc.

I think this method can be used to any color profile, but not tested.

like image 120
alekssaff Avatar answered Oct 05 '22 22:10

alekssaff


Thanks for the spec link martineau, I've put some working PIL code together with functions that detect the presence of a Adobe RGB ICC profile within an Image, and convert the colorspace to sRGB.

adobe_to_xyz = (
    0.57667, 0.18556, 0.18823, 0,
    0.29734, 0.62736, 0.07529, 0,
    0.02703, 0.07069, 0.99134, 0,
) # http://www.adobe.com/digitalimag/pdfs/AdobeRGB1998.pdf                                

xyz_to_srgb = (
    3.2406, -1.5372, -0.4986, 0,
    -0.9689, 1.8758, 0.0415, 0,
    0.0557, -0.2040, 1.0570, 0,
) # http://en.wikipedia.org/wiki/SRGB                                                     

def adobe_to_srgb(image):
    return image.convert('RGB', adobe_to_xyz).convert('RGB', xyz_to_srgb)

def is_adobe_rgb(image):
    return 'Adobe RGB' in image.info.get('icc_profile', '')

# alternative solution if happy to retain profile dependency:                             
# http://stackoverflow.com/a/14537273/284164                                              
# icc_profile = image.info.get("icc_profile")                                             
# image.save(destination, "JPEG", icc_profile=icc_profile)

(I used these to create a Django easy-thumbnails processor function):

def preserve_adobe_rgb(image, **kwargs):
    if is_adobe_rgb(image):
        return adobe_to_srgb(image)
    return image
like image 39
DrMeers Avatar answered Oct 06 '22 00:10

DrMeers


To program this yourself, you could convert pixels in the AdobeRGB colorspace to CIE XYZ, and then convert that to sRGB. PIL image objects have a method named convert() with the ability to apply a general matrix transformation to all the pixels in an image (see the section on Image.convert() in the the online documentation of the PIL Image module -- note the example showing the matrix values needed for going from RGB to XYZ).

Section 4.3.4 in the AdobeRGB1998 .pdf spec shows a matrix for transforming XYZ into RGB.

I'm not sure how to detect the colorspace of JPG images. I recall reading something about ICC xml profiles being attached to the end of the file (and a problem arising when there was more than one), but I can't vouch for its validity. The Wikipedia article on the JPEG file format says profiles are embedded.

like image 25
martineau Avatar answered Oct 05 '22 22:10

martineau