Почему преобразование изображения CMYK в sRGB для отображения в Интернете работает локально, а не на prod-сервере? - PullRequest
0 голосов
/ 17 июня 2020

Наш графический 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) enter image description here

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

...