Python PIL“IOError:图像文件被截断”,带有大图像

时间:2021-08-01 09:03:21

I think this problem is not Zope-related. Nonetheless I'll explain what I'm trying to do:

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

I'm using a PUT_factory in Zope to upload images to the ZODB per FTP. The uploaded image is saved as a Zope Image inside a newly created container object. This works fine, but I want to resize the image if it exceeds a certain size (width and height). So I'm using the thumbnail function of PIL to resize them i.e. to 200x200. This works fine as long as the uploaded images are relatively small. I didn't check out the exact limit, but 976x1296px is still ok.

我在Zope中使用PUT_factory将图像上传到每个FTP的ZODB。上传的图像将作为Zope Image保存在新创建的容器对象中。这工作正常,但如果图像超过一定的大小(宽度和高度),我想调整图像的大小。所以我使用PIL的缩略图功能来调整它们的大小,即200x200。只要上传的图像相对较小,这就可以正常工作。我没有查看确切的限制,但976x1296px仍然可以。

With bigger pictures I get:

随着更大的图片,我得到:

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

I tested a lot of jpegs from my camera. I don't think they are all truncated.

我从相机测试了很多jpeg。我不认为它们都被截断了。

Here is my 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)

As I'm using a PUT_factory, I don't have a file object, I'm using either the raw data from the factory or a previously created (Zope) Image object.

因为我正在使用PUT_factory,所以我没有文件对象,我使用的是工厂的原始数据或以前创建的(Zope)Image对象。

I've heard that PIL handles image data differently when a certain size is exceeded, but I don't know how to adjust my code. Or is it related to PIL's lazy loading?

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

4 个解决方案

#1


72  

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.

如果我们查看第220行(在您的情况下第201行 - 也许您运行的版本略有不同),我们会看到PIL正在读取文件的块,并且它希望块将具有一定的大小。事实证明,您可以通过更改设置来要求PIL容忍被截断的文件(从块中丢失一些文件)。

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

编辑:看起来这有助于Pillow捆绑的PIL版本(“pip安装枕头”),但可能不适用于PIL的默认安装

#2


11  

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.

注意:不鼓励在Python中使用camel case,并且仅在类名中使用。

#3


2  

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.

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

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

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

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

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

#4


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.

我不得不将tds版本更改为7.2以防止这种情况发生。也适用于tds版本8.0,但我在8.0中遇到了一些其他问题。

#1


72  

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.

如果我们查看第220行(在您的情况下第201行 - 也许您运行的版本略有不同),我们会看到PIL正在读取文件的块,并且它希望块将具有一定的大小。事实证明,您可以通过更改设置来要求PIL容忍被截断的文件(从块中丢失一些文件)。

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

编辑:看起来这有助于Pillow捆绑的PIL版本(“pip安装枕头”),但可能不适用于PIL的默认安装

#2


11  

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.

注意:不鼓励在Python中使用camel case,并且仅在类名中使用。

#3


2  

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.

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

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

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

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

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

#4


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.

我不得不将tds版本更改为7.2以防止这种情况发生。也适用于tds版本8.0,但我在8.0中遇到了一些其他问题。