WinApi - 字节数组到灰色8位位图(+性能)

时间:2013-02-25 13:59:12

标签: c# winapi bitmap bytearray draw

我有一个需要在桌面(或表单)上显示的字节数组。我正在使用WinApi而不确定如何一次设置所有像素。字节数组在我的内存中,需要尽快显示(只有WinApi)。

我正在使用C#,但简单的伪代码对我来说没问题:

// create bitmap
byte[] bytes = ...;// contains pixel data, 1 byte per pixel
HDC desktopDC = GetWindowDC(GetDesktopWindow());
HDC bitmapDC = CreateCompatibleDC(desktopDC);
HBITMAP bitmap = CreateCompatibleBitmap(bitmapDC, 320, 240);
DeleteObject(SelectObject(bitmapDC, bitmap));

BITMAPINFO info = new BITMAPINFO();
info.bmiColors = new tagRGBQUAD[256];
for (int i = 0; i < info.bmiColors.Length; i++)
{
    info.bmiColors[i].rgbRed = (byte)i;
    info.bmiColors[i].rgbGreen = (byte)i;
    info.bmiColors[i].rgbBlue = (byte)i;
    info.bmiColors[i].rgbReserved = 0;
}
info.bmiHeader = new BITMAPINFOHEADER();
info.bmiHeader.biSize = (uint) Marshal.SizeOf(info.bmiHeader);
info.bmiHeader.biWidth = 320;
info.bmiHeader.biHeight = 240;
info.bmiHeader.biPlanes = 1;
info.bmiHeader.biBitCount = 8;
info.bmiHeader.biCompression = BI_RGB;
info.bmiHeader.biSizeImage = 0;
info.bmiHeader.biClrUsed = 256;
info.bmiHeader.biClrImportant = 0;
// next line throws wrong parameter exception all the time
// SetDIBits(bitmapDC, bh, 0, 240, Marshal.UnsafeAddrOfPinnedArrayElement(info.bmiColors, 0), ref info, DIB_PAL_COLORS);

// how do i store all pixels into the bitmap at once ?
for (int i = 0; i < bytes.Length;i++)
    SetPixel(bitmapDC, i % 320, i / 320, random(0x1000000));

// draw the bitmap
BitBlt(desktopDC, 0, 0, 320, 240, bitmapDC, 0, 0, SRCCOPY);

当我尝试用SetPixel()单独设置每个像素时,我看到的单色图像没有灰色,只有黑色和白色。如何正确创建灰度位图以进行显示?我该如何快速完成?

<小时/> 的更新 在WinApi中,该调用最终会出现在我的程序之外的错误中。无法捕捉异常:

public const int DIB_RGB_COLORS = 0;
public const int DIB_PAL_COLORS = 1;

[DllImport("gdi32.dll")]
public static extern int SetDIBits(IntPtr hdc, IntPtr hbmp, uint uStartScan, uint cScanLines, byte[] lpvBits, [In] ref BITMAPINFO lpbmi, uint fuColorUse);

// parameters as above
SetDIBits(bitmapDC, bitmap, 0, 240, bytes, ref info, DIB_RGB_COLORS);

1 个答案:

答案 0 :(得分:1)

其中两个SetDIBits参数错误:

  • lpvBits - 这是图像数据,但您正在传递调色板数据。您应该传递bytes数组。
  • lpBmi - 这没关系 - BITMAPINFO结构同时包含BITMAPINFOHEADER和调色板,因此您无需单独传递调色板。我对你的另一个问题的回答描述了如何声明结构。
  • fuColorUse - 这描述了调色板的格式。您正在使用RGB调色板,因此您应该通过DIB_RGB_COLORS