я использую PHP Imagick
изменить размер изображения во время выполнения. На сайте есть функция загрузки изображений, и мы не можем доверять пользователю использование веб-страниц. JPEGs
, как во время mass-import
Здесь очень много 3
в 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 КБ. Есть ли какие-то дополнительные вещи, которые я могу сделать с этим сценарием, так как он должен оптимизировать изображение во время выполнения?
Я прочитал предложения по использованию libjpeg, который установлен, но я не могу найти никакой документации о том, какие функции он включает или есть ли способ заставить 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;
}
}
Установите для setImageCompressionQuality значение 70 и добавьте эти две строки после него.
$image->setImageFormat("jpg");
$image->stripImage();
Это значительно уменьшит размер изображений.
Других решений пока нет …