Откройте огромный TIF в.NET и скопируйте части в новое изображение

Я ищу библиотеку, которая может открывать и копировать разделы большого файла TIFF. Я посмотрел на LibTiff.Net, который очень быстро открывает файл, но у него нет никаких функций для обрезки или копирования участков изображения. Мое изображение имеет размер 100 000 x 100 000 пикселей и создает System.Drawing.Bitmap такого размера вылетает приложение, поэтому преобразование в Bitmap во-первых, это не вариант.

Кто-нибудь может порекомендовать библиотеку.NET?

4 ответа

Решение

Если размер вашего файла на диске меньше 4 ГБ, я рекомендую вам еще раз взглянуть на LibTiff.Net. Даже с такими большими изображениями у вас есть несколько вариантов.

Прежде всего, проверьте, является ли ваше изображение мозаичным или раздетым. Tiff.IsTiled Метод даст вам ответ.

Если ваше изображение выложено мозаикой, то вам, вероятно, не стоит читать его, используя ReadScanline метод. Может быть лучше использовать ReadEncodedTile метод в этом случае.

Если ваши изображения удалены, чем вы можете использовать ReadScanline а также ReadEncodedStrip методы, чтобы прочитать это.

Если вы хотите использовать то, что ожидает System.Drawing.Bitmap чем пытаться использовать ReadRGBATile или же ReadRGBAStrip, Эти методы могут использоваться для создания растровых изображений из частей вашего изображения. Для этого нет примера, но Преобразование цветного TIFF в 32-битный System.Drawing.Bitmap должно дать вам почти всю необходимую информацию о том, как преобразовать плитку или полосу изображения в растровое изображение.

РЕДАКТИРОВАТЬ:

В LibTiff.Net 2.4.508 добавлена ​​поддержка BigTiff, поэтому также поддерживаются файлы размером более 4 ГБ.

Ваше изображение должно быть в формате BigTIFF, поскольку обычный TIFF не может быть больше 4 ГБ.

BigTIFF можно читать с модифицированной версией libtiff (доступной на веб-сайте BigTIFF), эта библиотека позволяет обрабатывать такие изображения так, как вам нужно, без загрузки всех пиксельных данных в память.

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

Atalasoft dotImage имеет эту способность, встроенную в декодер TIFF. Декодер реализует интерфейс IRegionReadable, который позволяет считывать прямоугольный участок с заданной страницы изображения в потоке.

В формате TIFF этот раздел будет учитывать тег ориентации, а в полосатом или мозаичном стиле используется минимальный набор плиток и полос для заполнения прямоугольника.

(отказ от ответственности, я работаю на Atalasoft, написал этот интерфейс и реализовал его в декодере TIFF)

Как упоминал Бобровский, вы должны проверить, является ли изображение вашего файла мозаичным или нет. Далее я представил код фрагмента, чтобы прочитать поток и обрезать верхнюю левую часть изображения.

using (Tiff input = Tiff.Open(@"imageFile.tif", "r"))
        {
            // get properties to use in writing output image file
            int width = input.GetField(TiffTag.IMAGEWIDTH)[0].ToInt();
            int height = input.GetField(TiffTag.IMAGELENGTH)[0].ToInt();
            int samplesPerPixel = input.GetField(TiffTag.SAMPLESPERPIXEL)[0].ToInt();
            int bitsPerSample = input.GetField(TiffTag.BITSPERSAMPLE)[0].ToInt();
            int photo = input.GetField(TiffTag.PHOTOMETRIC)[0].ToInt();

            int scanlineSize = input.ScanlineSize();    
            byte[][] buffer = new byte[height][]; 
            for (int i = 0; i < height; ++i)
            {
                buffer[i] = new byte[scanlineSize];
                input.ReadScanline(buffer[i], i);
            }



            using (Tiff output = Tiff.Open("splitedImage.tif", "w"))
            {
                output.SetField(TiffTag.SAMPLESPERPIXEL, samplesPerPixel);
                output.SetField(TiffTag.IMAGEWIDTH, width/2);
                output.SetField(TiffTag.IMAGELENGTH, height/2);
                output.SetField(TiffTag.BITSPERSAMPLE, bitsPerSample);
                output.SetField(TiffTag.ROWSPERSTRIP, output.DefaultStripSize(0));
                output.SetField(TiffTag.PHOTOMETRIC, photo);
                output.SetField(TiffTag.PLANARCONFIG, PlanarConfig.CONTIG);


                int c = 0;
                byte[][] holder = new byte[height][];

                for (int i = height/2; i < height; i++)
                //for (int j = 0; j < height/2 ; j++)
                {
                    holder[i] = buffer[i].Skip(buffer[i].Length/2).ToArray();

                    output.WriteScanline(holder[i], c);
                    c++;
                }
            }
        }

        System.Diagnostics.Process.Start("splitedImage.tif");

Для других частей изображения вы можете изменить диапазон "i" в цикле for.

Другие вопросы по тегам