Ich verwende PHP Imagick
, um Bilder zur Laufzeit zu skalieren. Die Website verfügt über eine Funktion zum Hochladen von Bildern, und wir können nicht darauf vertrauen, dass der Benutzer webfreundliche JPEGs
verwendet, da während der mass-import
viele 5MB
bis 5MB
Bilder und sogar ein paar so groß wie 13MB
sind. Jedes Bild wird zu einem Thumbnail (200x200
), und wenn von der Listenansicht in die Detailansicht gewechselt wird, wird nur ein Bild angezeigt, so dass die Leistung keine große Sache ist, obwohl wir sie nicht vollständig wegwerfen können. Hier ist, was wir tun, so weit:PHP Imagick JPEG Optimierung
$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();
Randbemerkung: Ich habe erkannt, den Fehler in meiner bedingte Logik hier etwa Höhe/Breite, so ignorieren, dass für den Augenblick. Ich werde die Frage bald bearbeiten, um die korrekten Zustandsvergleiche zu berücksichtigen. Für diejenigen, die es nicht gefangen haben, skaliert es alle Bilder auf 1920
weit, auch wenn es die Höhe skalieren soll, dann nach der Skalierung wird es wieder auf 1080 height
verkleinert.
Das Bild, das ich zum Testen verwendet habe, beginnt als 3MB 2398×2400
Bild. Skalierung auf 1079x1080
ergibt ein 1.5MB
Bild, dann JPEG
Kompression bei Qualität 70
bringt es auf 750KB
. Mit kraken.io konnte das Image auf knapp 60KB komprimiert werden. Gibt es weitere Dinge, die ich mit diesem Skript tun kann, da es zur Laufzeit das Bild optimieren muss?
Ich habe Vorschläge gelesen, libjpeg zu verwenden, die installiert ist, aber ich kann keine Dokumentation finden, welche Funktionen es aktiviert, oder ob es eine Möglichkeit gibt, Imagick zu zwingen, es spezifisch zu verwenden. Ich bin mir nicht einmal sicher, ob Imagick es schon benutzt.
Edit: Lösung
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;
}
}
60KB für ein 1079x1080 Bild scheint ziemlich anständig. Ich glaube nicht, dass Sie es viel kleiner machen können, ohne die Pixelabmessungen zu verkleinern oder die Qualität ernsthaft zu senken. – GolezTrol
Das Problem ist, dass ich mit meinem Skript nicht annähernd so weit komme. Es ist bei ~ 750KB im Moment, die 60KB war ein Vergleich (was das kraken.io Tool auf dem gleichen Bild konnte). Ich sehe 60KB nicht als genaues Ziel, aber unter 200KB wäre nett. – MaKR