C #: имитация функции gdi GetBitmapBits и GdiFlush для заполнения массива байтов растровым изображением - PullRequest
1 голос
/ 05 января 2011

Я создал библиотеку, где мне нужно заполнить байтовый массив из 307200 элементов (320x240x4 (= 32 бита)) в правильный порядок для растрового изображения, дисплей использует формат 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 #?

1 Ответ

2 голосов
/ 05 января 2011
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 в ref byte[] array - массив уже является ссылочным типом, и вы не изменяете переменную array в своей функции.

PPS GetBitmapBitsвозвращает int, а не long (не путайте с макросом LONG C), GdiFlush возвращает [return:MarshalAs(UnmanagedType.Bool)] bool, а не void.

...