PIL“ IOError: image file truncated”with big images

我认为这个问题与 Zope 无关,尽管如此,我还是要解释一下我正在做的事情:

我正在使用 Zope 的一个 PUT _ Factory 来上传每个 fTP 的图像到 zODB。上传的图像保存为新创建的容器对象中的 Zope Image。这个工作很好,但是如果图像超过一定的大小(宽度和高度) ,我想调整图像的大小。因此我使用 PIL 的缩略图函数来调整它们的大小,即200x200。只要上传的图片相对较小,这种方法就可以很好地工作。我没有检查确切的限制,但976x1296px 仍然可以。

用更大的图片我得到:

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

我测试了很多照相机的 JPEG 图片,我不认为它们都被截断了。

这是我的代码:

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)

因为我使用的是 PUT _ Factory,所以没有 file 对象,我使用的是来自工厂的原始数据或以前创建的(Zope) Image 对象。

我听说当超过一定的尺寸时,PIL 处理图像数据的方式不同,但我不知道如何调整我的代码。或者与 PIL 的延迟加载有关?

100114 次浏览

This might not be a PIL issue. It might be related to your HTTP Server setting. HTTP servers put a limit on the size of the entity body that will be accepted.

For eg, in Apache FCGI, the option FcgidMaxRequestLen determines the maximum size of file that can be uploaded.

Check that for your server - it might be the one that is limiting the upload size.

Best thing is that you can:

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)

As dumb as it seems - it will work like a miracle. If your image has missing data, it will be filled with gray (check the bottom of your image).

Note: usage of camel case in Python is discouraged and is used only in class names.

I'm a little late to reply here, but I ran into a similar problem and I wanted to share my solution. First, here's a pretty typical stack trace for this problem:

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)

If we look around line 220 (in your case line 201—perhaps you are running a slightly different version), we see that PIL is reading in blocks of the file and that it expects that the blocks are going to be of a certain size. It turns out that you can ask PIL to be tolerant of files that are truncated (missing some file from the block) by changing a setting.

Somewhere before your code block, simply add the following:

from PIL import ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True

...and you should be good.

EDIT: It looks like this helps for the version of PIL bundled with Pillow ("pip install pillow"), but may not work for default installations of PIL

I had to change the tds version to 7.2 to prevent this from happening. Also works with tds version 8.0, however I had some other issues with 8.0.

Here is what I did:

  • Edit LOAD_TRUNCATED_IMAGES = False line from /usr/lib/python3/dist-packages/PIL/ImageFile.py:40 to LOAD_TRUNCATED_IMAGES = True.

Editing the file requires root access though. I encountered this error while running some pytorch which was maybe using the PIL library.

Do this fix only if you encounter this error, without directly using PIL.

Else please do

from PIL import ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True

I was trapped with the same problem. However, setting ImageFile.LOAD_TRUNCATED_IMAGES = True is not suitable in my case, and I have checked that all my image files were unbroken, but big.

I read the images using cv2, and then converted it to PIL.Image to get round the problem.

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

When image was partly broken, OSError will be caused.

I use below code for check and save the wrong image list.

try:
img = Image.open(file_path)
img.load()


## do the work with the loaded image


except OSError as error:
print(f"{error} ({file_path})")
    

with open("./error_file_list.txt", "a") as error_log:
log.write(str(file_path))