【问题标题】:Django PIL : IOError Cannot identify image fileDjango PIL:IOError无法识别图像文件
【发布时间】:2012-03-30 21:39:51
【问题描述】:

我正在学习 Python 和 Django。

图像由用户使用 forms.ImageField() 提供。然后我必须对其进行处理以创建两个不同大小的图像。

当我提交表单时,Django 返回以下错误:

IOError at /add_event/
cannot identify image file

我调用resize函数:

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

我正在尝试找出问题所在,但我不知道该怎么做。提前谢谢你!

编辑
我解决了重写函数;现在它会批量创建不同的图像:

我调用resize函数:

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

谢谢大家!

【问题讨论】:

  • 它是在Image.open()上提出的?那里提供了什么路径?该路径中真的有有效的图像文件吗?
  • 是的,它是在Image.open() 上提出的,它的类型是<class 'django.core.files.uploadedfile.InMemoryUploadedFile'>。现在我正在尝试使用@gareth-rees 提出的解决方案来解决。
  • 如果你传递 Image.open() 一个文件对象,该文件对象需要之前以二进制模式打开。这可能是问题所在,但无法从您的代码中确定。

标签: python django image python-imaging-library


【解决方案1】:

作为cmets中的ilvar asksimage是一个什么样的对象?出于此答案的目的,我将假设它是来自远程用户上传的文件的 Django ImageFieldfile 属性。

文件上传后,您在ImageField.file 属性中获得的对象是TemporaryUploadedFile 对象,它可能代表a file on disk or in memory,具体取决于上传的大小。这个对象的行为很像普通的Python file object,所以在你读过它一次(制作第一个缩略图)后,你已经到达文件的末尾,所以当你再次尝试阅读它时(制作第二个缩略图),那里什么都没有,因此是IOError。要制作第二个缩略图,您需要 seek 回到文件的开头。所以你可以添加这一行

image.seek(0)

到您的 image_resizer 函数的开头。

但是这是不必要的!您遇到此问题是因为您要求 Python 图像库为您要创建的每个新缩略图重新读取图像。这是浪费时间:最好只阅读一次图像,然后创建所需的所有缩略图。

【讨论】:

  • 感谢您的清晰解释!是的,图像由远程用户上传,类型为<class 'django.core.files.uploadedfile.InMemoryUploadedFile'>。现在我了解了IOError,我将重写我的代码以仅读取一次图像!
【解决方案2】:

我猜这是 TemporaryUploadedFile ... 用 type(image) 找到这个。

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,您的代码应该可以工作!

【讨论】:

  • 感谢您的帮助(我发现了 cStringIO)!我解决了批量创建不同图片的问题,所以我只会打开一次图片。
猜你喜欢
  • 2015-06-25
  • 2020-05-26
  • 2017-09-11
  • 2015-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多