2017-02-02 3 views
0

Проблема следующая. Необходимо работать с очень большими двоичными изображениями (100000x100000 пикселей). Первоначально он использовал класс QImage Qt, он поддерживает формат Format_Mono, который сохраняет изображение в виде 1 бит на пиксель. И вообще, все было хорошо, пока не выяснилось, что QPainter имеет ограниченный растеризатор и рисовать изображения, размер которых короче (32767x32767) не может быть, он просто отключен.Работа с двоичными (1 бит на пиксель) изображения C++

Мне не удалось комбинировать изображения более чем на 32767x32767. Затем я стал внимательно смотреть на отдельные библиотеки. OpenCV, как я понимаю, не поддерживает этот формат. Что касается ImageMagick, он поддерживает построение изображения как одноразрядное на пиксель и сохраняет его в том же формате. Однако при работе с изображением все еще сохраняется 8 бит на пиксель и, следовательно, возникает нехватка ОЗУ. Тогда я решил попробовать CImg, но это не Suppor 1bbp формат, как я понимаю:

общий размер использованной памяти для одного экземпляра изображения (в байтах) затем «ширина х высота х глубина х тусклый х SizeOf (Т)

Где SizeOf (T), конечно, не может быть меньше, чем SizeOf (Char) ...

Это было интересно, как QImage в принципе работает с форматом Format_Mono, но честно говоря, я запутался в исходном коде.

Итак, у меня есть следующий вопрос. Есть ли библиотека, которая реализовала возможность создавать и работать с бинарными изображениями, и в этом случае они действительно хранятся в виде 1 бит на пиксель в ОЗУ?

ответ

2

libvips может обрабатывать огромные 1 бит изображения. Он распаковывает их на один пиксель на каждый байт для обработки, но он сохраняет только часть изображения, которое в настоящее время обрабатывается в памяти, поэтому вы должны быть в порядке.

Например, эта маленькая программа делает 100000 х 100000 пикселей, черное изображение, а затем вставляет во всех изображений из командной строки на случайных позициях:

#!/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 

The [] на имя выходного файла опций набор записи изображений. Здесь я разрешаю сжатие факса и установку опции squash. Это означает, что 8-битные однополосные изображения должны быть сжаты до 1 бит для записи.

Максимальный результат от просмотра RES в top. 6.7gb довольно велико, к сожалению, поскольку он должен поддерживать входные буферы для каждого из 1000 входных изображений.

Если вы используете черепичный 1-битный tiff, вы можете удалить опцию access = и использовать операторы, которым нужен произвольный доступ, например, вращать. Если вы попытаетесь повернуть strip tiff, vips придется распаковать все изображение во временный файл диска, который вам, вероятно, не нужен.

vips имеет разумный диапазон стандартных операторов обработки изображений, поэтому вы можете делать то, что хотите, просто склеивать их вместе. Вы можете добавить новых операторов на C или C++, если хотите.

Этот пример приведен в Python для краткости, но вы можете использовать Ruby, PHP, C, C++, Go, JavaScript или командную строку, если хотите. Он поставляется со всеми Linuxes и BSD, он находится на домашнем компьютере, MacPorts и fink, и есть двоичный файл Windows.

+0

спасибо. и что, если я создам какое-то изображение и попытаюсь нарисовать на нем другое изображение, это будет работа в стиле потоковой передачи? – bronstein87

+0

Да, вы можете вставить одно изображение в другое. В Python 'im = im.insert (sub, 100, 100)' вставляет изображение 'sub' в изображение' im' в координате (100, 100). http://www.vips.ecs.soton.ac.uk/supported/current/doc/html/libvips/libvips-conversion.html#vips-insert – user894763

+0

Прошу прощения, но можете ли вы ответить на еще один мой вопрос. В вашем примере вы загрузили свое огромное изображение из файла. Но что, если нужно СОЗДАТЬ такое большое изображение, используя vips_black или какой-нибудь другой конструктор? Если я правильно тебя понимаю, я не могу этого сделать? – bronstein87

Смежные вопросы