问题如下。有必要使用非常大的二进制图像(100000x100000像素)。最初使用Qt的QImage类,它支持Format_Mono格式,将图像存储为每像素1位。一般来说,一切都很好,直到事实证明QPainter有限的光栅化器和绘制尺寸更短的图像(32767x32767)不能,它只是切断。
我无法将图像组合超过32767x32767。然后,我开始仔细研究各个库。据我所知,OpenCV不支持这种格式。关于ImageMagick,它支持将图像构造为每像素一位,并以相同的格式保存。然而,虽然使用图像仍然以每像素8位存储,因此出现RAM不足。然后我决定尝试CImg,但它不支持1bbp格式,据我所知:
一个实例图像的已用内存的总大小(以字节为单位) 然后是宽度x高度x深度x暗淡x尺寸(T)
当sizeof(T)当然不能小于sizeof(char)......
有趣的是QImage原则上如何使用Format_Mono格式,但老实说,我在源代码中纠缠不清。
所以,我有下一个问题。是否有一个库实现了创建和使用二进制图像的能力,在这种情况下,它们实际上是以每像素1位的形式存储在RAM中吗?
答案 0 :(得分:2)
libvips可以处理巨大的1位图像。它将每个字节解压缩到一个像素进行处理,但它只保留当前正在处理的图像部分在内存中,所以你应该没问题。
例如,这个小程序会产生一个100,000 x 100,000像素的黑色图像,然后在命令行中的随机位置粘贴所有图像:
#!/usr/bin/env python
import sys
import random
import gi
gi.require_version('Vips', '8.0')
from gi.repository import Vips
# this makes a 8-bit, mono image of 100,000 x 100,000 pixels, each pixel zero
im = Vips.Image.black(100000, 100000)
for filename in sys.argv[2:]:
tile = Vips.Image.new_from_file(filename, access = Vips.Access.SEQUENTIAL)
im = im.insert(tile,
random.randint(0, im.width - tile.width),
random.randint(0, im.height - tile.height))
im.write_to_file(sys.argv[1])
我可以像这样运行程序:
$ vipsheader wtc.tif
wtc.tif: 9372x9372 uchar, 1 band, b-w, tiffload
$ mkdir test
$ for i in {1..1000}; do cp wtc.tif test/$i.tif; done
$ time ./insert.py x.tif[bigtiff,squash,compression=ccittfax4] test/*.tif
real 1m31.034s
user 3m24.320s
sys 0m7.440s
peak mem: 6.7gb
输出文件名[]
设置图像写入选项。在这里,我启用了传真压缩并设置了squash
选项。这意味着8位一个频段图像应该被压缩到1位进行写入。
峰值记忆结果来自top
中观看RES。遗憾的是6.7gb相当大,因为它必须为1,000个输入图像中的每一个保留输入缓冲区。
如果使用平铺的1位tiff,则可以删除access =
选项并使用需要随机访问的运算符,例如rotate。如果你试图旋转一个条带tiff,vips将必须将整个图像解压缩到一个你可能不想要的临时磁盘文件。
vips拥有一系列合理的标准图像处理操作符,因此您可以将它们粘合在一起,从而实现您想要的功能。如果需要,可以使用C或C ++添加新运算符。
为简洁起见,该示例在Python中,但如果您愿意,可以使用Ruby,PHP,C,C ++,Go,JavaScript或命令行。它配备了所有Linux和BSD,它在自制软件,MacPorts和fink上,还有Windows二进制文件。