web-dev-qa-db-ja.com

Python PIL "IOError:画像ファイルが切り捨てられました"大きな画像

この問題は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の遅延読み込みに関連していますか?

51
Rastaf

ここで返信するのが少し遅れましたが、同様の問題に遭遇したため、解決策を共有したいと思いました。まず、この問題の典型的なスタックトレースを次に示します。

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

...そしてあなたは良いはずです。

編集:これは、PillowにバンドルされているPILのバージョン(「pip install pillow」)には役立ちますが、PILのデフォルトのインストールでは機能しない場合があります

127
abhillman

最も良いのは、次のことができることです。

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でのラクダケースの使用は推奨されず、クラス名でのみ使用されます。

12
Ctrl-C

これはPILの問題ではない可能性があります。 HTTPサーバーの設定に関連している可能性があります。 HTTPサーバーは、受け入れられるエンティティ本体のサイズに制限を設けます。

たとえば、Apache FCGIでは、オプションFcgidMaxRequestLenがアップロード可能なファイルの最大サイズを決定します。

ご使用のサーバーで確認してください-アップロードサイズを制限している可能性があります。

2
feroze

これを防ぐには、tdsバージョンを7.2に変更する必要がありました。また、tdsバージョン8.0でも動作しますが、8.0では他の問題がいくつかありました。

0
stuartz