5

我正在使用PillowDjangodjango-imagekit

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

前两个很简单:

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

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

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

4

2 回答 2

0

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

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

@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)
于 2016-07-19T19:15:47.750 回答
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()
于 2016-02-15T23:20:15.970 回答