如何使用PIL优化调色板图像的大小?

时间:2019-03-31 11:33:37

标签: python image python-imaging-library

我的目标是在黑色图像上绘制一些多边形,以使所得图像的总尺寸尽可能小。

因此,我在Wiki上阅读了一篇有关索引颜色(link)的文章,这似乎对我来说是一个不错的选择(因为我应该只支持黑色,而其他5种颜色,即总共支持6种颜色) )和png图片格式应支持'P'模式(即palette images)。

这就是我创建这段代码的原因,以了解我将获得6种颜色和1224x1024图像的图像大小:

from PIL import Image, ImageDraw
# Create a black 1224x1024 image
img = Image.new('P', (1224, 1024))
img.putpalette([
    0, 0, 0,  # black background
    236, 98, 98, # red color
    236, 98, 97,
    236, 98, 96,
    236, 98, 95,
    236, 98, 94,
])

draw = ImageDraw.Draw(img)
# Draw a random red polygon at the top left corner of the image
draw.polygon(xy=list(1,1,2,2,3,3,4,4), fill=1)
del draw

img.save('1.png', format='PNG')

结果图像大小为768字节,这对我来说似乎太大了。

我是否可以在代码中修复某些问题,以使结果图像的大小变得更小?

1 个答案:

答案 0 :(得分:3)

768字节对我来说代表1.2兆像素的图像似乎并不合理。您可以尝试像这样通过pngcrush运行PIL生成的文件,以查看它是否可以剃除一些字节:

pngcrush input.png result.png

如果您真的只想在黑色背景上绘制一些纯色多边形,建议您使用矢量格式,例如SVG example here,而不要使用栅格格式PNG et al < / em>。

如果需要,您也可以使用rsvg将SVG图像渲染为PNG,但是您的应用程序以及需要如此小的图像的原因都不能从您的问题中弄清楚,所以我不知道这是否是一个您的选择。

这是一个300字节的SVG图像,具有黑色背景,2个矩形和一个像红色星形一样的多边形,位于左上角:

<svg width="1224" height="1024">
  <rect width="100%" height="100%" fill="black"/>
  <polygon points="9.9, 1.1, 3.3, 21.78, 19.8, 8.58, 0, 8.58, 16.5, 21.78" fill="red"/>
  <rect x="100" y="200" width="100" height="400" fill="blue"/>
  <rect x="800" y="280" width="100" height="200" fill="lime"/>
</svg>

enter image description here


您可以像这样将SVG加载到Numpy数组中:

#!/usr/bin/env python3

import cairosvg
import io
from PIL import Image

def svgRead(filename):
   """Load an SVG file and return image in Numpy array"""
   # Make memory buffer
   mem = io.BytesIO()
   # Convert SVG to PNG in memory
   cairosvg.svg2png(url=filename, write_to=mem)
   # Convert PNG to Numpy array
   return np.array(Image.open(mem))

# Read SVG file into Numpy array
res = svgRead('image.svg')

如果您迫切希望缩小文件的大小,以降低与其他图像查看器的兼容性为代价,则可以设计自己的类似于SVG的非常简单的格式,从而可以存储SVG表示的图像我作为一个简单文本文件给出的示例:

b,1224,1024,#00000
r,100,200,100,400,#0000ff
r,800,280,100,200,#00ff00
p,9.9,1.1,3.3,21.78,19.8,8.58,0,8.58,16.5,21.78,#ff0000

我做了127个字节。


您可以通过将SVG文件加载到任何Web浏览器中来查看它们,或者使用 ImageMagick 在Terminal中将其制成PNG,如下所示:

magick input.svg result.png