C#:模拟gdi GetBitmapBits函数和GdiFlush用位图填充字节数组

发布于 2024-10-10 09:10:09 字数 1632 浏览 6 评论 0原文

我创建了一个库,其中需要以位图的正确顺序填充 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

冬天的雪花 2024-10-17 09:10:09
var data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
    System.Drawing.Imaging.ImageLockMode.ReadOnly,
    System.Drawing.Imaging.PixelFormat.Format32bppArgb);
Marshal.Copy(data.Scan0, array, 0, data.Stride * data.Height);
bmp.UnlockBits(data);

PS,您不需要在 ref byte[] array 中使用 ref - 数组已经是引用类型,并且您没有修改 array 中的变量你的职能。

PPS GetBitmapBits 返回 int,而不是 long(不要与 LONG C 宏混淆)、GdiFlush 返回 [return:MarshalAs(UnmanagementType.Bool)] bool,而不是 void

var data = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),
    System.Drawing.Imaging.ImageLockMode.ReadOnly,
    System.Drawing.Imaging.PixelFormat.Format32bppArgb);
Marshal.Copy(data.Scan0, array, 0, data.Stride * data.Height);
bmp.UnlockBits(data);

P.S. you don't need ref in ref byte[] array - array is a reference type already, and you are not modifying array variable in your function.

P.P.S. GetBitmapBits returns int, not long (don't confuse with LONG C macro), GdiFlush returns [return:MarshalAs(UnmanagedType.Bool)] bool, not void.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文