如何将图像转换为特定的文件大小?

时间:2016-02-15 20:54:09

标签: python django image pillow django-imagekit

我正在使用PillowDjangodjango-imagekit

我希望能够拥有一个个人资料图片模型字段(可能使用来自imagekit的ProcessedImageField类),它将获取任何图像,转换为JPEG,将其裁剪为150x150,并使其文件大小为5KB

前两个很容易:

profile_picture = imagekit.models.ProcessedImageField(upload_to=get_profile_picture_file_path,
                                                      format='JPEG',
                                                      processors=[ResizeToFill(height=150, width=150)]
                                                      )

但是如何确保文件大小为5KB?我可以在options={'quality': 60}中使用类似ProcessedImageField参数的内容,但这似乎只相对于原始文件大小(据我所知)。

解决方案不必使用django-imagekit,但这是首选。

2 个答案:

答案 0 :(得分:0)

也许是这样的。上传后检查图片大小并将其删除,或者在覆盖的save方法中减少更多:

class Images(models.Model):
    profile_picture = imagekit.models.ProcessedImageField(upload_to=get_profile_picture_file_path,
                                                  format='JPEG',
                                                  processors=[ResizeToFill(height=150, width=150)]
                                                  )

    def save(self, force_insert=False, force_update=False, using=None,
             update_fields=None):

        if os.stat(get_profile_picture_file_path + "/" + self.profile_picture.new_name).st_size > max_size:
            do_something_further_image_processing_to_decrease_size

        super(Images, self).save()

答案 1 :(得分:0)

我曾经有类似的问题,所以我决定使用从django调用的OS工具(jpegoptim,optipng等)在使用信号保存模型后优化图像(你也可以覆盖保存方法)。此工具可优化和消除图像中的元数据。另一方面,您可以研究150x150的jpg文件的平均压缩率和大小,并尝试猜测设置的最佳质量检查:(jpeg compression ratio

这是我保存后优化文件的代码,我使用简单的缩略图库,在保存后为我提供信号:

@receiver(saved_file)
def optimize_file(sender, fieldfile, **kwargs):
    optimize(fieldfile.path)


# thumbnail optimization
@receiver(thumbnail_created)
def optimize_thumbnail(sender, **kwargs):
    optimize(sender.path)

def optimize(path):
    """
    install image utilities
    apt-get install jpegoptim optipng pngcrush advancecomp
    :param path:
    :return:
    """
    # taken from trimage (http://trimage.org/)
    runString = {
        ".jpeg": u"jpegoptim -f --strip-all '%(file)s' ; chmod 644 '%(file)s'",
        ".jpg": u"jpegoptim -f --strip-all '%(file)s' ; chmod 644 '%(file)s'",
        ".png": u"optipng -force -o7 '%(file)s' && advpng -z4 '%(file)s' && pngcrush -rem gAMA -rem alla -rem cHRM -rem iCCP -rem sRGB -rem time '%(file)s' '%(file)s.bak' && mv '%(file)s.bak' '%(file)s' ; chmod 644 '%(file)s'"
    }

    ext = splitext(path)[1].lower()
    if ext in runString:
        subprocess.Popen(runString[ext] % {'file': path}, shell=True)