首页 > 解决方案 > Django 使用 Pillow 以不同格式保存图像

问题描述

我有我正在为我的学校制作的这个网站,我需要优化它,就像很多一样。

因此,我决定以 jpeg-2000 和 webp 等下一代格式提供我所有的压缩图像。使用 Pillow,这是我目前所拥有的:

class Bulletin(models.Model):
     banner = models.ImageField(upload_to='banner/', blank=True)

     def save(self, *args, **kwargs):
        super().save()
        if self.banner:
            thumbnail = Image.open(self.banner.path)
            resized = thumbnail.resize((1280, 620))
            resized.save(self.banner.path, quality=60)

所以我认为这会压缩图像(如果我在上面的代码中犯了错误,请告诉我)。

所以现在我希望能够以多种格式保存这张图片我希望上传的一张图片以这些格式保存:

我正在考虑在我的模型横幅上创建更多字段,例如 field banner_webp,然后我将其转换为 webp 并在保存期间将转换后的图像保存到该字段。

问题是我不知道如何使用 Pillow 转换图像,或者如何做我所要求的。感谢帮助。

标签: djangoimageformatpython-imaging-library

解决方案


约翰已经找到了一个可行的解决方案。我建议对此进行以下更改:

  • 假设公告有更多字段可能会在不更改横幅的情况下发生更改:您不需要在每个save()公告上重新编码图像。如果您将编码放入其自己的函数中,则可以在上传视图中专门调用该函数,如果这是您的代码中修改此值的唯一位置。有可能检测save()该字段是否已更改,因此这也是一种选择。
  • 如果您保留自定义save()方法:您应该在调用中传递参数supersuper().save(*args, **kwargs)
  • 您无需删除旧扩展名:您可以将图像命名为“whatever.jpg.webp”。它不会混淆计算机,而且我认为这个名称非常清楚地表明它是对原始文件的重新编码。此外,这允许您保持原始文件原样,以防有一天您决定要使用其他参数对图像进行编码,例如使用不同的质量设置。
  • 对重新编码的图像文件路径使用统一的访问器可以防止一些与拼写错误相关的错误。
class Bulletin(models.Model):
    BANNER_REENCODE_FORMATS = ["jpg", "jp2", "webp"]
    banner = models.ImageField(upload_to='banner/', blank=True)

    def reencoded_banner_path(self, file_format="jpg"):
        assert file_format in self.BANNER_REENCODE_FORMATS
        return self.banner.path + "." + file_format

    def reencode_banner(self):
        image = Image.open(self.banner.path).convert("RGB").resize((1280, 620))
        for extension in self.BANNER_REENCODE_FORMATS:
            image.save(self.reencoded_banner_path(extension), quality=60)

使用以下模板标签:

@register.filter(name='reencoded_banner_path')
@stringfilter
def reencoded_banner_path(bulletin, format):
    return bulletin.reencoded_banner_path(format)

你可以在你的模板中使用它:

{{ bulletin|reencoded_banner_path:"webp" }}

请注意,您可能希望对图像上传有一些重命名逻辑,以便在用户上传两个具有相同文件名的文件时不会中断。


推荐阅读