简体   繁体   English

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

[英]Getting the screen pixels as byte array

I need to change my screen capture code to get a pixel array instead of a Bitmap.我需要更改屏幕捕获代码以获取像素阵列而不是 Bitmap。

I change the code to this:我将代码更改为:

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

But, I'm checking if it's possible to cut some middle man, and have something like this:但是,我正在检查是否有可能削减一些中间人,并有这样的事情:

BitBlt > Marshal.Copy > pixel array

Or even:甚至:

WinApi method that gets the screen region as a pixel array

So far, I tried to use this code, without success:到目前为止,我尝试使用此代码,但没有成功:

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;
}

This code gives me an System.AccessViolationException while stepping on Marshal.Copy .这段代码在踩到Marshal.Copy时给了我一个System.AccessViolationException

Is there any more efficient way of getting screen pixels as a byte array while using BitBlt or similar screen capture methods?在使用 BitBlt 或类似的屏幕捕获方法时,是否有更有效的方法将屏幕像素作为字节数组获取?


EDIT:编辑:

As found in here and as suggested by CodyGray, I should use如发现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);

My data array has all the pixels of the screenshot.我的data数组包含屏幕截图的所有像素。 Now, I'm going to test if there's any performance improvements or not.现在,我将测试是否有任何性能改进。

Yeah, you can't just start accessing the raw bits of a BITMAP object through an HBITMAP (as returned by CreateCompatibleBitmap ).是的,您不能只是通过HBITMAP (由CreateCompatibleBitmap返回)开始访问BITMAP object 的原始位。 HBITMAP is just a handle, as the name suggests.顾名思义, HBITMAP只是一个句柄。 It's not a pointer in the classic "C" sense that it points to the beginning of the array.它不是经典“C”意义上的指针,它指向数组的开头。 Handles are like indirect pointers.句柄就像间接指针。

GetDIBits is the appropriate solution to get the raw, device-independent pixel array from a bitmap that you can iterate through. GetDIBits是从您可以迭代的 bitmap 获取原始的、与设备无关的像素阵列的合适解决方案。 But you'll still need to use the code you have to get the screen bitmap in the first place.但是您仍然需要首先使用获得屏幕 bitmap 的代码。 Essentially, you want something like this .本质上,你想要这样的东西。 Of course, you'll need to translate it into C#, but that shouldn't be difficult, since you already know how to call WinAPI functions.当然,您需要将其翻译成 C#,但这应该不难,因为您已经知道如何调用 WinAPI 函数。

Note that you do not need to call GetDesktopWindow or GetWindowDC .请注意,您不需要调用GetDesktopWindowGetWindowDC Just pass NULL as the handle to GetDC ;只需将NULL作为句柄传递给GetDC it has the same effect of returning a screen DC, which you can then use to create a compatible bitmap.它具有返回屏幕DC的相同效果,然后您可以使用它来创建兼容的bitmap。 In general, you should almost never call GetDesktopWindow .通常,您几乎不应该调用GetDesktopWindow

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM