libvips 有一个 arrayjoin 运算符,可以将一组图块连接到一个大图像中。
你可以像这样使用它(在 linux 命令行上):
vips arrayjoin "$(ls *.jpeg | sort -t_ -k2g -k1g)" x.tif[tile,pyramid,compression=jpeg] --across 20
这将加载当前目录中的所有 JPG 图像,将它们组合成一个巨大的网格,包含 20 张图像,并写入 TIFF 金字塔。显然,您需要检查网格的大小,并调整 across 参数。
$() 部分将x_y.jpg 形式的文件名按数字顺序先按 y 排序,然后按 x 排序。没有它,瓷砖会被调换,很烦人。
假设重叠为 0。如果您的图块有重叠,您需要设置 hspacing 和 vspacing 选项来控制图块的定位方式。例如:
vips arrayjoin "$(ls *.jpg | sort -t_ -k2g -k1g)" x.tif --across 20 --hspacing 254 --vspacing 254
将每 254 个像素水平和垂直放置图块。
arrayjoin 必须能够打开所有输入图像,因此它需要大量文件描述符。大多数 linux 默认每个进程一次最多打开 1024 个文件,因此您可能需要提高该数量。通常您只需编辑几个配置文件并注销并再次登录。我将我的系统设置为 65536,但您可以使用任何数字。
Windows 对每个进程有 2000 个文件的硬性限制,您无法更改。您需要在该平台上分段组装。
这是一个有效的例子。首先,创建一个没有重叠的深度缩放金字塔:
john@kiwi:~/pics/x$ vips dzsave ~/pics/k2.jpg x --overlap 0
john@kiwi:~/pics/x$ cd x_files/11
john@kiwi:~/pics/x/x_files/11$ ls
0_0.jpeg 0_7.jpeg 1_5.jpeg 2_3.jpeg 3_1.jpeg 3_8.jpeg 4_6.jpeg 5_4.jpeg
0_1.jpeg 0_8.jpeg 1_6.jpeg 2_4.jpeg 3_2.jpeg 4_0.jpeg 4_7.jpeg 5_5.jpeg
0_2.jpeg 1_0.jpeg 1_7.jpeg 2_5.jpeg 3_3.jpeg 4_1.jpeg 4_8.jpeg 5_6.jpeg
0_3.jpeg 1_1.jpeg 1_8.jpeg 2_6.jpeg 3_4.jpeg 4_2.jpeg 5_0.jpeg 5_7.jpeg
0_4.jpeg 1_2.jpeg 2_0.jpeg 2_7.jpeg 3_5.jpeg 4_3.jpeg 5_1.jpeg 5_8.jpeg
0_5.jpeg 1_3.jpeg 2_1.jpeg 2_8.jpeg 3_6.jpeg 4_4.jpeg 5_2.jpeg
0_6.jpeg 1_4.jpeg 2_2.jpeg 3_0.jpeg 3_7.jpeg 4_5.jpeg 5_3.jpeg
您可以看到它是由 6 宽和 9 下的瓷砖组成的网格。
现在重新组装瓷砖并写成 TIFF 金字塔:
john@kiwi:~/pics/x/x_files/11$ vips arrayjoin "$(ls *.jpeg | sort -t_ -k2g -k1g)" x.tif[tile,pyramid,compression=jpeg] --across 6
john@kiwi:~/pics/x/x_files/11$ vipsheader x.tif
x.tif: 1524x2286 uchar, 3 bands, srgb, tiffload_stream
使用 pyvips 会是这样的:
#!/usr/bin/env python3
import pyvips
tiles_across = 142
tiles_down = 150
tiles = [pyvips.Image.new_from_file(f"{x}_{y}.jpeg", access="sequential")
for y in range(tiles_down) for x in range(tiles_across)]
im = pyvips.Image.arrayjoin(tiles, across=tiles_across)
im.write_to_file("x.jpg")
在这台笔记本电脑上加入 21,000 个磁贴大约需要 10 分钟和 6GB 内存。