Python PIL “IOError: archivo de imagen truncado” con imágenes grandes
python-imaging-library zope (4)
Esto podría no ser un problema de PIL. Puede estar relacionado con la configuración de su servidor HTTP. Los servidores HTTP ponen un límite al 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.
Compruébelo en su servidor, podría ser el que limita el tamaño de la carga.
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 cargar imágenes al ZODB por FTP. La imagen cargada se guarda como una imagen de Zope dentro de un objeto contenedor recién creado. Esto funciona bien, pero quiero cambiar el tamaño de la imagen si supera 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 cargadas sean relativamente pequeñas. No revisé el límite exacto, pero 976x1296px todavía está bien.
Con imágenes más grandes me sale:
Module PIL.Image, line 1559, in thumbnail
Module PIL.ImageFile, line 201, in load
IOError: image file is truncated (nn bytes not processed).
He probado un montón de archivos JPEG 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 de archivo, 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 sé cómo ajustar mi código. ¿O está relacionado con la carga perezosa de PIL?
Llego un poco tarde para responder aquí, pero me encontré con un problema similar y quería compartir mi solución. Primero, aquí hay un rastro 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 tengan un tamaño determinado. Resulta que puedes pedirle a PIL que sea tolerante con los archivos que están truncados (falta algún archivo 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 deberías ser bueno.
EDITAR: Parece que esto ayuda para la versión de PIL incluida con la almohada ("pip install pillow"), pero puede que no funcione para las instalaciones predeterminadas de PIL
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)
Tan tonto como parece, funcionará como un milagro. Si a su imagen le faltan datos, se rellenará con gris (verifique la parte inferior de su imagen).
Nota: el uso de la funda de camello en Python no se recomienda y solo se usa en los nombres de las clases.
Tuve que cambiar la versión de tds a 7.2 para evitar que esto suceda. También funciona con la versión 8.0 de tds, sin embargo tuve otros problemas con la versión 8.0.