Инвертированные цвета после обновления Imagemagick с 6.9 до 7

#php #imagemagick

#php #imagemagick ( магия изображений)

Вопрос:

Я использую Imagick и расширение PHP Imagick в проекте для преобразования всевозможных изображений. Изображения предоставлены пользователями и будут преобразованы в миниатюры jpg заданного размера.

Это выполняется внутри docker-контейнера на основе php:7.4.12-cli . В настоящее время я использую Imagemagick 6.9.7-4 установленный из исходного кода со следующей командой:

 RUN apt-get update amp;amp; apt-get install -y libmagickwand-dev --no-install-recommends

RUN cd /usr/local/src amp;amp; 
    curl -L https://github.com/ImageMagick/ImageMagick6/archive/6.9.7-4.tar.gz --output Imagick-6.9.7-4.tar.gz amp;amp; 
    tar xvzf Imagick-6.9.7-4.tar.gz amp;amp; 
    cd ImageMagick6-6.9.7-4 amp;amp; 
    export CPPFLAGS=-I/usr/local/include amp;amp; 
    export LDFLAGS=-L/usr/local/lib amp;amp; 
    ./configure --with-module amp;amp; 
    make amp;amp; 
    make install amp;amp; 
    ldconfig /usr/local/lib amp;amp; 
    cd .. amp;amp; 
    rm -rf /usr/local/src/Imagick-6.9.7-4.tar.gz ImageMagick6-6.9.7-4
 

Чтобы преобразовать изображения, я использую следующую функцию, которая на данный момент работает без каких-либо известных проблем

 <?php
public static function resize(string $src, string $dst, int $width, $height = false, int $quality = 90) : bool {
    if ($quality <= 0 || $quality > 100) {
        throw new Exception(
            "quality is out of range. must be between 1 and 100. '".$quality."' given"
        );
    }

    // check if the source file exists
    if (!file_exists($src)) {
        throw new Exception(
            "source file '".$src."' does not exist"
        );
    }

    // check if imagemagick is installed
    if (!extension_loaded("imagick") || !class_exists("Imagick")) {
        throw new Exception(
            "Imagick Extension is not loaded"
        );
    }

    // create image
    $img = ImageHelpers::newImagick($src);

    // set backgroundcolor for transparent images and merge multiple layers to one
    $img->setBackgroundColor(new ImagickPixel("#FFFFFF"));
    $img = $img->mergeImageLayers(Imagick::LAYERMETHOD_FLATTEN);

    // auto orientation
    switch ($img->getImageOrientation()) {
        case Imagick::ORIENTATION_BOTTOMRIGHT:
            $img->rotateimage("#000", 180); // rotate 180 degrees
            break;

        case Imagick::ORIENTATION_RIGHTTOP:
            $img->rotateimage("#000", 90); // rotate 90 degrees CW
            break;

        case Imagick::ORIENTATION_LEFTBOTTOM:
            $img->rotateimage("#000", -90); // rotate 90 degrees CCW
            break;
    }

    // set new orientation in exif-data
    $img->setImageOrientation(Imagick::ORIENTATION_TOPLEFT);

    // resizes to whichever is larger, width or height
    if ($height !== false) {
        $img->thumbnailImage($width, $height, true);
    } else {
        $img->cropThumbnailImage($width, $width);
    }

    // set iterator to 0 on PSD and XCF Files
    $ending = strtolower(substr($src, -3, 3));
    if (in_array($ending, [ "psd", "xcf" ])) {
        $img->setIteratorIndex(0);
    }

    // convert image to jpg
    $img->setImageFormat("jpg");

    // colorspace transformation
    // only if imagick version is not 6.9.10-23 (1690)
    // due to bug in imagick
    // imagick generates segfault
    $imagickVersion = Imagick::getVersion();
    if ($imagickVersion['versionNumber'] ?? "" !== 1690) {
        try {
            // check if icc profiles exist
            $profiles = $img->getImageProfiles("*", false);
            $hasIccProfile = array_search("icc", $profiles) !== false;

            // fetch colorspace of the image
            $colorSpace = $img->getImageColorspace();

            // if images does not have an assigned profile and is cmyk add a default profile
            if ($hasIccProfile === false amp;amp; $colorSpace == Imagick::COLORSPACE_CMYK) {
                $img->profileImage("icc", file_get_contents(TB_PATH_ROOT."_common/icc/USWebUncoated.icc"));
            }

            // if images does not have an assigned profile and is srgb add a default profile
            if ($hasIccProfile === false amp;amp; $colorSpace == Imagick::COLORSPACE_SRGB) {
                $img->profileImage("icc", file_get_contents(TB_PATH_ROOT."_common/icc/sRGB_v4_ICC_preference.icc"));
            }

            // set the new color profile
            $img->profileImage("icc", file_get_contents(TB_PATH_ROOT."_common/icc/AdobeRGB1998.icc"));
        } catch (Exception $e) {
            // do nothing
            // thumbnail creation will still work
        }
    }

    // set image compression
    $img->setImageCompression(Imagick::COMPRESSION_JPEG);
    $img->setImageCompressionQuality($quality);

    // remove destination-file if already exists
    if (file_exists($dst) amp;amp; unlink($dst) === false) {
        throw new Exception(
            "destination file already exists but cannot be deleted"
        );
    }

    // write image
    $img->writeImage($dst);

    // clear image from memory
    $img->clear();

    // all done, image was created
    return true;
}
 

У меня есть соответствующие icc-файлы в данной папке, поэтому их можно использовать для настройки цветового профиля.

Теперь, как только я обновлюсь до Imagick 7 (7.0.10-43), у меня есть некоторые изображения, которые не были преобразованы правильно. У меня есть изображения в формате tiff, где цвета инвертированы. Даже если я удалю весь код преобразования, это все равно произойдет. Есть ли какие-либо известные изменения в Imagmagick, которые приводят к этим проблемам? Или есть какие-нибудь подсказки о том, где искать проблему?

Я разбил это, насколько это было возможно, и это также происходит со следующим кодом:

 <?php
$src = __DIR__ . "/_common/_data/persistent/images/219.tif";
$dst = __DIR__ . "/output.jpg";

$img = new Imagick($src);
$img->writeImage($dst);
 

Это работает в Imagick 6.9.7-4 , но не в Imagick 7.0.10-43 . В 7 все изображение инвертируется.

Расширение php imagick устанавливается с pecl

 RUN pecl install imagick amp;amp; docker-php-ext-enable imagick
 

С наилучшими пожеланиями, Дэвид

Комментарии:

1. Вы также должны опубликовать фрагмент простого кода, показывающий проблему, чтобы люди могли попробовать это. Кому-то очень трудно прочитать и попробовать ваш код таким, какой он есть. Вы обновили свои версии imagemagick и Imagick, поскольку они должны совпадать?

2. Привет, Бонзо. Спасибо за ваш ответ. Я изложил это так подробно, как только мог. Я использую этот код для тестов $img = new Imagick($src); $img->writeImage($dst); , в которых он работает, Imagick 6.9.7-4 но не в Imagick 7.0.10-43 нем. В 7 все изображение инвертируется. Я устанавливаю расширение php с pecl помощью . Есть ли лучший способ сделать это? Чтобы соответствовать установленной версии imagemagick? bash RUN pecl install imagick amp;amp; docker-php-ext-enable imagick