Python PIL "IOError: fichier image tronqué" avec de grandes images
je pense que ce problème n'est pas lié à Zope. Néanmoins, je vais vous expliquer ce que j'essaie de faire:
J'utilise un PUT_factory dans Zope pour télécharger des images dans la ZODB par FTP. L'image téléchargée est sauvegardée sous la forme D'une Image Zope à l'intérieur d'un objet conteneur nouvellement créé. Cela fonctionne bien, mais je veux redimensionner l'image si elle dépasse une certaine taille (largeur et hauteur). J'utilise donc la fonction miniature de PIL pour les redimensionner, c'est-à-dire à 200x200. Cela fonctionne très bien tant que les images téléchargées sont relativement petite. Je n'ai pas vérifié la limite exacte, mais 976x1296px est toujours ok.
<!-Avec de plus grandes photos je reçois:Module PIL.Image, line 1559, in thumbnail
Module PIL.ImageFile, line 201, in load
IOError: image file is truncated (nn bytes not processed).
j'ai testé beaucoup de jpegs de mon appareil photo. Je ne pense pas qu'ils sont tous tronqués.
Voici mon code:
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)
comme J'utilise un PUT_factory, Je n'ai pas d'objet file, j'utilise soit les données brutes de l'usine, soit un objet Image (Zope) créé précédemment.
j'ai entendu dire que PIL gère les données d'image différemment lorsqu'une certaine taille est dépassée, mais je ne sais pas comment régler mon code. Ou est-ce lié au chargement paresseux de PIL?
4 réponses
je suis un peu en retard pour répondre ici, mais j'ai rencontré un problème similaire et je voulais partager ma solution. Tout d'abord, voici une trace de pile assez typique pour ce problème:
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 nous regardons autour de la ligne 220 (dans votre cas la ligne 201-peut-être que vous utilisez une version légèrement différente), nous voyons que PIL lit dans les blocs du fichier et qu'il s'attend à ce que les blocs vont être d'une certaine taille. Il s'avère que vous pouvez demander à PIL d'être tolérant des fichiers qui sont tronqué (manque un fichier dans le bloc) en changeant un paramètre.
quelque part avant de votre bloc de code, il suffit d'ajouter le code suivant:
from PIL import ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True
...et tu devrais être sage.
EDIT: il semble que cela aide pour la version de PIL avec Pillow ("pip install pillow"), mais peut ne pas fonctionner pour les installations par défaut de PIL
Meilleure chose est que vous pouvez:
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)
aussi bête que cela paraisse - cela marchera comme un miracle. Si votre image a des données manquantes, elle sera remplie de gris (vérifiez le bas de votre image).
Note: l'utilisation de camel case en Python est déconseillée et n'est utilisée que dans les noms de classe.
ce n'est peut-être pas un problème de PIL. Il se peut que cela soit lié à la configuration de votre serveur HTTP. Les serveurs HTTP limitent la taille du corps de l'entité qui sera acceptée.
par exemple, dans Apache FCGI, L'option FcgidMaxRequestLen détermine la taille maximale du fichier qui peut être téléchargé.
vérifiez que pour votre serveur - c'est peut-être celui qui limite la taille du téléchargement.
j'ai dû changer la version tds à 7.2 pour éviter que cela ne se produise. Fonctionne également avec la version 8.0 de tds, mais j'ai eu d'autres problèmes avec la version 8.0.