Skip to main content
 首页 » 编程设计

python之尝试在 Django 中创建缩略图时获取无法识别图像文件

2025年05月04日42soundcode

<分区>

Possible Duplicate:
resize image on save

我正在尝试在 Django 中创建一个缩略图,我正在尝试构建一个专门用于生成缩略图的自定义类。如下

from cStringIO import StringIO 
from PIL import Image 
 
class Thumbnail(object): 
 
    SIZE = (50, 50) 
 
    def __init__(self, source): 
        self.source = source 
        self.output = None 
 
    def generate(self, size=None, fit=True): 
        if not size: 
            size = self.SIZE 
 
        if not isinstance(size, tuple): 
            raise TypeError('Thumbnail class: The size parameter must be an instance of a tuple.') 
 
        # resize properties 
        box = size 
        factor = 1 
        image = Image.open(self.source) 
        # Convert to RGB if necessary 
        if image.mode not in ('L', 'RGB'):  
            image = image.convert('RGB') 
        while image.size[0]/factor > 2*box[0] and image.size[1]*2/factor > 2*box[1]: 
            factor *=2 
        if factor > 1: 
            image.thumbnail((image.size[0]/factor, image.size[1]/factor), Image.NEAREST) 
 
        #calculate the cropping box and get the cropped part 
        if fit: 
            x1 = y1 = 0 
            x2, y2 = image.size 
            wRatio = 1.0 * x2/box[0] 
            hRatio = 1.0 * y2/box[1] 
            if hRatio > wRatio: 
                y1 = int(y2/2-box[1]*wRatio/2) 
                y2 = int(y2/2+box[1]*wRatio/2) 
            else: 
                x1 = int(x2/2-box[0]*hRatio/2) 
                x2 = int(x2/2+box[0]*hRatio/2) 
            image = image.crop((x1,y1,x2,y2)) 
 
        #Resize the image with best quality algorithm ANTI-ALIAS 
        image.thumbnail(box, Image.ANTIALIAS) 
 
        # save image to memory 
        temp_handle = StringIO() 
        image.save(temp_handle, 'png') 
        temp_handle.seek(0) 
 
        self.output = temp_handle 
 
        return self 
 
    def get_output(self): 
        self.output.seek(0) 
        return self.output.read() 

该类(class)的目的是让我可以在不同位置使用它来动态生成缩略图。该类工作完美,我直接在 View 下对其进行了测试。我在表单的保存方法中实现了缩略图类,以在保存时调整原始图像的大小。

在我的设计中,我有两个缩略图字段。我能够生成一个缩略图,如果我尝试生成两个缩略图,它就会崩溃,而且我已经被困了几个小时,不确定是什么问题。

这是我的模型

class Image(models.Model): 
    article         = models.ForeignKey(Article) 
    title           = models.CharField(max_length=100, null=True, blank=True) 
    src             = models.ImageField(upload_to='publication/image/') 
    r128            = models.ImageField(upload_to='publication/image/128/', blank=True, null=True) 
    r200            = models.ImageField(upload_to='publication/image/200/', blank=True, null=True) 
 
    uploaded_at     = models.DateTimeField(auto_now=True) 

这是我的表格

class ImageForm(models.ModelForm): 
    """ 
 
    """ 
    class Meta: 
        model = Image 
        fields = ('src',) 
 
 
    def save(self, commit=True): 
        instance = super(ImageForm, self).save(commit=True) 
 
 
        instance.r128 = SimpleUploadedFile( 
                    instance.src.name, 
                    Thumbnail(instance.src).generate((128, 128)).get_output(), 
                    content_type='image/png' 
                ) 
 
 
        instance.r200 = SimpleUploadedFile( 
            instance.src.name, 
            Thumbnail(instance.src).generate((200, 200)).get_output(), 
            content_type='image/png' 
        ) 
 
        if commit: 
            instance.save() 
        return instance 

奇怪的是,当我在保存表单中删除包含 instance.r200 的行时。它工作正常,它制作缩略图并成功存储。一旦我添加了第二个缩略图,它就失败了..

知道这里做错了什么吗?

谢谢

更新:

根据评论请求,我附加了错误跟踪

IOError at /en/publication/new/ 
 
cannot identify image file 
 
Request Method:     POST 
Request URL:    http://127.0.0.1:8000/en/publication/new/?image-extra= 
Django Version:     1.4.2 
Exception Type:     IOError 
Exception Value:     
 
cannot identify image file 
 
Exception Location:     /Users/mo/Projects/pythonic/snowflake-env/lib/python2.7/site-packages/PIL/Image.py in open, line 1980 
Python Executable:  /Users/mo/Projects/pythonic/snowflake-env/bin/python 
Python Version:     2.7.2 

更新

尝试创建打印语句,下面是输出

Source: publication/image/tumblr_m9o7244nZM1rykg1io1_1280_11.jpg 
Source: publication/image/tumblr_m9o7244nZM1rykg1io1_1280_11.jpg 
ERROR:root:cannot identify image file 
ERROR:django.request:Internal Server Error: /en/publication/new/ 
Traceback (most recent call last): 
  File "/Users/mo/Projects/pythonic/snowflake-env/lib/python2.7/site-packages/django/core/handlers/base.py", line 111, in get_response 
    response = callback(request, *callback_args, **callback_kwargs) 
  File "/Users/mo/Projects/pythonic/snowflake-env/lib/python2.7/site-packages/django/contrib/auth/decorators.py", line 20, in _wrapped_view 
    return view_func(request, *args, **kwargs) 
  File "/Users/mo/Projects/pythonic/snowflake-env/lib/python2.7/site-packages/django/db/transaction.py", line 209, in inner 
    return func(*args, **kwargs) 
  File "/Users/mo/Projects/pythonic/snowflake-env/snowflake/snowflake/apps/publication/views.py", line 69, in new 
    formset.save() 
  File "/Users/mo/Projects/pythonic/snowflake-env/lib/python2.7/site-packages/django/forms/models.py", line 497, in save 
    return self.save_existing_objects(commit) + self.save_new_objects(commit) 
  File "/Users/mo/Projects/pythonic/snowflake-env/lib/python2.7/site-packages/django/forms/models.py", line 628, in save_new_objects 
    self.new_objects.append(self.save_new(form, commit=commit)) 
  File "/Users/mo/Projects/pythonic/snowflake-env/lib/python2.7/site-packages/django/forms/models.py", line 727, in save_new 
    obj = form.save(commit=False) 
  File "/Users/mo/Projects/pythonic/snowflake-env/snowflake/snowflake/apps/publication/forms.py", line 113, in save 
    Thumbnail(instance.src).generate((200, 200)).get_output(), 
  File "/Users/mo/Projects/pythonic/snowflake-env/snowflake/snowflake/apps/core/utils.py", line 23, in generate 
    image = Image.open(self.source) 
  File "/Users/mo/Projects/pythonic/snowflake-env/lib/python2.7/site-packages/PIL/Image.py", line 1980, in open 
    raise IOError("cannot identify image file") 
IOError: cannot identify image file 

如图所示,第一个图像打印和处理成功,第二个图像失败。

更新

在缩略图类中应用 copy() 后回溯错误更新

ERROR:root:cannot identify image file 
ERROR:django.request:Internal Server Error: /en/publication/new/ 
Traceback (most recent call last): 
  File "/Users/mo/Projects/pythonic/snowflake-env/lib/python2.7/site-packages/django/core/handlers/base.py", line 111, in get_response 
    response = callback(request, *callback_args, **callback_kwargs) 
  File "/Users/mo/Projects/pythonic/snowflake-env/lib/python2.7/site-packages/django/contrib/auth/decorators.py", line 20, in _wrapped_view 
    return view_func(request, *args, **kwargs) 
  File "/Users/mo/Projects/pythonic/snowflake-env/lib/python2.7/site-packages/django/db/transaction.py", line 209, in inner 
    return func(*args, **kwargs) 
  File "/Users/mo/Projects/pythonic/snowflake-env/snowflake/snowflake/apps/publication/views.py", line 69, in new 
    formset.save() 
  File "/Users/mo/Projects/pythonic/snowflake-env/lib/python2.7/site-packages/django/forms/models.py", line 497, in save 
    return self.save_existing_objects(commit) + self.save_new_objects(commit) 
  File "/Users/mo/Projects/pythonic/snowflake-env/lib/python2.7/site-packages/django/forms/models.py", line 628, in save_new_objects 
    self.new_objects.append(self.save_new(form, commit=commit)) 
  File "/Users/mo/Projects/pythonic/snowflake-env/lib/python2.7/site-packages/django/forms/models.py", line 727, in save_new 
    obj = form.save(commit=False) 
  File "/Users/mo/Projects/pythonic/snowflake-env/snowflake/snowflake/apps/publication/forms.py", line 113, in save 
    f128.write(Thumbnail(instance.src).generate((128, 128)).get_output()) 
  File "/Users/mo/Projects/pythonic/snowflake-env/snowflake/snowflake/apps/core/utils.py", line 15, in __init__ 
    self._pilImage = Image.open(self.source) 
  File "/Users/mo/Projects/pythonic/snowflake-env/lib/python2.7/site-packages/PIL/Image.py", line 1980, in open 
    raise IOError("cannot identify image file") 
IOError: cannot identify image file 

更新

最后,我设法让它工作,但我必须将文件流式传输到 self.source as belo

def __init__(self, source): 
    self.source = StringIO(file(source.path, "rb").read()) 
    self.output = None 
 
    self._pilImage = Image.open(self.source) 

是上面的理想方法吗?每次点击时读取文件是个好主意吗?如果不是,我有什么选择?