You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pillow/OpenCV粘贴图像到画布后颜色偏移,如何添加ICC profile解决?

问题描述

这是原始图像:
原始图像

这是我用Pillow打开并显示后的图像:
Pillow中打开的图像

原始图像为JPEG格式,我尝试将格式改为TIFF、PSD均无效,也试过将图像转换为RGB、RGBA、CMYK模式,未见改善。
如果对该图像直接截图后再用Pillow打开,颜色可以正常保留。
之后我尝试换用OpenCV处理,也出现了完全相同的问题,显示结果和上述异常图片一致。
正如@HansHirse在我前一个问题的评论中提到的内容提醒的那样,我验证后确认直接打开图像后立即保存时颜色可以正常保留。哪怕不调用ICC profile,直接打开保存也会输出完全一致的图像。

相关测试代码:

from PIL import Image

i = Image.open("/Users/shashwataryal/Downloads/Tom Ford Rodeo.jpeg")

# 直接打开后立即保存,颜色可以正常保留
i.save("/Users/shashwataryal/Downloads/1.jpeg")

# 但如果新建图像后粘贴原始图像,就会出现颜色过饱和的问题,和之前显示异常的结果一致
layer = Image.new('RGB', i.size, "#faf8f8")
layer.show()
layer.paste(i)
layer.show()
layer.save('/Users/shashwataryal/Downloads/1.jpeg',icc_profile=i.info.get('icc_profile'))
layer.save('/Users/shashwataryal/Downloads/2.jpeg',icc_profile=i.info.get('icc_profile'))

我的需求是将该图添加到Pillow创建的空白新图像上,后续可能还会在旁添加其他图像。目前有两个疑问:

  • 我找不到给新图像添加ICC profile的方法
  • 如果我把其他图像粘贴到这个Pillow创建的新图像上,ICC profile会对其他图像产生影响吗?

之前我的问题被标记为相关问题的重复,但该问题仅涉及打开后立即保存图像的场景,我在该场景下无任何问题,我的问题出现在将图像粘贴到大尺寸空白画布后再保存的环节。


解决方案

你遇到的问题核心是原始图像携带的是广色域ICC配置文件,Pillow新建的空白画布默认使用sRGB色域,直接粘贴时没有做色域转换,导致颜色值映射错误。你直接保存原始图像时只是原样携带了ICC配置文件,所以显示正常;但粘贴到新画布后,即使保存时传入原始ICC,画布本身的颜色值是按sRGB生成的,套上广色域ICC后就会出现过饱和的问题。

具体解决步骤:

  1. 先读取原始图像的ICC配置文件,将原始图像的颜色值转换为sRGB色域的数值,再进行粘贴操作。可以用Pillow的ImageCms模块完成色域转换:
import io
from PIL import Image, ImageCms

# 打开原始图像
img = Image.open("/Users/shashwataryal/Downloads/Tom Ford Rodeo.jpeg")
# 获取原始ICC配置
orig_icc = img.info.get("icc_profile")

if orig_icc:
    # 构建原始色域和目标sRGB色域的转换路径
    src_profile = ImageCms.ImageCmsProfile(io.BytesIO(orig_icc))
    dst_profile = ImageCms.createProfile("sRGB")
    # 转换图像颜色值到sRGB
    img_srgb = ImageCms.profileToProfile(img, src_profile, dst_profile, outputMode="RGB")
else:
    img_srgb = img.convert("RGB")

# 新建空白画布,默认就是sRGB色域
layer = Image.new('RGB', img.size, "#faf8f8")
# 粘贴已经转换为sRGB的图像
layer.paste(img_srgb)
# 保存时不需要额外指定ICC,默认sRGB所有显示设备都能正确识别
layer.save('/Users/shashwataryal/Downloads/output.jpeg')

如果运行时提示找不到ImageCms模块,需要先安装对应依赖,macOS可以用brew install littlecms2后重装Pillow即可。

  1. 关于你提到的两个疑问:
  • 给新图像添加ICC配置文件不需要在新建时操作,只需要在最终save的时候传入icc_profile参数即可,你之前的写法是对的。但要注意:如果传入的是广色域ICC,整个画布所有内容都会按照这个ICC来解析,所以必须确保画布上所有图像的颜色值都已经提前转换到对应ICC的色域,不然其他图像也会出现颜色异常。
  • 如果你要在同一个画布上放多个不同ICC的图像,建议统一把所有图像都转换为sRGB色域后再粘贴,最终保存时也用sRGB的ICC,兼容性最好,不会出现不同图像颜色偏移的问题。

内容的提问来源于stack exchange,提问作者Shashwat Aryal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.17 06:15:03