Python PIL“IOError:图像文件被截断”与大图像

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12984426/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 12:19:01  来源:igfitidea点击:

Python PIL "IOError: image file truncated" with big images

pythonimagepython-imaging-libraryzope

提问by Georg Pfolz

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 图像。这工作正常,但如果图像超过特定大小(宽度和高度),我想调整图像大小。所以我使用 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的懒加载有关?

采纳答案by abhillman

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 install Pillow”),但可能不适用于 PIL 的默认安装

回答by feroze

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 服务器设置有关。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.

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

回答by Ctrl-C

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 中使用驼峰式大小写,并且仅在类名中使用。

回答by stuartz

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.0 中遇到了其他一些问题。

回答by Akhil

Here is what I did:

这是我所做的:

  • Edit LOAD_TRUNCATED_IMAGES = Falseline from /usr/lib/python3/dist-packages/PIL/ImageFile.py:40to LOAD_TRUNCATED_IMAGES = True.
  • 编辑LOAD_TRUNCATED_IMAGES = False行从/usr/lib/python3/dist-packages/PIL/ImageFile.py:40LOAD_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.

不过,编辑文件需要 root 访问权限。我在运行一些可能使用 PIL 库的 pytorch 时遇到了这个错误。

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

仅在遇到此错误时才进行此修复,而不直接使用 PIL。

Else please do

其他请做

from PIL import ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True