将屏幕像素作为字节数组获取

问题描述 投票:-2回答:1

我需要更改屏幕捕获代码以获取像素阵列而不是位图。

我将代码更改为此:

BitBlt > Image.FromHbitmap(pointer) > LockBits > pixel array

但是,我正在检查是否有可能削减一些中间人,并得到类似这样的东西:

BitBlt > Marshal.Copy > pixel array

甚至:

WinApi method that gets the screen region as a pixel array

到目前为止,我尝试使用此代码,但未成功:

public static byte[] CaptureAsArray(Size size, int positionX, int positionY)
{
    var hDesk = GetDesktopWindow();
    var hSrce = GetWindowDC(hDesk);
    var hDest = CreateCompatibleDC(hSrce);
    var hBmp = CreateCompatibleBitmap(hSrce, (int)size.Width, (int)size.Height);
    var hOldBmp = SelectObject(hDest, hBmp);

    try
    {
        new System.Security.Permissions.UIPermission(System.Security.Permissions.UIPermissionWindow.AllWindows).Demand();

        var b = BitBlt(hDest, 0, 0, (int)size.Width, (int)size.Height, hSrce, positionX, positionY, CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt);

        var length = 4 * (int)size.Width * (int)size.Height;
        var bytes = new byte[length];

        Marshal.Copy(hBmp, bytes, 0, length);

        //return b ? Image.FromHbitmap(hBmp) : null;
        return bytes;
    }
    finally
    {
        SelectObject(hDest, hOldBmp);
        DeleteObject(hBmp);
        DeleteDC(hDest);
        ReleaseDC(hDesk, hSrce);
    }

    return null;
}

此代码在踩到System.AccessViolationException时给了我Marshal.Copy

使用BitBlt或类似的屏幕捕获方法时,有没有更有效的方式将屏幕像素作为字节数组获取?


编辑:

[在here中发现,并且根据CodyGray的建议,我应该使用

var b = Native.BitBlt(_compatibleDeviceContext, 0, 0, Width, Height, _windowDeviceContext, Left, Top, Native.CopyPixelOperation.SourceCopy | Native.CopyPixelOperation.CaptureBlt);

var bi = new Native.BITMAPINFOHEADER();
bi.biSize = (uint)Marshal.SizeOf(bi);
bi.biBitCount = 32; 
bi.biClrUsed = 0;
bi.biClrImportant = 0;
bi.biCompression = 0;
bi.biHeight = Height;
bi.biWidth = Width;
bi.biPlanes = 1;

var data = new byte[4 * Width * Height];

Native.GetDIBits(_windowDeviceContext, _compatibleBitmap, 0, (uint)Height, data, ref bi, Native.DIB_Color_Mode.DIB_RGB_COLORS);

我的data数组具有屏幕截图的所有像素。现在,我将测试性能是否有所提高。

c# winapi screen-capture bitblt
1个回答
1
投票

[是的,您不能只是开始通过BITMAP(由HBITMAP返回)访问CreateCompatibleBitmap对象的原始位。顾名思义,HBITMAP只是一个句柄。在经典的“ C”意义上,它不是指向数组开头的指针。句柄就像间接指针。

GetDIBits是一种合适的解决方案,可从您可以迭代通过的位图获取原始的,与设备无关的像素阵列。但是您仍然需要使用必须首先获得屏幕位图的代码。本质上,您想要类似this的内容。当然,您需要将其转换为C#,但这并不难,因为您已经知道如何调用WinAPI函数。

注意,您不需要呼叫GetDesktopWindowGetWindowDC。只需将NULL作为句柄传递给GetDC;它具有返回屏幕DC的相同效果,然后您可以使用它来创建兼容的位图。通常,您几乎应该永远不要调用GetDesktopWindow

© www.soinside.com 2019 - 2024. All rights reserved.