97 votes

PIL "IOError : image file truncated" avec de grandes images

Je pense que ce problème n'est pas lié à Zope. Néanmoins, je vais expliquer ce que j'essaie de faire :

J'utilise un PUT_factory dans Zope pour télécharger des images vers la BDOCÉ par FTP. L'image téléchargée est enregistrée comme 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 thumbnail de PIL pour les redimensionner, par exemple à 200x200. Cela fonctionne bien tant que les images téléchargées sont relativement petites. Je n'ai pas vérifié la limite exacte, mais 976x1296px est toujours acceptable.

Avec des images plus grandes, j'obtiens :

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 provenant de mon appareil photo. Je ne pense pas qu'ils soient 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 une usine PUT_factory, je n'ai pas d'objet fichier, j'utilise soit les données brutes de l'usine, soit un objet image (Zope) précédemment créé.

J'ai entendu dire que l'IAP traite les données d'image différemment lorsqu'une certaine taille est dépassée, mais je ne sais pas comment adapter mon code. Ou est-ce lié au chargement paresseux de l'IAP ?

237voto

abhillman Points 2007

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 ligne 201 - peut-être avez-vous une version légèrement différente), nous voyons que PIL lit des blocs du fichier et qu'il s'attend à ce que les blocs aient une certaine taille. Il s'avère que vous pouvez demander à PIL d'être tolérant envers les fichiers qui sont tronqués (il manque un fichier dans le bloc) en modifiant un paramètre.

Quelque part avant votre bloc de code, ajoutez simplement ce qui suit :

from PIL import ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True

...et vous devriez être bon.

EDIT : Il semble que cela fonctionne pour la version de PIL fournie avec Pillow ("pip install pillow"), mais peut ne pas fonctionner pour les installations par défaut de PIL.

14voto

Akhil Points 332

Voici ce que j'ai fait :

  • Modifier LOAD_TRUNCATED_IMAGES = False ligne de /usr/lib/python3/dist-packages/PIL/ImageFile.py:40 a LOAD_TRUNCATED_IMAGES = True .

L'édition du fichier nécessite cependant un accès Root. J'ai rencontré cette erreur en exécutant un pytorch qui utilisait peut-être la bibliothèque PIL.

Effectuez cette correction uniquement si vous rencontrez cette erreur, sans utiliser directement le LIP.

Sinon, s'il vous plaît, faites

from PIL import ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True

13voto

Kern3l Points 1977

La meilleure chose est que vous le 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 stupide que cela puisse paraître, cela fonctionnera comme un miracle. Si votre image a des données manquantes, elle sera remplie de gris (vérifiez le bas de votre image).

Remarque : l'utilisation de la casse camel en Python est déconseillée et n'est utilisée que dans les noms de classes.

5voto

feroze Points 3433

Il ne s'agit peut-être pas d'une question de LIP. Il peut être lié aux paramètres de votre serveur HTTP. Les serveurs HTTP imposent une limite à 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 cela pour votre serveur - il se peut que ce soit celui qui limite la taille du téléchargement.

1voto

Hanying Liang Points 11

J'ai été pris au piège avec le même problème. Cependant, en réglant ImageFile.LOAD_TRUNCATED_IMAGES = True ne convient pas dans mon cas, et j'ai vérifié que tous mes fichiers image étaient intacts, mais gros.

Je lis les images en utilisant cv2 et l'a ensuite converti en PIL.Image pour contourner le problème.

img = cv2.imread(imgfile, cv2.IMREAD_GRAYSCALE)
img = Image.fromarray(img)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X