2012-03-30 193 views
7

我正在學習Python和Django。Django PIL:IOError無法識別圖像文件

圖像是由用戶使用forms.ImageField()提供的。然後我必須處理它以創建兩個不同大小的圖像。

當我提交表單,Django的返回以下錯誤:

IOError at /add_event/ 
cannot identify image file 

我所說的調整大小功能:

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) 

我得到連接錯誤時image_resizer被稱爲第二次:

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 2012-03-31 02:37:20

+0

是的,它在'Image.open()'上產生,它的類型是''。現在我正在嘗試使用@ gareth-rees提出的解決方案來解決問題。 – enri 2012-04-02 09:51:29

+0

如果您傳遞Image.open()文件對象,則該文件對象需要先前以二進制模式打開。這可能是問題所在,但從代碼中確定是不可能的。 – user240515 2012-07-19 17:32:01

回答

19

由於ilvar asks在評論中,什麼樣的對象是image?爲了這個答案,我將假設它是來自遠程用戶上傳文件的Django ImageFieldfile屬性。

上傳文件後,您在ImageField.file屬性中獲得的對象是TemporaryUploadedFile對象,該對象可能代表a file on disk or in memory,具體取決於上傳的大小。該對象的行爲非常類似於正常的Python file object,因此在讀完一次(製作第一個縮略圖)之後,即已到達文件末尾,以便當您嘗試再次讀取它(製作第二個縮略圖)時,沒有什麼,因此IOError。要製作第二個縮略圖,您需要seek回到文件的開頭。所以你可以添加一行

image.seek(0) 

image_resizer函數的開頭。

但是這是不必要的!您遇到此問題是因爲您要求Python Imaging Library重新讀取要創建的每個新縮略圖的圖像。這是浪費時間:最好只讀一次圖像,然後創建所有你想要的縮略圖。

+0

感謝您的明確解釋!是的,圖像是由遠程用戶上傳的,其類型爲'。現在我理解了'IOError',我將重寫我的代碼來只讀一次圖像! – enri 2012-04-02 09:40:17

-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() 

我不完全確定上面的代碼...來自2個類我有圖像處理...但試試看。

如果是InMemoryUploadedFile您的代碼應該工作!

+0

感謝您的幫助(我發現了cStringIO)!我解決了批量創建不同的照片,所以我只打開一次圖片。 – enri 2012-04-02 13:43:47

+0

這不起作用。 StringIO不是有效的文件對象。 – Cerin 2012-08-16 22:25:43