Python图像库(PIL),如何将图像压缩成所需的文件大小?

Jam*_*Lin 8 python compression image

我要求压缩文件大小小于500kb的任何上传图像,我在谷歌上搜索过,我只能看到:

 >>> foo = foo.resize((160,300),Image.ANTIALIAS)
 >>> foo.save("path\\to\\save\\image_scaled.jpg",quality=95)
Run Code Online (Sandbox Code Playgroud)

如果我采用这种方法,我将不得不在压缩后检查图像是否小于500kb,如果不是那么则去降低质量和尺寸.

有没有更好的方法呢?

Mar*_*som 11

JPEG压缩预先不可预测.您描述的方法,压缩和测量,再次尝试,是我所知道的唯一方法.

您可以尝试使用不同的质量设置压缩大量典型图像,以了解最佳起点,以及猜测设置更改将如何影响大小的方法.这将使您在没有太多迭代的情况下实现最佳尺寸.

您还可以将类似文件的对象传递给save不费心写入磁盘的函数,只计算字节数.一旦确定了最佳设置,就可以将其再次保存到实际文件中.

编辑:这是一个合适的字节计数文件对象的实现.size保存后再检查一下.

class file_counter(object):
    def __init__(self):
        self.position = self.size = 0

    def seek(self, offset, whence=0):
        if whence == 1:
            offset += self.position
        elif whence == 2:
            offset += self.size
        self.position = min(offset, self.size)

    def tell(self):
        return self.position

    def write(self, string):
        self.position += len(string)
        self.size = max(self.size, self.position)
Run Code Online (Sandbox Code Playgroud)

编辑2:这是使用上面的二进制搜索,以quality最小的尝试次数获得最佳.

def smaller_than(im, size, guess=70, subsampling=1, low=1, high=100):
    while low < high:
        counter = file_counter()
        im.save(counter, format='JPEG', subsampling=subsampling, quality=guess)
        if counter.size < size:
            low = guess
        else:
            high = guess - 1
        guess = (low + high + 1) // 2
    return low
Run Code Online (Sandbox Code Playgroud)