如何使用PIL优化调色板图像的大小? [英] How can I optimize the palette image size with PIL?

查看:143
本文介绍了如何使用PIL优化调色板图像的大小?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

My goal is to draw some polygons on a black image such that the total size of the resulting image is as small as possible.

因此,我在Wiki上阅读了一篇有关索引颜色的文章(链接),这对我来说是一个不错的选择(因为我应该只支持黑色,而其他5种颜色,即总共6种颜色),并且png图像格式应该支持'P'模式(即调色板图像).

So I read an article on wiki about indexed colors (link) and it seems like it's a good choice for me (since I should support only a black color and the 5 other ones, i.e. 6 colors in total) and png image format should support 'P' mode (i.e., palette images).

这就是我创建这段代码的原因,以查看六种颜色和1224x1024图像可获得的图像大小:

That's the reason I created this piece of code to see what image size I'll get for 6 colors and 1224x1024 image:

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个字节,这对我来说似乎太大了.

The result image size is 768 bytes which seems too much for me.

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

Is there something I can fix in my code to make the result image size even smaller?

推荐答案

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

768 bytes does not seem unreasonable to me to represent a 1.2 megapixel image. You could try running the file produced by PIL through pngcrush like this to see if it can shave a few bytes:

pngcrush input.png result.png


如果您真的只想在黑色背景上绘制一些纯色多边形,建议您使用矢量格式,例如SVG 此处的示例,而不是栅格格式PNG .


If you really only want to draw a few solid-coloured polygons on a black background, I would suggest you look to a vector format, such as SVG example here rather than raster format PNG et al.

如果需要,您还可以使用 rsvg 将SVG图像渲染为PNG.但是从您的问题中,您的应用程序或需要这么小的图像的原因都不清楚,因此我不知道这是否适合您.

You can also use rsvg to render SVG images to PNG if you need to but neither your application, nor the reason you need such small images is clear from your question, so I have no idea if that is an option for you.

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

Here is a 300 byte SVG image with a black background, 2 rectangles and a polygon like a red star shape at top-left:

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

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

You could load an SVG into a Numpy array like this:

#!/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表示的图像我作为一个简单文本文件给出的示例:


If you are hell-bent on making the files even smaller, at the price of reduced compatibility with other image viewers, you could devise your own very simple format somewhat similar to SVG, so you could store the image represented by the SVG example I gave as a simple text file:

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文件加载到任何网络浏览器中来查看它们,或者使用Terminal中的 ImageMagick 将其制作为PNG文件,如下所示:

You can view your SVG files by loading them into any web-browser, or make one into a PNG with ImageMagick in Terminal like this:

magick input.svg result.png

这篇关于如何使用PIL优化调色板图像的大小?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆