使用二进制(每像素1位)图像c ++

时间:2017-02-02 11:13:53

标签: c++ image monochrome

问题如下。有必要使用非常大的二进制图像(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中吗?

1 个答案:

答案 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二进制文件。