c # сохранение очень больших растровых изображений в формате JPEG (или любой другой сжатый формат) - PullRequest
9 голосов
/ 23 ноября 2011

В настоящее время я работаю с очень большими изображениями, которые в основном создаются путем сшивания множества меньших изображений (например, программного обеспечения для панорамы или фото-мозаики). Чтобы избежать исключений нехватки памяти (в памяти есть только «карты» того, как расположить меньшие изображения), я написал некоторый код, сохраняющий эти изображения построчно в виде растровых изображений, используя BinaryWriter и LockBits. Пока все хорошо.

Проблема теперь в том, что я хотел бы сохранить эти изображения также в формате JPEG (или PNG). Поскольку я довольно новичок в c #, на данный момент я могу думать только о двух путях:

1) Аналогично процедуре сохранения растрового изображения. Генерация заголовка в формате jpeg и сохранение больших изображений построчно, как-то раньше сжимая их. Я не знаю, как выполнить сжатие.

2) Потоковая передача уже сохраненного растрового изображения в память и сохранение его в формате jpeg.

Поскольку второй подход казался более простым, я попробовал что-то вроде этого:

FileStream fsr =
    new FileStream("input.bmp", FileMode.Open, FileAccess.Read);
FileStream fsw =
    new FileStream("output.jpg", FileMode.CreateNew, FileAccess.Write);

EncoderParameters encoderParameters = new EncoderParameters(1);
encoderParameters.Param[0] =
    new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 80L);

Bitmap bmp = new Bitmap(fsr);
bmp.Save(fsw, GetEncoder(ImageFormat.Jpeg), encoderParameters);
bmp.Dispose();

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

Я был бы более чем рад любым предложениям о том, как решить или обойти эту проблему!

Ответы [ 3 ]

1 голос
/ 24 ноября 2011

Обратите внимание, что сжатие JPEG имеет ряд важных нетривиальных недостатков:

1) JPEG с потерями, поэтому вы не сможете восстановить то же изображение.Это может быть вполне приемлемо, но если вам нужно точно восстановить исходное изображение, тогда PNG - это путь.

2) JPEG выровнен по границам 8 пикселей.Если вы склеиваете изображения, размеры которых не кратны 8, по ширине или высоте, вы получите некоторые сильные артефакты на границах изображения

Учитывая ваш вариант использования, я бы рекомендовал не Сшивайте изображения вместе и используйте стандартный алгоритм сжатия, такой как PNG или Zlib, для каждого меньшего изображения.Вы все еще можете сохранить полученные сжатые потоки в одном файле.Преимущество заключается в том, что вы можете напрямую «прыгать» в положение небольшого изображения, которое вы хотите извлечь, что сэкономит * много * памяти.

Недостатком является то, что вы не можете "визуально просмотреть" все меньшие изображения в одно большое (вам нужно будет создать программу для этого использования).

0 голосов
/ 24 ноября 2011

(поскольку в заголовке написано "или любой другой сжатый формат")

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

Вы можете попробовать LibTiff.Net (бесплатный, коммерческий, с открытым исходным кодом, написанный только на C #) для выполнения этой задачи.

Есть статья Основные сведения о возможностях библиотеки с информацией о IO изображений, ориентированных на полосы и плитки (во второй части статьи).

Отказ от ответственности: я работаю на компанию.

0 голосов
/ 24 ноября 2011

Я подозреваю, что вы не можете сделать это в .NET, но вы всегда можете вызвать библиотеку C, чтобы выполнить тяжелую работу.Я сам этим не пользовался, но предлагаю вам взглянуть на библиотеку GraphicsMagick .Это библиотека C с лицензированием, которая позволяет использовать ее как с открытым исходным кодом, так и в коммерческих целях, и, похоже, она может делать то, что вам нужно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...