Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/285.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 快速桌面图像捕获_C#_Winforms_Screenshot - Fatal编程技术网

C# 快速桌面图像捕获

C# 快速桌面图像捕获,c#,winforms,screenshot,C#,Winforms,Screenshot,我正在尝试用C#开发一个基本的屏幕共享和协作应用程序。我目前正在抓拍屏幕,查找屏幕上已更改的区域,然后需要传输到最终客户端 我有一个问题,屏幕截图的整体帧速率太低。我有一个相当好的算法来查找屏幕上发生变化的区域。给定屏幕上像素的字节数组,它计算在2-4ms内发生变化的区域,但是我得到的总帧速率是15-18fps(即每帧大约60毫秒)。瓶颈是将屏幕上的数据捕获为字节数组,这大约需要35-50毫秒。我尝试了几种不同的技术,但无法将fps推过20秒 起初我试过这样的方法: var _bmp = new

我正在尝试用C#开发一个基本的屏幕共享和协作应用程序。我目前正在抓拍屏幕,查找屏幕上已更改的区域,然后需要传输到最终客户端

我有一个问题,屏幕截图的整体帧速率太低。我有一个相当好的算法来查找屏幕上发生变化的区域。给定屏幕上像素的字节数组,它计算在2-4ms内发生变化的区域,但是我得到的总帧速率是15-18fps(即每帧大约60毫秒)。瓶颈是将屏幕上的数据捕获为字节数组,这大约需要35-50毫秒。我尝试了几种不同的技术,但无法将fps推过20秒

起初我试过这样的方法:

var _bmp = new Bitmap(screenSectionToMonitor.Width, screenSectionToMonitor.Height);
var _gfx = Graphics.FromImage(_bmp);
_gfx.CopyFromScreen(_screenSectionToMonitor.X, _screenSectionToMonitor.Y, 0, 0, new Size(_screenSectionToMonitor.Width, _screenSectionToMonitor.Height), CopyPixelOperation.SourceCopy);
var data = _bmp.LockBits(new Rectangle(0, 0, _screenSectionToMonitor.Width, _screenSectionToMonitor.Height), ImageLockMode.ReadOnly, _bmp.PixelFormat);
var ptr = data.Scan0;
Marshal.Copy(ptr, _screenshot, 0, _screenSectionToMonitor.Height * _screenSectionToMonitor.Width * _bytesPerPixel);
_bmp.UnlockBits(data);
仅在单个1080p屏幕上运行上面的代码就需要大约45毫秒,这太慢了。这使得整体帧速率太慢而无法平滑,因此我尝试使用DirectX,如下例所示:

然而,这并没有带来任何结果。它略微提高了屏幕捕获的速度,但仍然太慢(大约需要25-40ms,这一小幅度的增加不值得额外的DLL、代码等开销)

在谷歌搜索了一段时间后,我真的找不到更好的解决方案,所以我的问题是,捕捉屏幕上当前显示的像素的最佳方法是什么?理想的解决方案是:

  • 将屏幕捕获为RGBA形式的字节数组
  • 在较旧的windows平台(如windows XP及以上)上工作
  • 使用多个显示器
  • 使用现有系统库而不是第三方DLL
所有这些点都是可以协商的解决方案,该解决方案返回一个合适的总体帧速率,实际捕获的帧速率为5-10ms,因此帧速率可以为40-60fps


或者,如果没有与上面匹配的解决方案,我是否选择了错误的路径来计算屏幕更改。是否有更好的方法来计算已更改的屏幕区域?

也许您可以在较低的代码级别访问屏幕缓冲区,并直接挂接到Windows用作屏幕更新一部分的层和区域s、 听起来你是在追求原始显示的变化,Windows已经开始跟踪这些数据。只是为你提供了一个方向,同时你也找到了更有知识的人。

你看过DFMirage吗?这是TightVNC用来提高Windows性能的东西。我觉得你的方法是错误的。抓取世界卫生组织的屏幕截图先打开桌面,然后处理区域等。试着分析什么占用了大部分时间?我很确定这将是一个锁定或转换的功能,您可以为每个区域多次调用它。我同意@Sinatr-经常获取原始屏幕数据可能会很快,但处理这些数据不会很快。@Sinatr我已经分析了应用程序。处理过程需要时间在2-4毫秒之间。调用
\u gfx.CopyFromScreen(\u screenSectionToMonitor.X,\u screenSectionToMonitor.Y,0,0,新大小(\u screenSectionToMonitor.Width,\u screenSectionToMonitor.Height),CopyPixelOperation.SourceCopy)
需要35毫秒以上的时间,这不是我的代码,也没有锁定。这一次调用是图形的瓶颈。CopyFromScreen是。我的意思是使用
DirectX
一次捕获整个屏幕的流(锁定不是
c#
中的
lock
,而是一种直接访问缓冲区的技术,类似于
位图.LockBits
)。这应该是您在不使用驱动程序的情况下所能获得的最快速度。这正是我所希望的方法。由于数据明显显示在屏幕上,因此它位于内存/缓冲区中的某个位置是有意义的,只需要知道如何访问它,但目前为止没有运气