Магия изображения /PHP падает с большими изображениями
У меня есть скрипт PHP, который используется для изменения размера изображений в папке FTP пользователя для использования на его веб-сайте.
Несмотря на медленное изменение размера, скрипт завершил корректно со всеми изображениями в прошлом. Однако недавно пользователь загрузил альбом изображений JPEG с разрешением 21 мегапикселя, и, как я обнаружил, сценарий не может преобразовать изображения, но не выдает никаких ошибок PHP. Когда я просматривал различные журналы, я обнаружил, что несколько процессов Apache были завершены с ошибками Out Of Memory.
Функциональная часть сценария PHP - это, по сути, цикл for, который перебирает мои изображения на диске и вызывает метод, который проверяет, существует ли миниатюра, а затем выполняет следующее:
$image = new Imagick();
$image->readImage($target);
$image->thumbnailImage(1000, 0);
$image->writeImage(realpath($basedir)."/".rescale."/".$filename);
$image->clear();
$image->destroy();
Сервер имеет 512 МБ оперативной памяти, обычно не менее 360 МБ + свободной.
В PHP ограничение памяти установлено на 96 МБ, но я уже устанавливал его выше без какого-либо влияния на проблему.
По моим оценкам, 21-мегапиксельное изображение должно занимать в области 80 МБ + в несжатом виде, и поэтому я озадачен, почему ОЗУ так быстро исчезает, если объекты Image Magick не удаляются из памяти.
Есть ли способ, которым я могу оптимизировать свой сценарий, чтобы использовать меньше памяти или сборщика мусора более эффективно?
У меня просто нет оперативки, чтобы справиться с такими большими изображениями?
ура
3 ответа
Вызов $image->setSize()
до $image->readImage()
чтобы libjpeg изменил размер изображения во время загрузки, чтобы уменьшить использование памяти.
(редактировать), пример использования: эффективное изменение размера изображения JPEG в PHP
Смотрите этот ответ для более подробного объяснения.
imagick использует разделяемую библиотеку, и ее использование памяти недоступно для PHP, поэтому настройка памяти PHP и сборка мусора не помогут.
Попробуйте добавить это до создания new Imagick()
объект:
// pixel cache max size
IMagick::setResourceLimit(imagick::RESOURCETYPE_MEMORY, 32);
// maximum amount of memory map to allocate for the pixel cache
IMagick::setResourceLimit(imagick::RESOURCETYPE_MAP, 32);
Это приведет к тому, что imagick перейдет на диск (по умолчанию /tmp), когда ему потребуется более 32 МБ для манипулирования изображениями. Это будет медленнее, но не будет исчерпано ОЗУ (если / tmp не находится на виртуальном диске, в этом случае вам нужно изменить место, где imagick записывает свои временные файлы).
MattBianco почти верен, единственное изменение состоит в том, что пределы памяти указаны в байтах, поэтому будет 33554432 для 32 МБ:
// pixel cache max size
IMagick::setResourceLimit(imagick::RESOURCETYPE_MEMORY, 33554432);
// maximum amount of memory map to allocate for the pixel cache
IMagick::setResourceLimit(imagick::RESOURCETYPE_MAP, 33554432);