Подтвердить что ты не робот

Python PIL "IOError: файл изображения усечен" с большими изображениями

Я думаю, что эта проблема не связана с Zope. Тем не менее я объясню, что я пытаюсь сделать:

Я использую PUT_factory в Zope для загрузки изображений на ZODB на FTP. Загруженное изображение сохраняется как изображение 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).

Я проверил много jpegs с моей камеры. Я не думаю, что все они урезаны.

Вот мой код:

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, у меня нет файлового объекта, я использую либо необработанные данные из factory, либо ранее созданного объекта Zope.

Я слышал, что PIL обрабатывает данные изображения по-разному, когда определенный размер превышен, но я не знаю, как настроить свой код. Или это связано с ленивой загрузкой PIL?

4b9b3361

Ответ 1

Я немного опоздал, чтобы ответить здесь, но у меня возникла аналогичная проблема, и я хотел поделиться своим решением. Во-первых, здесь довольно типичная трассировка стека для этой проблемы:

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)

Если мы рассмотрим строку 220 (в вашем случае строка 201, возможно, вы используете немного другую версию), мы видим, что PIL читает в блоках файла и ожидает, что блоки будут иметь определенный размер. Оказывается, вы можете попросить PIL быть терпимым к файлам, которые усекаются (отсутствует некоторый файл из блока), изменяя параметр.

Где-то перед блоком кода просто добавьте следующее:

from PIL import ImageFile
ImageFile.LOAD_TRUNCATED_IMAGES = True

... и вы должны быть хорошими.

EDIT: похоже, что это помогает для версии PIL в комплекте с подушкой ( "подушка для установки подушек" ), но может не работать для стандартных установок PIL

Ответ 2

Лучше всего то, что вы можете:

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)

Как ничтожно, как кажется - это будет работать как чудо. Если у вашего изображения отсутствуют данные, он будет заполнен серым (проверьте нижнюю часть изображения).

Примечание: использование верблюжьего футляра в Python не рекомендуется и используется только в именах классов.

Ответ 3

Это может быть не проблема PIL. Это может быть связано с настройкой вашего HTTP-сервера. HTTP-серверы устанавливают ограничение на размер тела объекта, который будет принят.

Например, в Apache FCGI параметр FcgidMaxRequestLen определяет максимальный размер файла, который можно загрузить.

Проверьте, что для вашего сервера это может быть ограничение размера выгрузки.

Ответ 4

Мне пришлось изменить версию tds на 7.2, чтобы это не происходило. Также работает с tds версии 8.0, однако у меня были некоторые другие проблемы с 8.0.