Мне нужно обрабатывать большие изображения (20 000 x 20 000 пикселей) на C#. Открытие этих изображений напрямую не подходит из-за ограничений памяти, но я хочу разделить изображение на более мелкие части (обрезать). Я искал стороннюю библиотеку, которая могла бы помочь, но пока безрезультатно. Я пробовал FreeImage и ImageMagick, но они не могут открыть изображение размером 20 000x20x000 пикселей. Как я могу этого добиться?
Как обрезать огромное изображение
Ответы (5)
Мой текущий проект на работе состоит из программы просмотра/анализа изображений, способной загружать изображения размером более 16 ГБ. Вы должны использовать ручной файловый ввод-вывод, извлекать информацию из заголовка и создавать свои субизображения по запросу (или, если вы обрабатываете изображение, вы можете создать одну плитку и обработать ее на месте). Очень немногие библиотеки дадут вам возможность загружать/изменять изображения 20k на 20k (1,2 ГБ при 24bpp), а те, которые это делают, редко делают это с чем-то, напоминающим производительность (если это вызывает беспокойство).
Не знаю, поможет ли это, но вот статья на обработка изображений с помощью лямбда-выражений C#.
Я не знаю ни одной существующей библиотеки для этого.
Вам, вероятно, придется взломать поток файла изображения, найти место, где существуют данные о цвете и пикселях, прочитать часть данных о пикселях в массив и создать из него свое изображение.
Например, для формата файла BMP вам потребуется выполнить поиск в таблице цветов, загрузить таблицу цветов, затем перейдите к разделу массива пикселей, загрузите любое количество пикселей в массив, а затем создайте новое растровое изображение только с этими пикселями.
Я бы сделал это с ImageMagick. Существует довольно надежный .NET API, и, как правило, это лучший способ такой обработки изображений.
Посмотрите под .NET, часть пути вниз по странице.
http://www.imagemagick.org/script/api.php
Вот информация о том, как работает кадрирование в ImageMagick, для версии командной строки.
http://www.imagemagick.org/Usage/crop/#crop
Вы можете использовать встроенные библиотеки .Net.
Использовать
sourceBitmap = (Bitmap)Image.FromStream(sourceFileStream, false, false);
Это предотвратит кэширование данных изображения в памяти. Вы можете создать новое целевое растровое изображение, чтобы нарисовать подраздел этого массивного изображения:
var output = new Bitmap(outputWidth, outputHeight);
var outputGraphics = Graphics.FromImage(output);
outputGraphics.DrawImage(sourceBitmap, destRect, srcRect, GraphicsUnit.Pixel);
using (var fs = File.OpenWrite(outputFilePath))
{
output.Save(fs, System.Drawing.Imaging.ImageFormat.Png);
}
Где destRect может быть полным размером выходного изображения или меньшей областью.