Blog. Just Blog

Проверка памяти при вызове функции ImageCreateTrueColor

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Web-мастеру и не только | Автор: ManHunter
Проверка памяти при вызове функции ImageCreateTrueColor
Проверка памяти при вызове функции ImageCreateTrueColor

При разработке любого сайта или веб-приложения нужно делать его максимально устойчивым к различным ситуациям, особенно если со стороны пользователя поступают какие-либо данные. Одна из таких ситуаций - обработка фотографий или других изображений, загружаемых пользователем. Для ресайза, наложения водяных знаков или эффектов, так или иначе приходится вызывать функцию ImageCreateTrueColor. Эта операция требует много памяти. Особенно это критично на виртуальном хостинге, где очень часто аккаунт жестко ограничен в использовании памяти сервера. Если памяти не хватает, например, для обработки больших изображений или в случае применения "бомб", то скрипт падает с фатальной ошибкой. Как узнать объем памяти, который потребуется для работы с изображением, до вызова функции ImageCreateTrueColor? Ответ вы найдете в этой статье.

Если скачать и посмотреть исходники PHP, в частности исходники расширения GD, то в функции gdImageCreateTrueColor можно обнаружить следующий код. Для удобства я оставил только те строчки, которые связаны с выделением памяти под изображение.

im->tpixels=(int **) gdMalloc(sizeof(int *) * sy);
im->AA_opacity=(unsigned char **) gdMalloc(sizeof(unsigned char *) * sy);
for (i = 0; i < sy; i++) {
  im->tpixels[i]=(int *) gdCalloc(sx,sizeof(int));
  im->AA_opacity[i]=(unsigned char *) gdCalloc(sx,sizeof(unsigned char));
}

Получается, что функция ImageCreateTrueColor создает массив из пикселей, плюс массив из коэффициентов прозрачности, плюс массивы с указателями на строки и коэффициенты прозрачности. Остальную мелочь можно не учитывать, там считанные байты. Если свернуть все это до единой формулы, то получится следующее:

Размер необходимой памяти = sy*sizeof(int *) + sy*sizeof(char *) + sy*sx*sizeof(int) + sy*sx*sizeof(char)
В человекопонятном виде это будет выглядеть вот так:

Размер необходимой памяти = sy*8 + sy*8 + sy*sx*4 + sy*sx*1
Вспоминаем школьный курс арифметики:

Размер необходимой памяти = sy*16 + sy*sx*5
Осталось реализовать все это в виде функции. Она получает объем памяти, которую уже занял PHP, прибавляет к ней рассчитанный размер памяти для изображения и сравнивает с параметром memory_limit из настроек PHP. Расширение GD работает в контексте PHP, поэтому попадает под это ограничение.
  1. function chk_memory($x,$y) {
  2.     // Доступная память для PHP
  3.     $memory_available=intval(ini_get('memory_limit'))*1000*1000;
  4.     // Подсчет необходимой памяти для обработки изображения
  5.     $memory_needed=memory_get_usage()+($y*16 $x*$y*5);
  6.     return ($memory_available>$memory_needed);
  7. }
Эту же функцию можно использовать для проверки доступной памяти перед вызовом функций ImageCreateFrom*. Определяем размеры изображения, передаем их в функцию и сразу же узнаем, сможем ли мы обработать этот файл. Больше не будет никаких фатальных ошибок из-за переполнения памяти.

А как быть, если все равно требуется обработка больших изображений? Для этого придется использовать средства ImageMagick. ImageMagick работает вне контекста PHP и на него не распространяются лимиты памяти.

Поделиться ссылкой ВКонтакте Поделиться ссылкой на Facebook Поделиться ссылкой на LiveJournal Поделиться ссылкой в Мой Круг Добавить в Мой мир Добавить на ЛиРу (Liveinternet) Добавить в закладки Memori Добавить в закладки Google
Просмотров: 587 | Комментариев: 2

Метки: PHP, графика
Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
ManHunter (11.03.2018 в 14:25):
Это сделано специально, чтобы доступная по расчетам память была чуть меньше, чем реальная. Разница невелика, но она как раз может быть задействована под прочие нужды.
Str1ker (06.03.2018 в 17:18):
$memory_available=intval(ini_get('memory_limit'))*1000*1000;

Разве не 1024?

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2018
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.16 сек. / MySQL: 2 (0.0757 сек.) / Память: 4.75 Mb
Наверх