Проверка памяти при вызове функции 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, поэтому попадает под это ограничение.
Code (PHP) : Убрать нумерацию
- function chk_memory($x,$y) {
- // Доступная память для PHP
- $memory_available=intval(ini_get('memory_limit'))*1000*1000;
- // Подсчет необходимой памяти для обработки изображения
- $memory_needed=memory_get_usage()+($y*16 + $x*$y*5);
- return ($memory_available>$memory_needed);
- }
А как быть, если все равно требуется обработка больших изображений? Для этого придется использовать средства ImageMagick. ImageMagick работает вне контекста PHP и на него не распространяются лимиты памяти.
Просмотров: 1707 | Комментариев: 2
Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
ManHunter
(11.03.2018 в 14:25):
Это сделано специально, чтобы доступная по расчетам память была чуть меньше, чем реальная. Разница невелика, но она как раз может быть задействована под прочие нужды.
Str1ker
(06.03.2018 в 17:18):
$memory_available=intval(ini_get('memory_limit'))*1000*1000;
Разве не 1024?
Разве не 1024?
Добавить комментарий
Заполните форму для добавления комментария