Наш графический c художник доставляет изображение, готовое к печати, в формате JPG с цветовым пространством CMYK, который подходит для печати. Я конвертирую их для отображения в Интернете. Я понимаю, что «лучше всего» преобразовать sr c .jpg в цветовое пространство sRGB. Я пробовал как командную строку с использованием convert
, так и подход Imagick с использованием transformImageColorspace()
, и обнаружил, что он отлично работает на моем локальном компьютере (Fedora 32 Linux), но не работает на производственном сервере (CentOS 7.3 Linux) .
У нас этот процесс работал в течение нескольких лет на производстве с использованием командной строки convert
, но недавно мы усилили безопасность и отключили exec
из PHP, поэтому я пытаюсь сделать тот же процесс работает через привязки Imagick, но результирующее изображение отображается некорректно. Я не знаю, правильно ли применяется цветовой профиль I CC, происходит ли преобразование в sRGB или что-то еще.
Локальный компьютер: Версия: ImageMagick 6.9. 10-86 Q16 x86_64 2020-01-31 https://imagemagick.org
Prod server: Версия: ImageMagick 6.9.11-19 Q16 x86_64 2020-06-15 https://imagemagick.org
Обе машины показывают, что «lcms» находится в списке Delegates (built-in)
, что может вызвать проблемы, но выглядит нормально.
Исходное изображение: sr c .jpg в Формат CMYK, в основном серое / белое изображение.
Загрузка этого изображения в программу просмотра изображений Gnome показывает неправильные цвета, синий sh оттенок, но я думаю, это потому, что 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);
}
Предварительные требования: sr c .jpg должен находиться в каталоге 'srgb', а профиль AdobeRGB1998.i cc должен находиться в текущем каталоге.
Как вы можете видеть, есть как попытка командной строки, так и Попытка Imagick в сценарии с логическим значением $useCmdLine
, которое переключает между ними.
Результат на локальном компьютере: src_srgb.jpg создан и выглядит нормально. Цвета соответствуют изображению sr c .jpg.
$ / opt / remi / php71 / root / bin / php imagick_srgb. php Информация о profileImage () ... profileImage вернул 1 истинное цветовое пространство начинается с 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 создан, но выглядит синим i sh.
$ /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 - нет. Может ли это быть связано с root причиной проблемы, и если да, что я могу с этим поделать? Я считаю, что профили exif
, iptc
и xmp
являются метаданными и могут быть проигнорированы для целей этого теста.
После небольшого проб и ошибок я думаю, что получил transformImageColorspace
и profileImage
звонки в правильном порядке.
Совет будет очень признателен.
Я не могу поделиться полным sr c .jpg, но вот его обрезанная часть (обрезанная с imagemagick convert
, чтобы сохранить свой цветовой профиль et c)
Edit Reading PHP Imagick не будет добавлять цветовой профиль I CC Я думал, что продемонстрирую наличие 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
Edit 2 Есть что-то странное в imagemagick на двух системах. Моя локальная машина сообщает о профиле i cc на sr c .jpg, но производство не делает этого для точно такого же изображения. Я попытался загрузить свое собственное приложение к этому сообщению как 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 наши исторические задания, похоже, перестали работать 1 июня 2020 года, и в тот день я вижу, что 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);
К моему большому удивлению, с моей локальной версией 6.9.10-86 и старой версией 6.9.11-14 на prod выходной файл отображается правильно в программе просмотра изображений Gnome и в веб-браузере, поэтому я думаю, что это одна проблема решена. Я до сих пор не понял, почему последняя версия ImageMagick 6.9.11-19 не работает, буду продолжать.
Edit 5 Ребята из ImageMagick приняли и исправили мой отчет об ошибке :) https://github.com/ImageMagick/ImageMagick6/issues/83