Sto usando PHP Imagick
per ridimensionare le immagini in fase di esecuzione. Il sito ha una funzione di caricamento dell'immagine e non possiamo fidarci dell'utente di usare il web JPEGs
, poiché durante lo mass-import
ci sono molte 3
a 5MB
immagini, e anche alcune grandi quanto 13MB
. Ogni immagine viene trasformata in una miniatura (200x200
) e quando si passa dalla visualizzazione elenco alla visualizzazione dettagliata viene mostrata solo un'immagine, quindi le prestazioni non sono un grosso problema, anche se non è possibile lanciarlo completamente per strada. Ecco cosa stiamo facendo finora: notaPHP Imagick JPEG Optimization
$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();
laterale: Ho appena realizzato il difetto nella mia logica condizionale qui circa altezza/larghezza, in modo da ignorare che, per il momento. Elaborerò presto la domanda per riflettere i confronti delle condizioni corrette. Per coloro che non l'hanno catturato, ridimensiona tutte le immagini a 1920
di larghezza anche se si suppone che riduca l'altezza, quindi dopo la scala ridimensiona a 1080 height
.
L'immagine che ho usato per il test inizia come immagine 3MB 2398×2400
. Ridimensionandolo a 1079x1080
si ottiene un'immagine con 1.5MB
, quindi aggiungendo la compressione JPEG
alla qualità 70
si riduce a 750KB
. Utilizzando kraken.io l'immagine è stata in grado di essere compressa a poco meno di 60 KB. Ci sono altre cose che posso fare a questo script dal momento che ha bisogno di ottimizzare l'immagine in fase di runtime?
Ho letto i suggerimenti per utilizzare libjpeg, che è installato, ma non riesco a trovare alcuna documentazione su quali funzioni abilita o se c'è un modo per forzare Imagick ad usarlo in modo specifico. Non sono nemmeno sicuro che Imagick non lo stia già usando.
Edit: Soluzione
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;
}
}
60 KB per un'immagine 1079x1080 sembra abbastanza decente. Non penso che si possa ottenere molto più piccolo senza diminuire le dimensioni dei pixel o abbassare seriamente la qualità. – GolezTrol
Il problema è che non sto arrivando da nessuna parte vicino a quello con il mio script. È a ~ 750KB in questo momento, il 60KB era un confronto (ciò che lo strumento kraken.io era capace sulla stessa immagine). Non guardo a 60KB come obiettivo preciso, ma sotto i 200KB sarebbe bello. – MaKR