1

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#?

1 Answer 1

2
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.

Sign up to request clarification or add additional context in comments.

2 Comments

Technically you should use data.Stride instead of bmp.Width in the Copy() call. It now works by accident.
Yes, using Stride is correct, but in this particular case Stride will always be Width * 4 (because Stride rounds up to 4-byte boundary, and we are using ARGB - 4 bytes per pixel, and even more, our image width is 320 = 80 * 4). Changed code anyway.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.