18

无法弄清楚为什么使用 PIL 在裁剪、缩放和保存时更改文档配置文件。已经使用具有 sRGB 作为颜色配置文件的图像进行了测试,并且在它具有未标记的 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

我试图让 PIL 使用与原始图像相同的颜色配置文件保存缩放版本。

编辑:据此它应该是可能的http://comments.gmane.org/gmane.comp.python.image/3215,但仍然不适合我使用 PIL 1.1.7

4

2 回答 2

23

PIL 具有读取 icc_profile 的功能以及使用 icc_profile 保存的方法。所以我所做的是打开文件以获取 icc_profile:

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

并在保存时再次将其添加到文件中:

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

以及完整的代码:

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

我已经使用标记(带有 icc 配置文件)和未标记的 jpeg 图像进行了测试。

于 2013-01-26T13:12:46.743 回答
6

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.

于 2012-12-21T03:09:24.033 回答