【问题标题】:WinApi - Byte Array to Gray 8-bit Bitmap (+Performance)WinApi - 字节数组到灰色 8 位位图(+性能)
【发布时间】:2013-02-25 13:59:11
【问题描述】:

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

【问题讨论】:

    标签: c# winapi bitmap bytearray draw


    【解决方案1】:

    SetDIBits参数中有两个错误:

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

    【讨论】:

    • 感谢您在这两个问题上提供帮助。但是在更改参数后应用程序崩溃并且我无法捕获异常。请查看更新。
    • 我尝试使用您的 SetDIBits 声明并将 BITMAPINFO 中的 SizeConst 设置为 256。它有效。还有其他几个错误。对 CreateCompatibleBitmap 的调用应使用桌面 DC,否则您将获得单色位图(因为新 DC 中的默认位图是单色的)。您不应该在 SelectObject 的返回值上调用 DeleteObject(您应该在完成后将原始对象选择回 DC,并删除您的新对象)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-07
    • 1970-01-01
    • 1970-01-01
    • 2020-05-07
    相关资源
    最近更新 更多