Python PIL-在裁剪、缩放和保存时将颜色配置更改为未标记的RGB

Python PIL-在裁剪、缩放和保存时将颜色配置更改为未标记的RGB,python,Python,无法理解为什么要使用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)

无法理解为什么要使用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保存与原始图像具有相同颜色配置文件的缩放版本


编辑:根据这一点,这应该是可能的,但仍然不适用于我使用PIL 1.1.7更新:忽略此答案,这是正确的答案。事实证明,
load
没有进行任何转换,ICC配置文件只是保存在其他地方


我认为这两种操作都不会改变颜色配置文件,但转换是在
load
上正确完成的。使用最新版本的PIL(Windows XP上的1.1.7)打开后,它会立即转换为RGB:

>>> from PIL import Image
>>> Image.open('Flower-sRGB.jpg')
<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=600x450 at 0xD3D3F0>
尝试将结果图像转换回sRGB无效:

>>> 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
im=Image.open('Flower-sRGB.jpg')。convert('CMYK')) >>>即时通讯 >>>im.save(“Flower CMYK.png”) >>>im=Image.open('Flower-sRGB.jpg')。convert('sRGB')) 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 文件“C:\Python27\lib\site packages\PIL\Image.py”,第702行,转换为 im=im.convert(模式,抖动) ValueError:不支持从RGB到sRGB的转换
我相信在sRGB中保存需要一些外部库,比如或。我自己还没有试过,但这里有一个(使用后一个工具)看起来很有希望。最后,这里有一个与您面临的问题大致相同的问题(在加载/保存时保持颜色配置文件的完整性),希望它能为您提供更多的提示。

PIL有一个读取icc\u配置文件的功能,还有一种使用icc\u配置文件保存的方法。因此,我所做的是打开文件以获取icc_配置文件:

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图像进行了测试。

当图像点击服务器时,图像上的颜色配置文件会发生变化,因此如果我理解正确,它不会加载。但是,在我的代码中,应该是在im=PIL.open(image)处更改颜色配置文件。@Christoffer打开后,您是否打印/记录了
im
的模式?在我的测试中(参见第一个代码片段),它立即变为
RGB
,所以我仍然认为它在加载。顺便说一句,在仔细查看代码后,首先打开
image
创建变量
im
,然后裁剪
image
本身(丢弃
im
)。是吗?不要认为sRGB本身就是一种模式,而只是RGB模式的一个版本。因此,如果你必须检查颜色配置文件,你必须记录im.info.get(“icc_配置文件”)。你是对的,我丢弃了第一个即时通讯。我不知道为什么会在那里,因为我正在修复其他人的代码。但正如您在我找到的解决方案中所看到的,我现在使用它;)你看过链接讨论的第一个回复中提到的补丁了吗?颜色配置文件保存是必要的,仅仅更新PIL版本是不够的(在我下面的回答中,我也使用了1.1.7,并且有相同的问题)。@mgibsonbr正如我所见,根据Florian Hoech在hack中的自述文件,不需要其他库。在1.1.7中,黑客应该根据
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