【问题标题】:How to compress a picture less than a limit file size using python PIL library?如何使用 python PIL 库压缩小于限制文件大小的图片?
【发布时间】:2018-08-13 23:00:14
【问题描述】:

我需要将图片发送到另一个地方,它要求图片大小必须小于 512kb。
我使用PIL 来处理我从网上下载的图片。所以我不知道下一张图片的尺寸是多少,代码如下:

from PIL import Image
picture_location = '/var/picture/1233123.jpg'
compressed_picture_location = '/var/picture/1233123_compressed.jpg'
im = Image.open(picture_location)
quality = 75
im.save(compressed_picture_location, quality=quality)
im.save()

问题是压缩后的图片的文件大小不是原始图片的75%或者75%*75%,所以我要压缩,stat,再压缩,无法选择合适的质量值。

还有其他方法可以解决这个问题吗? 请帮助或尝试提供一些想法如何实现这一目标。

【问题讨论】:

  • 因为压缩是一组离散的过程,我能看到的唯一方法是编写一个暴力破解它的脚本。在你开始之前,你不知道它会是什么。如果你愿意,我可以在下面弹出一个脚本。
  • 不幸的是,JPEG 就是这样工作的。您也许可以通过使用 FileIO 对象而不是每次都写入磁盘来加快重复试验,尽管由于磁盘缓存,我不希望这会更快。
  • 您的进度有什么更新吗?
  • 我发现我公司使用的oss服务为压缩图片提供了特定的后缀,通过使用它我解决了这个问题。 :p 但是在技术方法上,我仍然找不到一个干净的解决方案。

标签: python python-imaging-library


【解决方案1】:

当您使用 PIL 更改质量时,图像的尺寸不会更改,它只是使用 JPEG 压缩更改图像的质量。默认值为 80,因此将值更改为 75 不会减少太多的尺寸,您可以将值更改为 60 左右而不会损失很多图片质量。该值以对数方式减少,因此如果您想要精确的数学,您可以阅读有关 JPEG 压缩的信息。 https://math.dartmouth.edu/archive/m56s14/public_html/proj/Marcus_proj.pdf

【讨论】:

    【解决方案2】:

    不幸的是,这是 JPEG 压缩的一个属性,并且没有严格的反函数(如果你想要大规模的效率,你可以用数学方法计算它)。

    但是,您可以低效地强制计算并通过以下方式使其接近。如果您不想要相同的大小,只需将质量更改为缩放因子,它应该会类似地工作。

    import os
    from PIL import Image
    
    def compress_under_size(size, file_path):
        '''file_path is a string to the file to be custom compressed
        and the size is the maximum size in bytes it can be which this 
        function searches until it achieves an approximate supremum'''
    
        quality = 90 #not the best value as this usually increases size
    
        current_size = os.stat(file_path).st_size
    
        while current_size > size or quality == 0:
            if quality == 0:
                os.remove(file_path)
                print("Error: File cannot be compressed below this size")
                break
    
            compress_pic(file_path, quality)
            current_size = os.stat(file_path).st_size
            quality -= 5
    
    
    def compress_pic(file_path, qual):
        '''File path is a string to the file to be compressed and
        quality is the quality to be compressed down to'''
        picture = Image.open(file_path)
        dim = picture.size
    
        picture.save(file_path,"JPEG", optimize=True, quality=qual) 
    
        processed_size = os.stat(file_path).st_size
    
        return processed_size
    
    for file in os.listdir("pics"):
        try:
            pic = f"./pics/{file}"
            compress_under_size(10000,pic)
        except Exception:
            pass
    

    【讨论】:

    • 我并没有真正检查过来源,我只是把它打出来了。如果有错误请告诉我,我会修复它。
    • 非常感谢!!!!!!修改了代码使其工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-12
    • 1970-01-01
    • 2023-03-05
    • 2011-06-21
    • 2011-09-20
    相关资源
    最近更新 更多