Создание растрового изображения из IntPtr

Я пытаюсь понять, как использовать API-интерфейс USB-видеокамеры, который не совсем понятен (по крайней мере, он, кажется, рассчитывает на предыдущие знания разработчика, и я не думаю, что понял "всю картину", каламбур)).

У меня есть следующий обработчик событий, который успешно получает данные, которые в данный момент я могу распечатать только на консоли:

    void  _camera_OnPreviewBitmap(IntPtr pbyteBitmap, uint dwBufferSize,
                                  uint dwWidth, uint dwHeight,
                                  uint dwFrameNo, uint dwPreviewPixelFormat) {

        Console.WriteLine(string.Format("{0}, {1}, {2}, {3}, {4}, {5}", pbyteBitmap, dwBufferSize, dwWidth, dwHeight, dwFrameNo, dwPreviewPixelFormat));

        //The callback function gets the image data as “IntPtr” type. 
        //When using “System.Runtime.InteropServices.Marshal.Copy”, the image data can copy to the array. 
        //When using “System.Runtime.InteropServices.Marchal.ReadByte”, the image data can get thedirectory. 
        //Sometimes the process speed is fast when receiving the image data after the image data copy to the array with 
        //“System.Runtime.InteropServices.Marchal.Copy”. 

    } 

Это дает мне такие результаты:

259129344, 1228800, 1280, 960, 195051, 1
250281984, 1228800, 1280, 960, 195052, 1
259129344, 1228800, 1280, 960, 195053, 1
250281984, 1228800, 1280, 960, 195054, 1
259129344, 1228800, 1280, 960, 195055, 1
250281984, 1228800, 1280, 960, 195056, 1
259129344, 1228800, 1280, 960, 195057, 1
250281984, 1228800, 1280, 960, 195058, 1
259129344, 1228800, 1280, 960, 195059, 1
250281984, 1228800, 1280, 960, 195060, 1
259129344, 1228800, 1280, 960, 195061, 1
250281984, 1228800, 1280, 960, 195062, 1

Таким образом, это согласуется с размерами изображения (1280 x 960), а 1228800 - это количество пикселей (размер буфера), а 1 для формата пикселей означает PIXEL_FORMAT_08_MONO_OR_RAW согласно перечислению формата пикселя API камеры (что также согласуется с этой камерой BW).

Мой вопрос:

Как я могу взять эту информацию и создать System.Drawing.Bitmap возразить с этим?

Я уже попробовал это, но безуспешно (по-видимому, изображение в градациях серого фактически не индексируется...):

        var bmp = new System.Drawing.Bitmap((int)dwWidth, (int)dwHeight, (int)dwBufferSize,
                                            PixelFormat.Format8bppIndexed, pbyteBitmap);

В конечном итоге это приводит к "общей ошибке GDI+".

1 ответ

Решение

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

Если изображение в градациях серого, вместо прямого указателя вы можете создать свое растровое изображение с 32bpp, блокировать биты, а затем установить значения байтов RGB для данных байтовых пикселей, вот пример (использование небезопасного кода для простоты и скорости):

Bitmap bmp = new Bitmap(1280, 960, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
var data = bmp.LockBits(new Rectangle(0, 0, 1280, 960), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppRgb);

byte* srcBmpData = (byte*)pbyteBitmap.ToPointer();
byte* dstBmpData = (byte*)data.Scan0.ToPointer();

for (int buc = 0; buc < 1280 * 960; buc++)
{
    int currentDestPos = buc * 4;
    dstBmpData[currentDestPos] = dstBmpData[currentDestPos + 1] = dstBmpData[currentDestPos + 2] = srcBmpData[buc];
}

bmp.UnlockBits(data);
Другие вопросы по тегам