2012-03-30 2 views
7

私はPythonとDjangoを学んでいます。Django PIL:IOErrorイメージファイルを特定できません

イメージはforms.ImageField()を使用してユーザーから提供されます。次に、私は2つの異なるサイズの画像を作成するためにそれを処理しなければなりません。 image_resizerが二度目に呼び出されたとき、私はエラーエン取得

def create_event(owner_id, name, image):   
    image_thumb = image_resizer(image, name, '_t', 'events', 180, 120) 
    image_medium = image_resizer(image, name, '_m', 'events', 300, 200) 

::私はサイズ変更機能を呼び出す

IOError at /add_event/ 
cannot identify image file 

:私はフォームを送信すると

は、Djangoは以下のエラーを返します

def image_resizer(image, name, size, app_name, length, height): 
    im = Image.open(image) 
    if im.mode != "RGB": 
     im = im.convert("RGB") 
    im = create_thumb(im, length, height) 
    posit = str(MEDIA_ROOT)+'/'+app_name+'/' 
    image_2 = im 
    image_name = name + size +'.jpg' 
    imageurl = posit + image_name 
    image_2.save(imageurl,'JPEG',quality=80) 
    url_image='/'+app_name+'/'+image_name 
    return url_image 

バージョン:
Django 1.3.1
のPython 2.7.1
PIL 1.1.7

私は問題を発見しようとしているが、私は何をすべきかわかりません。先進的でありがとう!

編集
私はこの機能を書き直しました。今では、バッチ内の異なる画像を作成していますので、

url_array = image_resizer.resize_batch(image, image_name, [[180,120,'_t'], [300,200,'_m']], '/events/') 

image_thumb = url_array[0] 
image_medium = url_array[1] 

とリサイズ機能:すべての

def resize_batch(image, name, size_array, position): 
    im = Image.open(image) 
    if im.mode != "RGB": 
     im = im.convert("RGB") 
    url_array = [] 
    for size in size_array: 
     new_im = create_thumb(im, size[0], size[1]) 
     posit = str(MEDIA_ROOT) + position 
     image_name = name + size[2] +'.jpg' 
     imageurl = posit + image_name 
     new_im.save(imageurl,'JPEG',quality=90) 
     new_url_array = position + image_name 
     url_array.append(new_url_array) 
    return url_array 

おかげで、私はサイズ変更機能を呼び出す

+0

Image.open()で生成されますか?そこにはどのような道がありますか?本当にそのパスに有効な画像ファイルがありますか? – ilvar

+0

はい、 'Image.open()'で生成され、 ''タイプです。今私は@ gareth-reesによって提案されたソリューションを使用して解決しようとしています。 – enri

+0

Image.open()にファイルオブジェクトを渡すと、そのファイルオブジェクトは以前にバイナリモードで開かれている必要があります。それはおそらく問題ですが、コードから判断するのは不可能です。 – user240515

答えて

19

ilvar asksコメントには、どのような種類のオブジェクトがimageですか?私はこの答えの目的のために、リモートユーザがアップロードしたファイルからDjango ImageFieldfileというプロパティを取得すると仮定します。

ファイルのアップロード後、ImageField.fileプロパティで取得するオブジェクトは、アップロードの大きさに応じて、a file on disk or in memoryを表すTemporaryUploadedFileオブジェクトです。このオブジェクトは通常のPython file objectのように振る舞いますので、最初のサムネイルを作成するために一度読んだら、ファイルの最後に達しています。そのため、再度読み取ろうとすると(2番目のサムネイルを作成する)そこには何もないので、IOErrorです。 2番目のサムネイルを作成するには、seekをファイルの先頭に戻す必要があります。つまり、あなたのimage_resizer関数の先頭に行

image.seek(0) 

を追加することができます。

これは不要です!この問題は、作成する新しいサムネイルごとに画像を再読み込みするようにPython Imaging Libraryに依頼しているためです。これは時間の無駄です。イメージを一度読み取ってから、必要なすべてのサムネイルを作成する方がよい。

+0

あなたの明確な説明に感謝します!はい。イメージはリモートユーザによってアップロードされ、 ''タイプです。今私は 'IOError'を理解しています。私はコードを書き直して一度だけイメージを読み込みます! – enri

-2

私はそれがTemporaryUploadedFileであると推測しています...タイプ(画像)でこれを見つけてください。

import cStringIO 

if isinstance(image, TemporaryUploadedFile): 
    temp_file = open(image.temporary_file_path(), 'rb+') 
    content = cStringIO.StringIO(temp_file.read()) 
    image = Image.open(content) 
    temp_file.close() 

は、私は上記のコードの100%わからないんだけど...私はイメージ操作のために持っている2クラスから来ている...しかし、それを試してみます。

InMemoryUploadedFileの場合は、コードが機能するはずです。

+0

助けてくれてありがとう(私はcStringIOを発見しました)!私は異なる写真をバッチで作成するように解決したので、イメージを一度しか開きません。 – enri

+0

これは動作しません。 StringIOは有効なファイルオブジェクトではありません。 – Cerin

関連する問題