Używam do zmiany rozmiaru zdjęć w czasie wykonywania. Witryna ma funkcję przesyłania obrazów i nie możemy ufać, że użytkownik może korzystać z funkcji przyjaznej dla WWW. Jest to JPEGs
, ponieważ w przypadku mass-import
istnieje wiele obrazów 3
do 5MB
, a nawet kilka tak dużych jak 13MB
. Każdy obraz zostaje zamieniony w miniaturę (200x200
), a podczas przechodzenia z widoku listy do widoku szczegółowego wyświetlany jest tylko jeden obraz, więc wydajność nie jest ogromną sprawą, chociaż nie możemy całkowicie wyrzucić go z drogi. Oto, co robimy dotąd: uwagaPHP Imagick Optymalizacja JPEG
$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();
Side: Właśnie sobie sprawę błąd w moim warunkowym logiki tutaj o wysokość/szerokość, więc ignorować faktu, że w chwili obecnej. Wkrótce zredaguję to pytanie, aby odzwierciedlić prawidłowe porównanie warunków. Dla tych, którzy go nie złapali, skalowanie wszystkich obrazów jest szerokie, nawet jeśli ma skalować wysokość, a następnie po skalowaniu z powrotem do rozmiaru 1080 height
.
Obraz użyty do przetestowania rozpoczyna się jako obraz 3MB 2398×2400
. Skalowanie go do wartości 1079x1080
powoduje wyświetlenie obrazu , a następnie dodanie kompresji JPEG
w jakości 70
powoduje jej zmniejszenie do 750KB
. Za pomocą pliku kraken.io obraz udało się skompresować do wartości poniżej 60 KB. Czy istnieją dodatkowe rzeczy, które mogę zrobić w tym skrypcie, ponieważ musi on zoptymalizować obraz w czasie wykonywania?
Przeczytałem sugestie dotyczące użycia libjpeg, która jest zainstalowana, ale nie mogę znaleźć żadnej dokumentacji na temat tego, jakie funkcje ona obsługuje lub czy istnieje sposób zmuszenia Imagick do użycia go w konkretny sposób. Nie jestem nawet pewien, czy Imagick go już nie używa.
Edit: Rozwiązanie
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 na obraz o rozmiarach 1079 x 1080 wydaje się być całkiem przyzwoity. Nie sądzę, że można go zmniejszyć o wiele mniej bez zmniejszenia wymiarów pikseli lub poważnie obniżenia jakości. – GolezTrol
Problem polega na tym, że nie zbliżam się do tego w moim scenariuszu. W chwili obecnej jest to ~ 750KB, 60KB było porównaniem (czym narzędzie kraken.io było w stanie zrobić na tym samym obrazie). Nie szukam 60KB jako dokładnego celu, ale poniżej 200KB byłoby miłe. – MaKR