使用PIL将AdobeRGB格式的JPG转换为sRGB格式?

14

如何检测JPG是否是AdobeRGB格式,如果是,则在Python中将其转换为sRGB JPG。

如果使用PIL可以实现的话,那就太好了。谢谢。


请查看以下问题:在Linux上将JPEG色彩空间(Adobe RGB到sRGB)转换 —— 上次链接出了点问题,很抱歉。 - martineau
你还对获得更好的答案感兴趣吗? - martineau
当然。你想到更好的方法了吗? - miki725
不完全是,但我可以通过让答案更具体来改进它 - 如果这是您正在寻找的,因为到目前为止您还没有接受答案。 - martineau
3个回答

11

我也遇到了同样的问题,测试了所有答案,但最终图片的颜色都是错误的。@DrMeers 我尝试了所有矩阵,但红色和黑色的结果都不对,所以这是我的解决方案:

我找到的唯一方法是从图像中读取配置文件,然后使用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.

我认为这种方法可以用于任何颜色配置文件,但未经测试。


使用 io.BytesIO() 而不是保存和从文件系统加载。 - Gringo Suave

6
感谢martineau的规范链接,我已经编写了一些工作PIL代码,其中包含检测图像中Adobe RGB ICC配置文件存在的功能,并将色彩空间转换为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:                             
# https://dev59.com/mmYr5IYBdhLWcg3wcJx0#14537273                                              
# icc_profile = image.info.get("icc_profile")                                             
# image.save(destination, "JPEG", icc_profile=icc_profile)

我使用这些内容创建了一个Djangoeasy-thumbnails处理函数:

def preserve_adobe_rgb(image, **kwargs):
    if is_adobe_rgb(image):
        return adobe_to_srgb(image)
    return image

1
是的,您可以将矩阵合并并在单个“convert”操作中完成。 - DrMeers

5
要自行编程,您可以将AdobeRGB色彩空间中的像素转换为CIE XYZ,然后将其转换为sRGB。PIL image 对象有一个名为convert()的方法,可以将通用矩阵变换应用于图像中的所有像素(请参见 PIL Image 模块的在线文档中关于 Image.convert() 的部分--注意示例中显示从RGB到XYZ所需的矩阵值)。
AdobeRGB1998 .pdf 规范中的第4.3.4节展示了将XYZ转换为RGB的矩阵。
我不确定如何检测JPG图像的颜色空间。我记得读过一个关于在文件末尾附加ICC xml配置文件的问题(当存在多个时会出现问题),但我不能保证其有效性。维基百科关于JPEG文件格式的文章说嵌入了配置文件。

@miki725:如果您采用这种方法,请注意两个矩阵变换可以合并,从而允许在一步(一个im.convert()调用)中完成转换。请参阅维基百科文章以获取有关将矩阵相乘的更多信息。 - martineau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接