Я использую 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;
}
}