2012-03-30 2 views
7

저는 Python과 Django를 배우고 있습니다.Django PIL : IOError 이미지 파일을 식별 할 수 없습니다.

이미지는 forms.ImageField()를 사용하여 사용자가 제공합니다. 그런 다음 크기가 다른 두 개의 이미지를 만들기 위해이를 처리해야합니다. image_resizer이 두 번째로 호출 될 때 나는 오류 ko를 얻을

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 

: 나는 양식을 제출하면

는, 장고는 다음과 같은 오류를 반환

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 

버전 :
장고 1.3.1 01 23, 파이썬 2.7.1
PIL 1.1.7

내가 문제를 발견하기 위해 노력하고있어,하지만 난 어떻게 해야할지 모르겠어요. 미리 감사드립니다!

EDIT I ​​함수 재기록 해결
; 지금은 일괄 적으로 서로 다른 이미지를 만듭니다 그래서

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입니까? 이 대답의 목적 상 리모트 사용자가 업로드 한 파일에서 오는 장고 ImageFieldfile 속성이라고 가정합니다.

파일 업로드 후 ImageField.file 속성에서 가져 오는 개체는 업로드 크기에 따라 a file on disk or in memory을 나타내는 TemporaryUploadedFile 개체입니다. 이 객체는 보통 Python file object처럼 동작하므로 첫 번째 축소판을 만들기 위해 한 번 읽은 후에는 파일의 끝에 도달하여 다시 읽으려고 할 때 (두 번째 축소판을 만들 때) 거기에는 아무 것도 없으므로 IOError입니다. 두 번째 미리보기 이미지를 만들려면 seek 파일의 시작 부분으로 되돌아 가야합니다. 따라서 기능을 시작하려면

image.seek(0) 

줄을 추가 할 수 있습니다.

이것은 필요하지 않습니다. 이 문제는 파이썬 이미징 라이브러리에 생성하려는 새로운 각 축소판에 대한 이미지를 다시 읽으려고 요청하기 때문에 발생합니다. 이는 시간 낭비입니다. 이미지를 한 번만 읽은 다음 원하는 모든 미리보기 이미지를 만드는 것이 좋습니다.

+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 % 확실하지 않다 ... 나는 이미지 조작을 위해있어이 개 클래스에서 온다 ...하지만 그것을 시도를 제공합니다.

InMemoryUploadedFile 인 경우 코드가 작동해야합니다.

+0

도움을 주셔서 감사합니다 (나는 cStringIO를 발견했습니다)! 나는 이미지를 한 번만 열어 볼 수 있도록 다른 사진을 일괄 적으로 만들지 만 해결했습니다. – enri

+0

이것은 작동하지 않습니다. StringIO는 유효한 파일 객체가 아닙니다. – Cerin

관련 문제