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
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With