Превышен жесткий предел памяти при загрузке большого изображения, возможно ли уменьшить разрешение при загрузке? - PullRequest
0 голосов
/ 14 июля 2020

Мне нужно сгенерировать маленькие эскизы из потенциально гигантских c изображений (10 000 x 10 000). Я использую ImageMagick и PHP в Google App Engine. Мой GAE имеет жесткий предел памяти 512 МБ.

Я пытался прочитать документацию по расширению imagemagick php, но документация довольно тонкая. Я нашел это сообщение SO , в котором есть ответ от сопровождающего, и попытался адаптировать их код. Я попытался установить область ресурсов так, чтобы изображения размером более 2000x2000 пикселей выгружались на диск, а не сохранялись в памяти, но либо я неправильно понимаю код, либо делаю что-то не так. Мой GAE по-прежнему вылетает, говоря, что я заполнил память.

try {
    Imagick::setResourceLimit(Imagick::RESOURCETYPE_AREA, 2000 * 2000);
    Imagick::setResourceLimit(Imagick::RESOURCETYPE_DISK, 1024c1024*2);

    $im = new \Imagick($path);
    
    // ...

} catch (\Exception $e) {
    error_log("Exception: " . $e->getMessage() . "\n");
}

Exceeded hard memory limit of 512 MB with 514 MB...

На устройствах Android при загрузке растрового изображения с диска появляется возможность понизить разрешение при загрузке в память . Это позволяет мне загружать уменьшенные версии изображения в память и избежать проблемы, когда файлы гигантских *1024* ломают все.

Есть ли что-то подобное в ImageMagick? Я видел ImageMagick :: setSamplingFactors () , но документация вообще не объясняет параметры, поэтому я не уверен, как его использовать.

Как я могу сгенерировать крошечный эскиз из гигантское изображение, не превышающее мой жесткий предел памяти в Google App Engine?

1 Ответ

2 голосов
/ 14 июля 2020

Если вы сжимаете изображения JPEG, imagemagick поддерживает сжатие при загрузке. Например, вот изображение JPEG размером 10k x 10k пикселей с уменьшенным размером до 200x200.

$ /usr/bin/time -f %M:%e \
    convert wtc.jpg -resize 200x200 x.jpg
713340:2.98

Это 720 МБ пикового использования памяти и почти 3 секунды процессорного времени. Теперь попробуйте следующее:

$ /usr/bin/time -f %M:%e \
    convert -define jpeg:size=400x400 wtc.jpg -resize 200x200 x.jpg
35952:0.32

До 35 МБ памяти и 300 мс ЦП.

-define jpeg:size=400x400 намекает загрузчику JPEG, что вам нужно изображение размером не менее 400x400 пикселей, поэтому (в данном случае) во время загрузки он будет иметь размер 1/8. Вам нужно, чтобы размер подсказки загрузки был как минимум в 2 раза больше, чем ваш окончательный выходной размер, чтобы избежать наложения.

Вы можете установить это из imagick с помощью setOption.

К сожалению, многие загрузчики не поддерживают сжатие при загрузке. PNG особенно плох:

$ /usr/bin/time -f %M:%e \
    convert wtc.png -resize 200x200 x.jpg
828376:5.62

830 МБ и 5,6 с.

Вы могли бы рассмотреть другие программы изменения размера. vipsthumbnail - это быстро и мало памяти для почти всех форматов файлов, например:

$ /usr/bin/time -f %M:%e \
    vipsthumbnail wtc.png --size 200x200 -o x.jpg
58780:2.29

60 МБ и 2,3 секунды для того же файла PNG. Качество такое же, как и у imagemagick.

Он также имеет PHP привязку - вы можете написать, например:

$image = Vips\Image::thumbnail('somefile.jpg', 200);
$image->writeToFile('tiny.jpg');
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...