WinApi-字节阵列到灰度8位位图(+性能)

本文关键字:性能 位图 8位 字节 阵列 灰度 WinApi- | 更新日期: 2023-09-27 18:01:04

我有一个字节数组,需要显示在桌面(或Form(上。我正在使用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);

WinApi-字节阵列到灰度8位位图(+性能)

SetDIBits的两个参数错误:

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