Windows 截图原理,高难度问题,请慎入

2020-12-31 09:53:44 +08:00
 cool1205
windows 截图可以使用 windows 自带的,也可以使用 QQ 等辅助工具截图,效果还是可以的。我想请教各位大神一个问题,windows 通过 API 截图是拿的哪里的数据,这可能与 windows 刷新屏幕有关系了,windows 是直接从屏幕直接截取,还是从内存中直接获取。这么说有些抽象,比如屏幕刷新率是 1HZ (例子而已),那就是一秒屏幕更新一下,此时有个程序每隔 0.1 秒向控制台输出当前毫秒时间戳,那此时使用截图工具,截到图片的时间戳会不会一秒内截图的十张图片一样,还是十张不一样。我尝试使用软件去验证,但不存在可操作性,希望有大哥指教一二
10056 次点击
所在节点    程序员
53 条回复
YouLMAO
2020-12-31 16:55:33 +08:00
截图跟显示屏有个乱关系, 真是知乎派来挖 keng
tomychen
2020-12-31 17:02:13 +08:00
你的显示器是真彩,我可以用调色板给你截成黑白的

这和显示器刷新率有什么关系???
across
2020-12-31 17:17:04 +08:00
显示器这个硬件物理刷新率先放一边。 软件系统设定刷新率 1Hz,那意思就是程序每秒只触发 1 次画面更新。
[此时有个程序每隔 0.1 秒向控制台输出当前毫秒时间戳] ,答案就是十张一样的。

Windows 底层图形绘制 api 是 DirectX 。DirectX 和显卡沟通,在显存上申请一块 Buffer 代表画面帧( Frame ),类似于 web 中的 canvas (可能不太贴切), 画布上具体要画什么东西,由上层软件给他发命令:这里画个圈圈,白色的,那里一个方块啥的,方块黑色的······
因为画面上命令绘制必然有先后顺序,如果只有一块 Buffer,人会看到画面是一步一步画出来的,这对于画面连贯性影响很大。现代系统对此的优化方法就是双缓冲三缓冲这种,前台始终显示的绘制完的画面帧,绘制中帧的放后台,画完后交换。
这个交换刷新后画面的时间间隔,就是的刷新率 。Frame 不刷,输出画面不会变。

一般情况下,要更新画面帧,应用软件是把自己要绘制的数据在内存中加载好,然后通过 DirectX 发到显卡上。截图是反过来,把 Frame 从显存读回内存,内存中你想干怎么就你自己干了,反正和硬件架构无关了。
across
2020-12-31 17:19:24 +08:00
@cool1205
显示器显示的画面和显存中的画面是两回事。
可以把显存中的画面看成“源头”,显卡把显存的数据转换成数字信号,通过 HDMI 之类的接口发给显示器显示。
而电脑中的数据,是显存通过 PCI-E 接口(显卡插槽)和内存交流的。
blindie
2020-12-31 17:29:52 +08:00
计算机里面有一块 buffer 放置任意一个时刻应该渲染的数据。显示器每隔 internal 去取一遍。而 buffer 会在任何时候更新。截图是取 buffer 。跟显示器无关。因为写速度和读速度的天然不统一,所以游戏里才有个选项叫做垂直同步。写的比读的快所以造成图像撕裂
laqow
2020-12-31 19:50:09 +08:00
屏幕刷新率和显存刷新没关系的,你插 1hz 屏幕打 60 帧的游戏电脑照样给你 60 帧渲染,反过来你插 240hz 屏幕电脑也是 60 帧渲染。另外这个 60 帧是人为卡的,不卡它给你 2400 帧渲染都可以。
snw
2020-12-31 21:33:16 +08:00
借楼,你们有没有用过 Azure Information Protection (AIP)?如果 Office 文档或邮件被保护,那么就截不到图(截出来全黑),不知道怎样实现的。
cool1205
2020-12-31 22:29:17 +08:00
@across 感谢你的回复,我懂了你的意思,但我今天买了一个 240hz 的显示器,出现一个让我有些疑惑的问题,之前截张图片大概需要十几毫秒甚至二十毫秒,偶尔个位数毫秒。我现在使用 240hz 显示器,同样截图程序输出基本上都是 3-4ms 。这个情况是什么原因造成的呢?
cool1205
2020-12-31 22:33:21 +08:00
@across 240hz 的显示器是 1080p 的,60hz 的显示器是 2k 的
across
2020-12-31 22:47:25 +08:00
@cool1205 和刷新率没关系。
截图速度包括: 显存数据拷贝到内存,再在内存中编码成 jpg 格式,最后写入到硬盘。
拷贝的数据量就是画面帧,帧大小 = 帧宽 * 帧高 * 每个像素点的色彩位数。 一般 32 位真彩就是 4byte,2560x1440 就是 14mb,1920:1080 才 8mb 。
systemcall
2020-12-31 22:49:22 +08:00
@cool1205 dwm 在更新画面的时候,一些区域的更新确实是和显示器目前的刷新率一致的,这点可以使用 Fraps 之类的软件来证明
分辨率高确实会降低绘图的速度,同时还对显存和内存有更大的负担,带宽上的需求也高一些。2k 的像素点是 1080p 的 2 倍,如果像素格式一样的话,2k 的负担应该是高一些的
GPU 的话,AMD 和 NVIDIA 都没有什么文档,Intel 倒是有。感兴趣的话可以去 Intel Ark 找个稍微新一点的带核显的处理器,看一下有没有 datasheet,一些产品是有的,里面可能会有 GPU 方面的介绍,2D 部分是有几个图层和精灵的
@snw 显卡、显示器是有 HDCP 之类的 DRM 的,受保护的内容会在专门的内存区域中处理,需要 1.处理器和 GPU 支持 2.BIOS 中启用相关功能 3.系统和驱动程序支持
@anuding 没有显示器的情况下没试过。但是如果是远程桌面之类的是通过 WARP 来使用 CPU 进行渲染。Windows Defend 应用程序高级防护下启用了 GPU 加速的浏览器,感觉是用名为“Display Controller"这个东西来渲染的, 似乎拆成了 2 个部分而且很吃 CPU
没有接显示器的情况下启动 OS 、自动登录,之后无论是远程桌面还是直接接显示器连接到电脑,都是可以正常显示画面的。但是如果是登录了之后断开显示器再连接上去,感觉还是和之前连接过的显示器有关系,桌面大小、缩放之类的
ysc3839
2020-12-31 23:47:11 +08:00
codehz
2021-01-01 11:09:52 +08:00
@cool1205 #48 多半是截图程序的故意设计。。。因为截图目标是游戏 /视频一类的话,它不会强行多画几帧的(换句话说,类似于 push 模式,画好了推到显存上)
但是如果是普通的窗口,则是你啥时候截图就可以即时给你画一个出来(当然内容更新与否还要看程序自己的意思),这就类似于 pull 模式( gdi 截图就可以做到)
但是同一个截图方式不可能同时兼容于两种模式,所以为了能给游戏窗口截图,就只能用于刷新率绑定的 dx 截图方法了*

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/740500

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX