从Django ImageField.file制作缩略图并转换回图像

时间:2012-09-06 01:22:08

标签: python django python-imaging-library

所以我在Django中有一个用于将图像上传到ImageField的表单。这很好用。然后我将request.FILES ['image']传递给一个名为MakeThumbnail的函数进行进一步处理。

MakeThumbnail效果不佳。我已经从一系列StackOverflow线程中组装了这个,但我认为我缺少一些关键概念。这是我的代码。

    def MakeThumbnail(file):
        img = Image.open(file)
        thumbnail = img.thumbnail((128, 128), Image.ANTIALIAS)
        thumbnailString = StringIO.StringIO(thumbnail)
        newFile = ContentFile(thumbnailString)
        return newFile

stacktrace说我在这一行上失败了:newFile = ContentFile(thumbnailString)。它给我以下错误:预期读缓冲区,找到实例

我认为在查看局部变量后,我可能会在thumbnail = img.thumbnail((128,128),Image.ANTIALIAS)中失败:

thumbnailString : <StringIO.StringIO instance at 0x0000000003B39748>
file : <InMemoryUploadedFile: Desert.jpg (image/jpeg)>
thumbnail : None
img : <PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=128x96 at 0x3B25C08>

请注意,缩略图是无。它应该包含一些东西。有人对我有一些提示吗?

谢谢你!

3 个答案:

答案 0 :(得分:5)

非常感谢你的帮助,Jan Spurny。我在你的帮助下想出来了。因此,当img保存到thumbnailString时,需要做一些事情。上面的代码实际上会产生错误,因为我们将实例传递给ContentFile而不是缓冲区。无论如何,我们只需要调用thumbnailString.read()。但是thumbnailString.read()返回''。事实证明我们需要事先做thumbnailString.seek(0)。但这也不起作用!

最终,我能够使用InMemoryUploadedFile将图像文件恢复为Django文件。

以下是代码从头到尾的样子:

from django.core.files.uploadedfile import InMemoryUploadedFile
import StringIO
def MakeThumbnail(file):
    img = Image.open(file)
    img.thumbnail((128, 128), Image.ANTIALIAS)
    thumbnailString = StringIO.StringIO()
    img.save(thumbnailString, 'JPEG')
    newFile = InMemoryUploadedFile(thumbnailString, None, 'temp.jpg', 'image/jpeg', thumbnailString.len, None)
    return newFile

答案 1 :(得分:3)

关于Image.thumbnail的PIL文档:

  

修改图像以包含其自身的缩略图版本,不大   超过给定的大小。此方法计算适当的缩略图   保持图像方面的大小,调用draft方法   配置文件阅读器(如果适用),最后调整大小   图像。

这意味着您的缩略图位于img,而不是thumbnail变量,因为Image.thumbnail不返回任何内容(因此None

另一个错误是将PIL.Image置于StringIO。您最好save将其StringIO

所以你的代码应该更像这样:

def MakeThumbnail(file):
    img = Image.open(file)
    img.thumbnail((128, 128), Image.ANTIALIAS)
    thumbnailString = StringIO.StringIO()
    img.save(thumbnailString, 'PNG')
    newFile = ContentFile(thumbnailString)
    return newFile

答案 2 :(得分:0)

我认为你需要将图像的完整路径传递给ur函数而不是路径的实例。

EX:
models.py
logo = models.ImageField(upload_to=os.path.join(MEDIA_ROOT, "logo"), null=True, default=None)

U need to pass
def MakeThumbnail(logo.path):