Эффективный способ написать очень большое количество страниц TIFF с помощью libtiff.net

Я использую следующий код для записи последовательности 16-битных изображений в градациях серого (пустой массив для целей этого вопроса) в многостраничный TIFF:

int numberOfPages = 1000;
int width = 256;
int height = 256;
string fileName = "test.tif";

ushort[] image = new ushort[width * height];
byte[] buffer = new byte[width * height * sizeof(ushort)];

Stopwatch stopWatch = new Stopwatch();

using (Tiff output = Tiff.Open(fileName, "w"))
{
    if (output == null)
    {
        return;
    }
    stopWatch.Start();
    for (int i = 0; i < numberOfPages; i++)
    {
        Buffer.BlockCopy(image, 0, buffer, 0, buffer.Length);

        output.SetField(TiffTag.IMAGEWIDTH, width);
        output.SetField(TiffTag.IMAGELENGTH, height);
        output.SetField(TiffTag.SAMPLESPERPIXEL, 1);
        output.SetField(TiffTag.BITSPERSAMPLE, 16);
        output.SetField(TiffTag.ORIENTATION, Orientation.TOPLEFT);
        output.SetField(TiffTag.XRESOLUTION, 96);
        output.SetField(TiffTag.YRESOLUTION, 96);
        output.SetField(TiffTag.PLANARCONFIG, PlanarConfig.CONTIG);
        output.SetField(TiffTag.PHOTOMETRIC, Photometric.MINISBLACK);
        output.SetField(TiffTag.COMPRESSION, Compression.NONE);
        output.SetField(TiffTag.FILLORDER, FillOrder.MSB2LSB);
        output.SetField(TiffTag.SUBFILETYPE, FileType.PAGE);
        output.SetField(TiffTag.PAGENUMBER, i + 1, numberOfPages);

        output.WriteEncodedStrip(0, buffer, buffer.Length);

        output.WriteDirectory();
    }
    stopWatch.Stop();
}

Debug.WriteLine(stopWatch.ElapsedMilliseconds);

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

1000 страниц --- 3130 мс

2000 страниц --- 11778 мс

3000 страниц --- 25830 мс

Я также пытался использовать режим добавления внутри цикла, но получил аналогичные результаты.

Я делаю это неправильно или я должен ожидать таких накладных расходов?


person getter1    schedule 10.02.2017    source источник
comment
Скорее всего, вы сталкиваетесь с узкими местами ввода-вывода/памяти. Вы профилировали использование памяти и диска?   -  person Dan Field    schedule 10.02.2017
comment
@DanField Я не знаю, как сделать правильное профилирование, но если я заменю вывод Tiff на FileStream, средняя скорость передачи данных составит 250 МБ / с, а время записи окажется линейным. 1000 кадров или 10 000 кадров не имеют большого значения, как TIFF.   -  person getter1    schedule 10.02.2017


Ответы (1)


Я профилировал ваш код в Visual Studio («Анализ» -> «Профилировщик производительности») с помощью инструмента «Использование ЦП», и вот мои выводы:

Для 5000 страниц около 91% времени уходит на написание каталогов TIFF. Не данные, а структура, описывающая каталог. Это выглядело подозрительно, поэтому я посмотрел, что WriteDirectory делает так долго.

WriteDirectory пытается связать предыдущий и вновь созданный каталоги. Для этого он ищет предыдущий каталог, всегда начиная с первого каталога. Чем больше каталогов в TIFF, тем больше времени требуется для добавления каждого нового.

Боюсь, изменить это поведение без изменения кода библиотеки невозможно.

person Bobrovsky    schedule 10.02.2017