我们的图形艺术家以 CMYK 色彩空间 JPG 格式提供可打印的图像,该格式适用于打印。我正在将这些转换为在网络上显示。我了解“最好”的做法是将 src.jpg 转换为 sRGB 颜色空间。我已经尝试过使用命令行convert
和使用 Imagick 方法transformImageColorspace()
,发现它在我的本地机器(Fedora 32 Linux)上运行良好,但在生产服务器(CentOS 7.3 Linux)上不起作用。
我们已经让这个过程使用命令行在生产中工作了几年,convert
但我们最近加强了安全性并禁用exec
了 PHP,所以我试图通过 Imagick 绑定使相同的过程工作,但生成的图像没有t 正确显示。我不知道是否没有正确应用 ICC 颜色配置文件,或者到 sRGB 的转换出错,或者可能发生其他任何事情。
本地机:版本:ImageMagick 6.9.10-86 Q16 x86_64 2020-01-31 https://imagemagick.org
产品服务器:版本:ImageMagick 6.9.11-19 Q16 x86_64 2020-06-15 https://imagemagick.org
两台机器都显示“lcms”在Delegates (built-in)
列表中,这是一件可能会引起麻烦但看起来不错的事情。
源图像:CMYK 格式的 src.jpg,主要是灰色/白色图像。
在 Gnome 的图像查看器中加载此图像显示不正确的颜色,偏蓝色调,但我认为这是因为 Gnome 没有正确处理 CMYK。将相同的图像加载到 GIMP 中会自动将其转换为 sRGB,并正确显示灰色/白色。我的目标是生成输出文件 src_srgb.jpg,该文件在加载到 Image Viewer 时显示为灰色/白色(因此它显然是一个简单的 RGB 配置文件图像)。
源代码:
class Logger {
public function log ($str) {
echo $str . "\n";
}
}
$l = new Logger();
$master_filename_abs = 'srgb/src.jpg';
$icc_profile_file = 'AdobeRGB1998.icc';
$pathinfo = pathinfo($master_filename_abs);
// e.g. turn mickey.jpg into mickey_srgb.jpg
$preview_filename = $pathinfo['filename'] . '_srgb.' . $pathinfo['extension'];
$preview_filename_abs = $pathinfo['dirname'] . '/' . $preview_filename;
$useCmdLine = false; // use cmd line 'convert', or Imagick?
try {
if ($useCmdLine) {
$cmd = 'convert "' . $master_filename_abs . '" -verbose' .
' -profile "' . $icc_profile_file . '"' .
' -colorspace srgb' .
' -resize 800 "' . $preview_filename_abs . '" 2>&1';
$l->log('executing "' . $cmd . '"...');
exec($cmd, $output, $return_var);
$l->log("exec returned $return_var with " . count($output) . ' lines of output:' .
join("\n", $output));
} else {
$master_img = new Imagick();
$master_img->readImage($master_filename_abs);
$icc_profile_contents = file_get_contents($icc_profile_file);
$l->log('About to profileImage()...');
$r = $master_img->profileImage('icc', $icc_profile_contents);
$l->log("profileImage returned $r " . ($r == TRUE ? 'true' : 'false'));
$space = $master_img->getImageColorspace();
$l->log("Colorspace starts as $space, CMYK is " . Imagick::COLORSPACE_CMYK);
$r = $master_img->transformImageColorspace(imagick::COLORSPACE_SRGB);
$l->log("transformImageColorspace returned $r " . ($r == TRUE ? 'true' : 'false'));
$space = $master_img->getImageColorspace();
$l->log("Colorspace after conversion is $space, SRGB is " . Imagick::COLORSPACE_SRGB);
$master_img->scaleImage(800, 0);
$l->log('Saving RGB profile version to ' . $preview_filename_abs);
$master_img->writeImage($preview_filename_abs);
}
} catch (Exception $ex) {
$l->log('Caught ' . $ex);
}
先决条件:src.jpg 应该在 'srgb' 目录下,AdobeRGB1998.icc 配置文件应该在当前目录下。
如您所见,脚本中既有命令行尝试,也有 Imagick 尝试,并带有一个$useCmdLine
在它们之间切换的布尔值。
本地机器上的结果: src_srgb.jpg 已创建并且看起来没问题。颜色与 src.jpg 图像匹配。
$ /opt/remi/php71/root/bin/php imagick_srgb.php 即将 profileImage()... profileImage 返回 1 true 颜色空间开始为 13,CMYK 为 12 transformImageColorspace 返回 1 true 转换后颜色空间为 13,SRGB 为 13 保存RGB 配置文件版本为 srgb/src_srgb.jpg
identify -verbose srgb/src_srgb.jpg
显示:
Colorspace: sRGB
Type: TrueColor
...
Profiles:
Profile-8bim: 6694 bytes
Profile-exif: 4617 bytes
Profile-icc: 560 bytes
Profile-iptc: 17 bytes
unknown[2,0]:
Image Name[2,5]: Print
Profile-xmp: 16695 bytes
prod 服务器上的结果: src_srgb.jpg 已创建,但看起来偏蓝。
$ /opt/cpanel/ea-php73/root/usr/bin/php imagick_srgb.php
About to profileImage() with 1 bytes of profile data...
profileImage returned 1 true
Colorspace starts as 12, CMYK is 12
transformImageColorspace returned 1 true
Colorspace after conversion is 13, SRGB is 13
Saving RGB profile version to srgb/src_srgb.jpg
identify -verbose srgb/src_srgb.jpg
显示:
Colorspace: sRGB
Type: TrueColor
...
Profiles:
Profile-8bim: 6694 bytes
Profile-exif: 4617 bytes
Profile-iptc: 17 bytes
unknown[2,0]:
Image Name[2,5]: Print
Profile-xmp: 16695 bytes
我在配置文件列表中看到本地计算机上的“好”版本Profile-icc
,而来自 prod 的“坏”版本没有。这是否与问题的根本原因有关,如果是,我该怎么办?我相信exif
,iptc
和xmp
配置文件是元数据,可以安全地忽略此测试的目的。
通过一些试验和错误,我认为我已经按照正确的顺序进行了transformImageColorspace
andprofileImage
调用。
建议将不胜感激。
我不能分享完整的 src.jpg 但这里是裁剪的一部分(用 imagemagick 裁剪convert
以保留其颜色配置文件等)
编辑阅读PHP Imagick 不会添加 ICC 颜色配置文件我想我会展示生产服务器的 lcms 存在:
$ convert -list configure | grep DELEGATES
DELEGATES bzlib djvu mpeg fftw fontconfig freetype gslib heic jbig jng jpeg lcms lzma openexr openjp2 pango png raqm raw rsvg tiff webp wmf x xml zlib zstd
DELEGATES bzlib cairo djvu fftw fontconfig freetype gslib gvc heic jbig jng jp2 jpeg lcms ltdl lzma openexr pangocairo png ps raqm raw rsvg tiff webp wmf x xml zlib
$ rpm -qa | grep cms
lcms2-devel-2.6-3.el7.x86_64
lcms2-2.6-3.el7.x86_64
编辑 2两个系统上的 imagemagick 有点奇怪。我的本地机器在 src.jpg 上报告了一个 icc 配置文件,但对于完全相同的图像,生产没有。我尝试将我自己的附件下载为 SO.jpg 以检查,将其复制到 prod,并区分以下输出identify -verbose SO.jpg
:
$ diff so_local so_prod
1c1,2
< Image: SO.jpg
---
> Image:
> Filename: srgb/SO.jpg
12c13
< Endianess: Undefined
---
> Endianness: Undefined
83,84d83
< Profiles:
< Profile-icc: 557168 bytes
86,89c85,86
< date:create: 2020-06-17T06:14:10+00:00
< date:modify: 2020-06-17T06:14:10+00:00
< icc:copyright: Copyright 2000 Adobe Systems, Inc.
< icc:description: U.S. Web Coated (SWOP) v2
---
> date:create: 2020-06-17T06:14:59+00:00
> date:modify: 2020-06-17T06:14:59+00:00
94c91
< filename: SO.jpg
---
> filename: srgb/SO.jpg
99c96
< Pixels per second: 25.3889MB
---
> Pixels per second: 27.3785MB
102c99
< Version: ImageMagick 6.9.10-86 Q16 x86_64 2020-01-31 https://imagemagick.org
---
> Version: ImageMagick 6.9.11-19 Q16 x86_64 2020-06-15 https://imagemagick.org
这对我来说真的很臭,对imagemagick知之甚少。我将考虑在生产中降级 ImageMagick 包以匹配本地,但我们正在进入生产服务器上的白天工作时间,所以我可能无法做到。
编辑 3回顾我们的历史工作,它似乎已于 2020 年 6 月 1 日停止工作,那天我看到它ImageMagick-6.9.11.14-1.el7.remi.x86_64
已升级到ImageMagick-6.9.11.16-1.el7.remi.x86_64
(以及-libs
和-devel
包)。因此,看起来这个重大更改是在 6.9.11.14-1 和 6.9.11.16-1 之间引入的。我们从中获得它们的 remi 存储库似乎仅包含两个最新版本,6.9.11.18-1 和 6.9.11.19-1,降级到 6.9.11.18-1 并不能解决我的问题。
编辑 4可能已获得 PHP Imagick 绑定以成功进行转换。来自https://www.imagemagick.org/discourse-server/viewtopic.php?p=67114#p67114的评论“您应该在之前定义色彩空间 CMYK,应用您需要的任何操作,然后定义 RGB 色彩空间”示例convert -colorspace CMYK mona_lisa.cmyk.jpg -modulate 110 -colorspace RGB monalisa_rgb.jpg
..所以我拼命尝试(首先将配置文件设置为 null 以删除任何现有的):
$r = $master_img->profileImage('icc', null);
$r = $master_img->profileImage('icc', file_get_contents($cmyk_icc_profile_file));
$r = $master_img->profileImage('icc', file_get_contents($srgb_icc_profile_file));
$r = $master_img->transformImageColorspace(imagick::COLORSPACE_SRGB);
令我惊讶的是,在 prod 上使用我的本地版本 6.9.10-86 和旧版本 6.9.11-14 时,输出文件在 Gnome Image Viewer 和 Web 浏览器中显示正确,所以我认为这是解决了一个问题。我仍然不明白为什么最新版本的 ImageMagick 6.9.11-19 似乎不起作用,会继续使用它。
编辑 5 ImageMagick 的人接受并修复了我的错误报告 :) https://github.com/ImageMagick/ImageMagick6/issues/83