如何在 `vips` 工具中将图像转换为 RGBA?如何确保两个图像具有相同数量的波段?

How to convert image to RGBA in `vips` tool? How to make sure two images have the same number of bands?

我正在编写一个 shell 脚本来连接一些图像,我正在使用 vips 命令行,因为它对内存的要求很低(而且我打算使用非常大的图片)。

但是,如果一张图片是RGB,另一张是RGBA,则失败:

$ vips insert foo3.png foo4.png foo.png 64 0 --expand --background '0 0 0 0'
insert: images must have the same number of bands, or one must be single-band

$ file foo?.png
foo3.png: PNG image data, 1 x 1, 8-bit/color RGB, non-interlaced
foo4.png: PNG image data, 1 x 1, 8-bit/color RGBA, non-interlaced

如何在使用 vips 时将输入图像转换为 RGBA?我一直在搜索文档,但找不到它。

我也愿意用nip2 tool, which also uses libvips。我不愿意使用 ImageMagick(或类似工具),因为该脚本最终将处理大至 20k×20k 像素的图像,这需要几千兆字节的 RAM,比我现在多。

这不是最佳解决方案,但作为解决方法,如果输入图像足够小:

convert "foo3.png" "png32:tmp.png"
vips insert tmp.png foo4.png foo.png 64 0 --expand --background '0 0 0 0'

基本上,我使用 ImageMagick 转换为临时 RGBA 文件,然后对该文件使用 vips。它只适用于小文件。

我会用 pyvips 将整个内容写在 Python 中。例如:

#!/usr/bin/python3

import sys 
import pyvips

if len(sys.argv) < 3:
    print("usage: join outfile in1 in2 in3 ...")
    sys.exit(1)

def imopen(filename):
    im = pyvips.Image.new_from_file(filename, access="sequential")
    if not im.hasalpha():
        im = im.addalpha()

    return im

images = [imopen(filename) for filename in sys.argv[2:]]
image = images[0]
for tile in images[1:]:
    image = image.join(tile, "horizontal", expand=True)

image.write_to_file(sys.argv[1])

如果可能的话,我会使用 TIFF 而不是 PNG -- PNG 非常慢。

recent vips versions:

vips bandjoin_const source.png dest.png 255

255 表示不透明,0 表示透明。