Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python PIL - changing colour profile to untagged RGB on crop, scale and save

Tags:

python

Can't figure out why the document profile is being changed on a crop, scale and save with PIL. Have tested with an image that had sRGB as color profile, and after it has untagged RGB.

def scale(self, image):
    images = []

    image.seek(0)

    try:
        im = PIL.open(image)
    except IOError, e:
        logger.error(unicode(e), exc_info=True)

    images.append({"file": image, "url": self.url, "size": "original"})

    for size in IMAGE_WEB_SIZES:
        d = cStringIO.StringIO()
        try:
            im = crop(image, size["width"], size["height"])
            im.save(d, "JPEG")
            images.append({"file": d, "url": self.scale_url(size["name"]), "size": size})
        except IOError, e:
            logger.error(unicode(e), exc_info=True)
            pass

    return images

I am trying to get PIL to save the scaled version with the same colour profile that the original image has.

EDIT: According to this it should be possible http://comments.gmane.org/gmane.comp.python.image/3215, but still not working for me using PIL 1.1.7

like image 388
Christoffer Avatar asked Dec 02 '12 19:12

Christoffer


2 Answers

PIL has a function to read the icc_profile and also a way to save with icc_profile. So what I did was to open the file to get the icc_profile:

try:
    im1 = PIL.open(image)
    icc_profile = im1.info.get("icc_profile")

And the add it to the file again on save:

im.save(d, "JPEG", icc_profile=icc_profile)

And the full code:

def scale(self, image):
    images = []

    image.seek(0)

    try:
        im1 = PIL.open(image)
        icc_profile = im1.info.get("icc_profile")
    except IOError, e:
        logger.error(unicode(e), exc_info=True)

    images.append({"file": image, "url": self.url, "size": "original"})

    for size in IMAGE_WEB_SIZES:
        d = cStringIO.StringIO()
        try:
            im = crop(image, size["width"], size["height"])

            im.save(d, "JPEG", icc_profile=icc_profile)
            images.append({"file": d, "url": self.scale_url(size["name"]), "size": size})
        except IOError, e:
            logger.error(unicode(e), exc_info=True)
            pass

    return images

I have tested with both tagged (with icc profile) and untagged jpeg images.

like image 139
Christoffer Avatar answered Nov 20 '22 11:11

Christoffer


Update: Disregard this answer, @Christoffer's answer is the correct one. As it turns out, load was not making any conversions, the ICC profile was just being saved somewhere else.


I don't think either of these operations are changing the color profile, but the conversion is being done right on load. After opening this sample image using a recent version of PIL (1.1.7 on Windows XP), it is immediatly converted to RGB:

>>> from PIL import Image
>>> Image.open('Flower-sRGB.jpg')
<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=600x450 at 0xD3D3F0>

If I try to save it back the way it is (without changing anything), some quality is lost. If I use a lossless format OTOH, the resulting image looks fine to me:

>>> im = Image.open('Flower-sRGB.jpg')
>>> im.save("Flower-RBG.jpg")
>>> im.save("Flower-RBG.png")

Trying to convert the resulting image back to sRGB didn't work:

>>> im = Image.open('Flower-sRGB.jpg').convert('CMYK')
>>> im
<PIL.Image.Image image mode=CMYK size=600x450 at 0xD73F08>
>>> im.save("Flower-CMYK.png")

>>> im = Image.open('Flower-sRGB.jpg').convert('sRGB')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python27\lib\site-packages\PIL\Image.py", line 702, in convert
    im = im.convert(mode, dither)
ValueError: conversion from RGB to sRGB not supported

I believe saving in sRGB would require some external library, like pyCMS or LittleCMS. I haven't tried them myself, but here's a tutorial (using the latter tool) that looks promising. Finally, here's a discussion thread about the same problem you're facing (keeping the color profile intact when loading/saving), hopefully it can give you some more pointers.

like image 21
mgibsonbr Avatar answered Nov 20 '22 10:11

mgibsonbr