Магия изображения /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);
Другие вопросы по тегам