如何在任意像素值集合上使用ICC配置文件进行颜色转换?

7 投票
2 回答
5542 浏览
提问于 2025-04-16 03:28

我想把一组像素值从一种颜色空间转换到另一种,而这些值并不在图像文件里,比如说一串RGB/RGBA/CMYK等数据结构。

我手头有Python和PIL,不过如果需要的话,我也对其他相关环境的解决方案感兴趣。

最新的PIL对LittleCMS的支持非常好,但它只能处理PIL图像(或者旧版的pyCMS对象),无法直接处理其他类型的数据。

根据我了解的情况,LittleCMS里包含的命令行工具icctrans可以做类似的事情,但我找不到详细的文档,文档里只把它当作一个演示工具来介绍。

2 个回答

6

有两种方法。

  • 黑科技方法: 如果你想重新调整 N 个颜色结构(或者在不同的颜色空间之间转换),你可以用 PIL.Image.new() 创建一个 1x(N+2) 的图像,然后用 yourimage.load() 获取一个可以设置像素的对象。接着,把 (0,0) 到 (0, N) 的值设置成你想要的颜色。然后把 (0, N+1) 设置成白色,(0, N+2) 设置成黑色,最后用你喜欢的 ICC 文件和 PIL.ImageCms.ImageCmsTransform() 来转换(或者校正转换)这个图像。这样,你的 PIL 对象就变成了 LUT。用 image.load() 获取值就可以了,搞定。

  • 真正的极客方法: 你需要使用 Python-colormath,这个工具在颜色空间转换方面很不错,但不适合做配置文件。Colormath 不能读取 ICC 配置文件,所以你要么 a) 找个可靠的方法解析它们复杂的二进制格式,要么 b) 直接做数学运算。这个 Bruce Lindbloom 提供了所有数据的 Excel 格式,比如说 你需要的所有矩阵 来重新调整你的 LUT。他真是太棒了。我还在努力把这些数据输入到 colormath 中,所以我可能没那么厉害,因为我还在试图把这个“极客方法”变成接近生产级别的东西。

就这样。这就是我到目前为止为了解决独立的、指挥官风格的 ICC LUT 转换所做的工作。你们,真的。

7

为了在Python中使用当前的2.3版本的Little CMS,我用Python自带的h2py.py脚本把lcms2.h转换成了lcms2consts.py。这个脚本不会翻译结构体的声明,但常量的转换已经足够我们用ctypeslcms2这个动态库来进行基本的颜色转换了。

这个例子演示了如何将一种颜色从双精度的Lab格式转换为8位的sRGB格式,使用的是内置的配置文件。如果要处理文件的话,可以用cmsOpenProfileFromFile(filename, 'r')这个方法。

import ctypes
from ctypes import byref
from lcms2consts import *

lcms = ctypes.windll.lcms2

inprof = lcms.cmsCreateLab4Profile(0)
outprof = lcms.cmsCreate_sRGBProfile()
xform = lcms.cmsCreateTransform(inprof, TYPE_Lab_DBL, 
    outprof, TYPE_RGB_8,
    INTENT_PERCEPTUAL, 0)
lcms.cmsCloseProfile(inprof)
lcms.cmsCloseProfile(outprof)

DblTriplet = ctypes.c_double * 3
ByteTriplet = ctypes.c_ubyte * 3
inbuf = DblTriplet(60.1,20.2,0.5)
outbuf = ByteTriplet()
lcms.cmsDoTransform(xform, byref(inbuf), byref(outbuf), 1)
print list(outbuf)

lcms.cmsDeleteTransform(xform)

撰写回答