2009-07-13 13 views
5

¿Hay alguna manera de evitar que PHP GD image library se quede sin memoria? Si se carga una imagen demasiado grande, GD tiende a quedarse sin memoria, terminando el script. Me gustaría arrojar una excepción atrapable o algo así, pero no es así.¿Una forma segura de evitar que la biblioteca de imágenes GD se quede sin memoria? (PHP)

En este momento estoy usando un script improvisado que primero emite un ini_set('memory_limit', '128M'), si eso funciona, generalmente estoy listo. Dependiendo de la configuración del servidor, eso puede no ser posible, así que estoy recurriendo a un algoritmo que intenta estimar la cantidad de memoria necesaria (teniendo en cuenta la resolución, la profundidad de color, los canales y un factor de caramelo), y luego lo compara con memory_get_usage() si la función existe, de lo contrario hace una estimación aproximada.

Todo funciona hasta ahora, pero está lejos de ser elegante y fallará en algunos casos extremos, estoy seguro. ¿Hay alguna forma mejor de hacerlo, es decir, si GD falla correctamente si es necesario, en lugar de detenerlo todo?

+1

imágenes JPEG grandes (no-PNG u otros tipos) puede cambiar el tamaño, mientras que la carga, consulte esta respuesta para más detalles: http://stackoverflow.com/questions/12661/efficient-jpeg-image-resizing- in-php/4613341 # 4613341 –

Respuesta

3

¡Compre más memoria! :-P

En serio, es imposible manejar la memoria insuficiente porque cualquier acción que realice requerirá más memoria.

Su mejor opción es limitar el tamaño de la imagen que se está cargando según la configuración actual de la memoria.

+2

LOL, cómprame un host con más memoria. ;-) Bueno, al menos me gustaría que GD calcule su propio uso de memoria, en lugar de tener que hacer las conjeturas propensas a errores y luego contener la respiración. No puedo limitar la imagen por tamaño de archivo. Un archivo pequeño con un JPG altamente comprimido y de alta resolución puede ocupar más memoria que un archivo grande con un archivo PNG de baja resolución. Es por eso que tengo que recurrir a mi cálculo mencionado anteriormente. – deceze

0

Su mejor apuesta es dejar de tratar de calcular cuánto carnero necesitará, y simplemente agotarlo al máximo - si tiene 4 GB disponibles, indique al script de imagen que use entre 2 y 4 GB más o menos , y cuando el guión finaliza, haz que vuelva a la normalidad, que cubrirá todas las situaciones potencialmente fatales. Esa es la única forma "a prueba de fallas" que se me ocurre de todos modos ...

+0

Eso es lo que trato de hacer, pero eso rara vez es posible en hosts compartidos. Para esos casos estoy haciendo los mejores cálculos de adivinanzas para evitar problemas. – deceze

+0

Al establecer el límite de la memoria de PHP igual a la cantidad total de RAM que tiene el sistema, o en cualquier lugar remotamente cercano, permitirá a los usuarios DOS a través de su script de imagen. Averiguar cuánta memoria RAM se necesita de antemano es la única forma en que se me ocurre que evitará este tipo de DOS. –

1

Hay otra manera de hacerlo, pero puede llevar mucho tiempo, ya que ciertas partes del proceso de edición de imágenes se repetirían varias veces. veces, pero puede establecer el límite de memoria a su valor estimado, luego intente procesar la imagen; si falla, capture la excepción, aumente el límite de memoria y luego procese la imagen nuevamente; repita esto hasta que tenga éxito o alcance un determinado límite de memoria - en ese punto, lanzaría un mensaje de error al usuario explicando que su imagen es demasiado grande para ser utilizada.

Editar: Para detectar el error fuera de la memoria, se puede usar esta solución: http://au2.php.net/set_error_handler#35622

+0

Lea de nuevo, AFAIK no hay nada atrapable lanzado. Es una operación única de "funciona o no funciona". A menos que pueda decirme cómo detectar un error de falta de memoria, que es lo que estoy pidiendo. :) – deceze

+2

Hay una manera de detectar estos errores: http://au2.php.net/set_error_handler#35622 – jsnfwlr

+0

Voy a tener que ver si esto realmente ayuda, como señaló Nick, tendría que usar más memoria para tratar el error después de que ocurriera – deceze

0

para detectar errores fatales de PHP, como "memoria insuficiente" o "error fatal de PHP: Permitido el tamaño de la memoria de 8388608 bytes agotados (intentó asignar ... bytes) en ", consulte aquí: http://php.net/manual/en/function.set-error-handler.php#88401

+0

Una vez que una secuencia de comandos PHP está sin memoria, no puede llamar a la función de apagado porque eso requeriría la asignación de más memoria. – scotts

3

Después de crear una imagen.

imagepng($image); 
imagedestroy($image); 

eliminará el problema de memoria

+0

Esto debería marcarse como la respuesta, funcionó como un encanto para mí. – Vic

+0

Esto ** no ** debe marcarse como la respuesta. La destrucción de una imagen ahorra el uso de memoria, pero de ninguna manera hace que GD se comporte de forma más elegante. – Glutexo

0

hacer algunas pruebas para comprobar la cantidad de memoria cada necesidad gd función.

  • imagecreatetruecolor parece necesitar width*height*5 bytes.

  • imagepng parece necesitar width*height*4 bytes.

+0

¿Por qué 'imagecreatetruecolor' necesita 5 bytes por píxel? Suena como un número impar. – Luke

+0

porque el soporte alfa se agregó mucho tiempo después de crear imágenes, y muchas funciones probablemente tenían suposiciones de que el 4to byte siempre era 0, por lo que no se podía usar ... o pensaban/veían que era demasiado complejo para usarlo y creó uno nuevo. – sebbu

+0

¿Tiene alguna experiencia también al cargar imágenes existentes encima de él? p.ej. para jpg o png? Uso x * y * ~ 5 para jpg, ~ 8 para png, además del uso actual de la memoria. si eso excede el límite de memoria, establezco una excepción. Pero: configurar 64M como límite y tener un jpg cargado de 2MB a veces puede interrumpir la operación. Jpg parece usar a veces más memoria. ¿Compresión? ¿Alguna otra información exif? donde puedo mejorar el cálculo? – flobee

Cuestiones relacionadas