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

时间:2022-09-01 21:23:14

I am working with Pillow, Django, and django-imagekit.

我正在使用Pillow,Django和django-imagekit。

I am looking to be able to have a profile picture model field (probably using the ProcessedImageField class from imagekit) that will take any image, convert to JPEG, crop it to 150x150, and make its file size 5KB.

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

The first two are easy:

前两个很简单:

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

But how can I ensure the file size is 5KB? I could use something like the options={'quality': 60} parameter in ProcessedImageField, but that seems to be only relative to the original file size (to my knowledge).

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

Solutions don't have to use django-imagekit, but that would be preferred.

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

2 个解决方案

#1


0  

Maybe in such way. Check the size of image after uploaded and remove it or decrease more in overridden save method:

也许就是这样。上传后检查图像大小并将其删除,或者在重写保存方法中减少更多:

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()

#2


0  

I used to have a similar issue, so I decided to optimize the images using OS tools (jpegoptim, optipng, etc) called from django after save the model using signals (you can do overriden save method too). This tools optimize and eliminate metadata from your images. In the other hand you could study the average compression ratio and size for jpg files of 150x150 and try to guess the best quality to setup check this: (jpeg compression ratio)

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

This is my code for optimize files after save them, I'm using easy thumbnails library which provide me signals after save:

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

@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)

#1


0  

Maybe in such way. Check the size of image after uploaded and remove it or decrease more in overridden save method:

也许就是这样。上传后检查图像大小并将其删除,或者在重写保存方法中减少更多:

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()

#2


0  

I used to have a similar issue, so I decided to optimize the images using OS tools (jpegoptim, optipng, etc) called from django after save the model using signals (you can do overriden save method too). This tools optimize and eliminate metadata from your images. In the other hand you could study the average compression ratio and size for jpg files of 150x150 and try to guess the best quality to setup check this: (jpeg compression ratio)

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

This is my code for optimize files after save them, I'm using easy thumbnails library which provide me signals after save:

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

@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)