如何在不改变PNG图像尺寸的情况下减小文件大小?

6
我想用Python减小PNG文件的大小。我在互联网上查阅了很多资料,但是没有找到任何关于如何在不改变图像尺寸(即高度/宽度)的情况下减小图像文件大小的内容。我找到的是如何使用PIL或其他Python库更改图像尺寸的方法。
如何在保持图像尺寸不变的情况下减小图像文件大小呢?

只有一张图片,还是很多?请分享图片。你为什么想要这样做?硬盘很便宜。 - Mark Setchell
如果图像是彩色的,您可以将其转换为灰度(即丢弃颜色信息)。模糊可能是另一种减少信息内容的方法。 - martineau
我需要通过网络提供这些PNG图像,因此需要它们的尺寸较小。 - Ahsan Mukhtar
如果你真的非常需要使用PNG格式,也许可以尝试使用“pngcrush”工具。 - Mark Setchell
@MarkSetchell,好的。让我看看那个。 - Ahsan Mukhtar
3个回答

7
PNG是一种无损格式,但仍可以以无损方式进行压缩。Pillow的Image类带有一个接受compress_level参数的png写入器。
很容易证明它可以工作:
步骤1:加载通用RGB Lena图像以.png格式:
import os
import requests
from PIL import Image
from io import BytesIO

img_url = 'http://pngnq.sourceforge.net/testimages/lena.png'
response = requests.get(img_url)
img = Image.open(BytesIO(response.content))

步骤2:使用compress_level=0编写png:
path_uncompressed = './lena_uncompressed.png'
img.save(path_uncompressed,compress_level=0)
print(os.path.getsize(path_uncompressed))
> 691968

img_uncompressed: 691968 bytes

第三步:使用compress_level=9编写PNG文件:
path_compressed = './lena_compressed.png'
img.save(path_compressed,compress_level=9)
print(os.path.getsize(path_compressed))
> 406889

img_compressed: 406889 bytes

在这种情况下,我们得到了可观的30%压缩,没有明显的图像质量降低(这应该是无损压缩算法所期望的)。

1
压缩后的图像和原始图像包含完全相同的信息。一旦解压缩,数据完全相同,且不会有任何图像质量下降。 - Cris Luengo
请注意,默认情况下,PNG文件的压缩级别可能已设置为最大。 - Cris Luengo

4

PNG是一种无损格式,显然会占用更多的空间。

如果你只关心分辨率,那么你可以将它转换为任何有损形式,如JPG。

https://whatis.techtarget.com/definition/lossless-and-lossy-compression

转换后的尺寸将是相同的,但质量取决于所需的压缩程度。

将PNG转换为JPG的代码段:

from PIL import Image

im = Image.open("Picture2.png")
rgb_im = im.convert('RGB')
rgb_im.save('Picture2.jpg')

我希望它保存为PNG格式。有什么办法吗? - Ahsan Mukhtar

3
默认情况下,大多数PNG编写器将使用最大压缩设置,因此尝试更改它不会有太大帮助。虽然存在未压缩的PNG文件,但它们没有意义,我认为你不会遇到太多这样的文件。
因此,使PNG文件显着变小的唯一方法是减少存储的像素数量或减少存储的颜色数量。您明确表示不想减少像素数量,因此另一个选择是减少颜色数量。
大多数PNG文件将处于“真彩色”模式(每个像素通常具有24位,每个像素的红色、绿色和蓝色分量各占一个字节)。但是,也可以创建索引PNG文件。这些文件存储颜色映射(又称调色板)和每个像素的单个值,即颜色映射中的索引。例如,如果您选择了64个条目的颜色映射,则每个像素将需要6位来编码索引。您将存储64 * 3个字节+每个像素的3/4个字节(当然也会被压缩)。我在这个网站上发现了一些比较示例图像的文章,其中显示了在减少颜色时它们的外观以及文件最终变得多大。 这个问题展示了如何使用PIL将RGB图像转换为索引图像。
img.convert("P", palette=Image.ADAPTIVE)

这似乎生成了一个8位色彩映射,但PIL不支持更小的色彩映射。使用PyPNG模块可以让你写入任意数量颜色的PNG文件。"最初的回答"。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接