90

我认为这个问题与 Zope 无关。尽管如此,我会解释我正在尝试做的事情:

我在 Zope 中使用 PUT_factory 通过 FTP 将图像上传到 ZODB。上传的图像在新创建的容器对象中保存为 Zope 图像。这很好用,但是如果图像超过一定大小(宽度和高度),我想调整它的大小。所以我使用 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,因此我没有文件对象,我使用的是来自工厂的原始数据或以前创建的 (Zope) Image 对象。

我听说当超过一定大小时 PIL 会以不同的方式处理图像数据,但我不知道如何调整我的代码。还是和PIL的延迟加载有关?

4

6 回答 6

217

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

于 2014-05-09T23:26:17.013 回答
13

最好的事情是你可以:

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)

尽管看起来很愚蠢 - 它会像奇迹一样工作。如果您的图像缺少数据,它将用灰色填充(检查图像底部)。

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

于 2013-11-19T10:00:21.617 回答
13

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
于 2020-01-07T08:44:54.860 回答
4

这可能不是 PIL 问题。它可能与您的 HTTP 服务器设置有关。HTTP 服务器对将被接受的实体主体的大小进行了限制。

例如,在 Apache FCGI 中,选项 FcgidMaxRequestLen 确定可以上传的文件的最大大小。

检查您的服务器 - 它可能是限制上传大小的服务器。

于 2012-10-21T05:13:14.747 回答
1

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)
于 2021-08-15T07:52:12.477 回答
0

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.

于 2014-12-19T20:21:55.680 回答