使用PIL将多个PNG合并为一个透明的PNG

0 投票
1 回答
1409 浏览
提问于 2025-04-18 08:40

我有很多小的png图片,想把它们合并成一张png文件,我用Python来完成这个工作,下面是我的代码:

from PIL import Image,ImageDraw  
import os,math

def combine_images(path,out,padding=1):
    imgs=[]
    min_width,max_width,min_height,max_height=-1,-1,-1,-1
    for infile in os.listdir(path):
        f,ext=os.path.splitext(infile)
        if ext== ".png":
            im=Image.open(os.path.join(path,infile))
            imgs.append(im)
            min_width = im.size[0] if min_width<0 else  min(min_width,im.size[0])
            max_width = im.size[0] if max_width<0 else  max(max_width,im.size[0])
            min_height = im.size[1] if min_height<0 else  min(min_height,im.size[0])
            max_height = im.size[1] if max_height<0 else  max(max_height,im.size[0])
    #calculate the column and rows
    num = len(imgs)
    column_f = math.ceil(math.sqrt(num))
    row_f = math.ceil(num / column_f)

    column = int(column_f)
    row = int(row_f)

    #out image
    box=(max_width + padding*2,max_height + padding*2)
    out_width = row * box[0]
    out_height = column * box[1]

    //out_image=Image.new('L', (out_width,out_height), color=transparent)
    out_image=Image.new("RGB", (out_width, out_height))
    for y in range(row):
        for x in range(column):
            index = (y * column) + x
            if index < num:
                out_image.paste(imgs[index],(x * box[0],y * box[1]))
    out_image.save(out)

combine_images('icon','t.png')

这个逻辑很简单,先读取某个文件夹里的png图片,计算这些图片的数量和大小,然后创建一张新图片,把它们一个一个粘贴上去。为了让最终的图片尽量呈现出正方形的形状,我还做了一些额外的计算。

不过,我得到的结果是这样的:http://pbrd.co/1kzErSc

我遇到了两个问题:

1. 我无法让输出的图片透明。

2. 看起来我的图标布局在图片中浪费了太多空间。

我想知道有没有办法解决这些问题?

1 个回答

0
out_image=Image.new("RGB", (out_width, out_height))

在创建输出图像时,你需要指定想要一个透明通道。

out_image=Image.new("RGBA", (out_width, out_height))

关于浪费的空间,有两点可以考虑:

  1. 这重要吗?如果你只关心文件大小(而不是图像的尺寸),可以检查一下图像的文件大小是否真的增加了。因为PNG格式是经过压缩的,所以这可能并不重要。

  2. 在加载图像后,按高度对图像进行排序,将相似高度的图像分组,然后为每组调整网格大小。不过,如果使用这些图像的应用程序需要猜测每个图标的大小,这种方法可能就不太管用了。

撰写回答