GDI+ общая ошибка сохранения растрового изображения, созданного из памяти с использованием LockBits

Общая ошибка GDI+ при сохранении растрового изображения, очевидно, является общей проблемой, согласно моим исследованиям SO и Интернета. Учитывая следующий упрощенный фрагмент:

byte[] bytes = new byte[2048 * 2048 * 2];

for (int i = 0; i < bytes.Length; i++)
{
    // set random or constant pixel data, whatever you want
}

Bitmap bmp = new Bitmap(2048, 2048, PixelFormat.Format16bppGrayScale);
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, 2048, 2048), ImageLockMode.ReadWrite, bmp.PixelFormat);
System.Runtime.InteropServices.Marshal.Copy(bytes, 0, bmpData.Scan0, 8388608);
bmp.UnlockBits(bmpData);
bmp.Save(@"name.bmp");

Это приводит к общей ошибке 0x80004005. Говорят, что обычной причиной этого являются блокировки компонентов, но я здесь ничего не вижу. Я просто слепой? Путь, по которому я сохраняю, существует, конечно, создается только пустой файл bmp (0B).

Справочная информация: я получаю пиксельные данные из драйвера камеры, который я передаю в.NET с помощью оболочки C++/CLI, поэтому приведенный выше объект Bitmap возвращается вызовом функции. Но так как этот маленький пример уже дает сбой, я думаю, что с адаптером все в порядке.

Любые предложения высоко ценятся!

1 ответ

Решение
   Bitmap bmp = new Bitmap(2048, 2048, PixelFormat.Format16bppGrayScale);

GDI+ исключения довольно бедны, у вас будет мало надежды на диагностику двух ошибок. Меньший - это ваш вызов Save(), он не определяет формат изображения, который вы хотите сохранить. По умолчанию используется PNG, а не BMP, как вы и надеялись.

Но основным является PixelFormat.Format16bppGrayScale. Когда GDI+ разрабатывался задолго до появления.NET, все по-прежнему использовали ЭЛТ вместо ЖК-мониторов. ЭЛТ были довольно хороши в отображении гаммы цветов. Хотя это и хорошо, еще не было ЭЛТ, которые могли бы отображать 65536 различных серых цветов. Больше всего ограничен ЦАП в видеоадаптере, чипе, который преобразует значение цифрового пикселя в аналоговый сигнал для ЭЛТ. ЦАП, который может конвертировать с 16-битной точностью на частоте 100 МГц или более, пока еще технологически неосуществим. Microsoft рискнула усовершенствовать технологию отображения, чтобы сделать это когда-нибудь возможным, поэтому определил Format16bppGrayScale как формат пикселей, который может когда-нибудь стать доступным.

Этого не произошло. Скорее наоборот, ЖК-дисплеи значительно хуже в цветовом разрешении. Типичные ЖК-панели могут разрешать только 6 бит цвета, а не 8 бит, доступных в пиксельном формате. Переход к 16-битному цветовому разрешению потребует значительного технологического прорыва.

Таким образом, они догадались неправильно, и, поскольку формат пикселей бесполезен, GDI+ на самом деле не имеет кодировщика изображений, который может записывать 16-битный формат изображения в градациях серого. Kaboom, когда вы пытаетесь сохранить его на диск, независимо от выбранного вами формата изображения.

На самом деле используется шкала яркости 16 бит на пиксель, в радиологическом изображении используется этот пиксельный формат. С очень дорогими дисплеями, чтобы сделать его действительно полезным. Такое оборудование, однако неизменное, использует собственный формат изображения, DICOM является обычным выбором. GDI+ не имеет кодека для этого.

Вам нужно будет пойти за покупками в библиотеку, которая поддерживает формат изображения, который хочет ваш клиент. Lead Tools - горилла в тысячу фунтов в этом сегменте.

PixelFormat.Format32bppArgb похоже, у меня работает на Ubuntu 20 с использованием GDI.

var bitmapdata = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly,
                PixelFormat.Format32bppArgb);

Ошибка, которую я получал, была

System.ArgumentException: 'Parameter is not valid.'
at System.Drawing.SafeNativeMethods.Gdip.CheckStatus(Int32 status)
   at System.Drawing.Bitmap.LockBits(Rectangle rect, ImageLockMode flags, PixelFormat format, BitmapData bitmapData)
   at System.Drawing.Bitmap.LockBits(Rectangle rect, ImageLockMode flags, PixelFormat format)
Другие вопросы по тегам