Python PIL "IOError: archivo de imagen truncado" con imágenes grandes


Creo que este problema no está relacionado con Zope. Sin embargo, voy a explicar lo que estoy tratando de hacer:

Estoy usando un PUT_factory en Zope para subir imágenes al ZODB por FTP. La imagen subida se guarda como una imagen Zope dentro de un objeto contenedor recién creado. Esto funciona bien, pero quiero cambiar el tamaño de la imagen si excede un cierto tamaño (ancho y alto). Así que estoy usando la función de miniatura de PIL para redimensionarlos, es decir, a 200x200. Esto funciona bien siempre y cuando las imágenes subidas sean relativamente pequeño. No comprobé el límite exacto, pero 976x1296px sigue estando bien.

Con imágenes más grandes obtengo:

Module PIL.Image, line 1559, in thumbnail
Module PIL.ImageFile, line 201, in load
IOError: image file is truncated (nn bytes not processed).

Probé muchos jpegs de mi cámara. No creo que todos estén truncados.

Aquí está mi código:

if img and img.meta_type == 'Image':
  pilImg = PIL.Image.open( StringIO(str(img.data)) )
elif imgData:
  pilImg = PIL.Image.open( StringIO(imgData) )

pilImg.thumbnail((width, height), PIL.Image.ANTIALIAS)

Como estoy usando un PUT_factory, no tengo un objeto file, estoy usando los datos sin procesar de la fábrica o un objeto de imagen creado previamente (Zope).

He oído que PIL maneja los datos de imagen de manera diferente cuando se excede un cierto tamaño, pero no se como ajustar mi código. ¿O está relacionado con la carga perezosa de PIL?

Author: Rastaf, 2012-10-20

4 answers

Estoy un poco tarde para responder aquí, pero me encontré con un problema similar y quería compartir mi solución. Primero, aquí hay un seguimiento de pila bastante típico para este problema:

Traceback (most recent call last):
  ...
  File ..., line 2064, in ...
    im.thumbnail(DEFAULT_THUMBNAIL_SIZE, Image.ANTIALIAS)
  File "/Library/Python/2.7/site-packages/PIL/Image.py", line 1572, in thumbnail
    self.load()
  File "/Library/Python/2.7/site-packages/PIL/ImageFile.py", line 220, in load
    raise IOError("image file is truncated (%d bytes not processed)" % len(b))
IOError: image file is truncated (57 bytes not processed)

Si miramos alrededor de la línea 220 (en su caso la línea 201-quizás está ejecutando una versión ligeramente diferente), vemos que PIL está leyendo en bloques del archivo y que espera que los bloques sean de un cierto tamaño. Resulta que puede pedirle a PIL que sea tolerante con los archivos que están truncados (faltantes algunos archivos del bloque) cambiando una configuración.

En algún lugar antes de su bloque de código, simplemente agregue lo siguiente:

from PIL import ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True

...y tú deberías ser bueno.

EDITAR: Parece que esto ayuda para la versión de PIL incluida con Pillow ("pip install pillow"), pero puede no funcionar para las instalaciones predeterminadas de PIL

 73
Author: abhillman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-09 23:43:20

Lo mejor es que puedes:

if img and img.meta_type == 'Image':
    pilImg = PIL.Image.open( StringIO(str(img.data)) )
elif imgData:
    pilImg = PIL.Image.open( StringIO(imgData) )

try:
    pilImg.load()
except IOError:
    pass # You can always log it to logger

pilImg.thumbnail((width, height), PIL.Image.ANTIALIAS)

Por tonto que parezca, funcionará como un milagro. Si su imagen tiene datos faltantes, se llenará con gris (verifique la parte inferior de su imagen).

Nota: se desaconseja el uso de camel case en Python y solo se usa en nombres de clases.

 11
Author: Ctrl-C,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-03 08:49:23

Esto podría no ser un problema PIL. Podría estar relacionado con la configuración de su servidor HTTP. Los servidores HTTP ponen un límite en el tamaño del cuerpo de la entidad que será aceptado.

Por ejemplo, en Apache FCGI, la opción FcgidMaxRequestLen determina el tamaño máximo del archivo que se puede cargar.

Compruebe que para su servidor - podría ser el que está limitando el tamaño de carga.

 2
Author: feroze,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-21 05:13:14

Tuve que cambiar la versión de tds a 7.2 para evitar que esto sucediera. También funciona con la versión 8.0 de tds, sin embargo, tuve algunos otros problemas con 8.0.

 0
Author: stuartz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-19 20:21:55