C#:模拟gdi GetBitmapBits函数和GdiFlush用位图填充字节数组
我创建了一个库,其中需要以位图的正确顺序填充 307200 个元素(320x240x4(=32bit))的字节数组,显示使用 RGBA 格式,我想避免正如我目前正在做的那样,使用互操作来使用 GetBitmapBits,而我更喜欢用 C# 代码编写它以了解如何在其上打印字节。
有人可以帮助我吗?
这是我的实际代码
/// <summary>
/// LONG GetBitmapBits(
/// __in HBITMAP hbmp,
/// __in LONG cbBuffer,
/// __out LPVOID lpvBits
/// );
/// </summary>
/// <param name="hbmp"></param>
/// <param name="cbBuffer"></param>
/// <param name="lpvBits"></param>
/// <returns></returns>
[DllImport("Gdi32", EntryPoint = "GetBitmapBits")]
private extern static long GetBitmapBits([In] IntPtr hbmp, [In] int cbBuffer, [Out] byte[] lpvBits);
[DllImport("Gdi32", EntryPoint = "GdiFlush")]
private extern static void GdiFlush();
private void FillPixelArray(Bitmap bmp, ref byte[] array, bool bw = false)
{
Color tmp;
if (!bw)
{
IntPtr hbmp = bmp.GetHbitmap();
GdiFlush();
GetBitmapBits(hbmp, array.Length * Marshal.SizeOf(typeof(byte)), array);
}
else
{
for (int x = 0; x < LgLcd.NativeConstants.LGLCD_BMP_WIDTH; ++x)
{
for (int y = 0; y < LgLcd.NativeConstants.LGLCD_BMP_HEIGHT; ++y)
{
tmp = bmp.GetPixel(x, y);
array[y * 160 + x] = (byte)((tmp.R == 255 && tmp.G == 255 && tmp.B == 255) ? 0 : 255);
}
}
}
}
另外,GetBitmapBits 比我在 C# 中可以实现的任何实现都快吗?
I created a lib where I need to fill a byte array of 307200 elements (320x240x4(=32bit)) in the correct order for a bitmap, the display uses the format RGBA, and I would like to avoid using interop to use GetBitmapBits as I'm doing at the moment, while I prefer writing it in c# code to understand how bytes are printed on it.
Can someone help me?
Here is my actual code
/// <summary>
/// LONG GetBitmapBits(
/// __in HBITMAP hbmp,
/// __in LONG cbBuffer,
/// __out LPVOID lpvBits
/// );
/// </summary>
/// <param name="hbmp"></param>
/// <param name="cbBuffer"></param>
/// <param name="lpvBits"></param>
/// <returns></returns>
[DllImport("Gdi32", EntryPoint = "GetBitmapBits")]
private extern static long GetBitmapBits([In] IntPtr hbmp, [In] int cbBuffer, [Out] byte[] lpvBits);
[DllImport("Gdi32", EntryPoint = "GdiFlush")]
private extern static void GdiFlush();
private void FillPixelArray(Bitmap bmp, ref byte[] array, bool bw = false)
{
Color tmp;
if (!bw)
{
IntPtr hbmp = bmp.GetHbitmap();
GdiFlush();
GetBitmapBits(hbmp, array.Length * Marshal.SizeOf(typeof(byte)), array);
}
else
{
for (int x = 0; x < LgLcd.NativeConstants.LGLCD_BMP_WIDTH; ++x)
{
for (int y = 0; y < LgLcd.NativeConstants.LGLCD_BMP_HEIGHT; ++y)
{
tmp = bmp.GetPixel(x, y);
array[y * 160 + x] = (byte)((tmp.R == 255 && tmp.G == 255 && tmp.B == 255) ? 0 : 255);
}
}
}
}
Another thing, is GetBitmapBits faster than any implementation I can do in C#?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
PS,您不需要在
ref byte[] array
中使用ref
- 数组已经是引用类型,并且您没有修改array
中的变量你的职能。PPS
GetBitmapBits
返回int
,而不是long
(不要与LONG
C 宏混淆)、GdiFlush
返回[return:MarshalAs(UnmanagementType.Bool)] bool
,而不是void
。P.S. you don't need
ref
inref byte[] array
- array is a reference type already, and you are not modifyingarray
variable in your function.P.P.S.
GetBitmapBits
returnsint
, notlong
(don't confuse withLONG
C macro),GdiFlush
returns[return:MarshalAs(UnmanagedType.Bool)] bool
, notvoid
.