Оптимизация JPEG Imagick для PHP

Я использую PHP Imagick для изменения размера изображений во время выполнения. На сайте есть функция загрузки изображений, и мы не можем доверять пользователю использовать веб-интерфейс JPEGs, так как во время mass-import есть много изображений 3 to 5MB и даже несколько таких, как 13MB. Каждое изображение превращается в миниатюру (200x200), и при переходе от просмотра списка к подробному просмотру отображается только одно изображение, поэтому производительность не является огромной сделкой, хотя мы не можем полностью бросить ее на обочину. Вот что мы делаем до сих пор:

$iMagick = new Imagick($file);
$iMagick->setImageResolution(72,72);
$iMagick->resampleImage(72,72,imagick::FILTER_UNDEFINED,1);
$geometry = $iMagick->getImageGeometry();
if ($geometry['height'] > 1920 || $geometry['width'] > 1080) {
    $iMagick->scaleImage(1920, 0);
    if($geometry['height'] > $resizeHeight) {
        $iMagick->scaleImage(0, 1080);
    }
}
$iMagick->setImageCompression(Imagick::COMPRESSION_JPEG);
$iMagick->setImageCompressionQuality($compression);
$iMagick->writeImage($file);
$Imagick->clear();

Боковое замечание: я только что понял недостаток в моей условной логике здесь о высоте/ширине, поэтому пока игнорируйте это. Я скоро отредактирую этот вопрос, чтобы отразить правильные сравнения условий. Для тех, кто этого не понимал, он масштабирует все изображения до 1920 широкие, даже если он должен масштабировать высоту, а затем после масштабирования он уменьшает его до 1080 height.

Изображение, которое я использовал для тестирования, начинается с изображения 3MB 2398×2400. Масштабирование до 1079x1080 приводит к изображению 1.5MB, а добавление сжатия JPEG при качестве 70 сводит его к 750KB. Используя kraken.io, изображение было сжато до уровня менее 60 КБ. Есть ли какие-либо дополнительные вещи, которые я могу сделать для этого script, так как он должен оптимизировать изображение во время выполнения?

Я прочитал предложения по установке libjpeg, который установлен, но я не могу найти документацию о том, какие функции он включает, или если есть способ заставить Imagick использовать его специально. Я даже не уверен, что Imagick уже не использует его.

Изменить: Решение

function itm_optimizeImage($file, $compression = 70, $maxDimensions = ['width' => null, 'height' => null]) {
    $save = false;
    $fi = new finfo(FILEINFO_MIME);
    $mime = explode(';', $fi->file($file));
    switch ($mime[0]) {
        // possible to optimize other image types in the future
        case 'image/jpeg':
            try {
                $iMagick = new Imagick($file);
                if ($iMagick->getImageCompressionQuality() > $compression) {
                    $file = !itm_compressJPEG($file, $compression, $maxDimensions, $iMagick);
                }
            }
            catch (Exception $e) {
                error_log(__FUNCTION__ . " $path/$file failed: " . $e->getMessage());
                return false;
            }
            if ($file) {
                $pathParts = pathinfo($file);
                rename($file, $pathParts['dirname'] . '/' . $pathParts['filename'] . '.large.' . $pathParts['extension']);
                $iMagick->writeImage($file);
            }
            $iMagick->clear();
            break;
    }

    return $file;
}

function itm_compressJPEG($file, $compression = 70, $maxDimensions = ['width' => null, 'height' => null], &$iMagick = null) {
    try {
        $iMagickCreated = true;
        if ($iMagick) $iMagickCreated = false;
        else $iMagick = new Imagick($file);

        $iMagick->setImageResolution(72,72);
        $iMagick->resampleImage(72,72,imagick::FILTER_UNDEFINED,1);
        $geometry = $iMagick->getImageGeometry();
        if (($geometry['width'] / $maxDimensions['width']) > ($geometry['height'] / $maxDimensions['height'])) {
            // scale by width
            $iMagick->scaleImage($maxDimensions['width'], 0);
        } else {
            // scale by height
            $iMagick->scaleImage(0, $maxDimensions['height']);
        }
        $iMagick->setImageCompression(Imagick::COMPRESSION_JPEG);
        $iMagick->setImageCompressionQuality($compression);
        $iMagick->setImageFormat('jpg');
        $iMagick->stripImage();

        if ($iMagickCreated) {
            $pathParts = pathinfo($file);
            rename($file, $pathParts['dirname'] . '/' . $pathParts['filename'] . '.large.' . $pathParts['extension']);
            $iMagick->writeImage($file);
            $Imagick->clear();
        }
        return $file;
    }
    catch (Exception $e) {
        error_log(__FUNCTION__ . " $path/$file failed: " . $e->getMessage());
        return false;
    }
}

Ответ 1

Установите для параметра setImageCompressionQuality значение 70 и добавьте эти две строки после него.

$image->setImageFormat("jpg");
$image->stripImage();

Это значительно уменьшит размер изображений.