Convert JPG from AdobeRGB to sRGB using PIL?

后端 未结 3 1506
佛祖请我去吃肉
佛祖请我去吃肉 2021-02-13 19:15

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.

相关标签:
3条回答
  • 2021-02-13 20:03

    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.

    0 讨论(0)
  • 2021-02-13 20:09

    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
    
    0 讨论(0)
  • 2021-02-13 20:20

    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.

    0 讨论(0)
提交回复
热议问题