![屏幕截图如何工作?](https://linux22.com/image/1612852/%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE%E5%A6%82%E4%BD%95%E5%B7%A5%E4%BD%9C%EF%BC%9F.png)
我目前正在写一篇关于游戏摄影的考试试卷,在写试卷时,我想(简要地)指出相机和截屏之间的区别 - 但我对后者的技术方面了解不够,无法胜任。我希望你们中的一些人可能知道?
换句话说,截屏是如何工作的?它会“冻结”像素吗?是显卡或其驱动程序在工作吗?还是其他硬件或软件组件?
在摄影中,光线被传感器捕捉,而计算机则通过屏幕发射光线 - 但我认为屏幕截图本身是在数据转换成像素之前发生的?
答案1
但我认为屏幕截图本身是在数据转换成像素之前发生的?
它发生在数据被转换成身体的像素(如果有的话),但它发生在数据变成像素值,即位图图像。
例如,如果程序正在显示文本或矢量图形或 3D 视觉效果,则屏幕截图过程根本不关心这些,它只关心将这些图形渲染成位图后生成的图像。
但是,屏幕截图是直接从操作系统内存中截取的,或者在最坏的情况下,从 GPU 内存中读回的——这是不是从实际的 VGA 或 HDMI 信号捕获。
换句话说,截屏是如何工作的?它会“冻结”像素吗?是显卡或其驱动程序在工作吗?还是其他硬件或软件组件?
取决于您询问的操作系统。通常,核心图形系统(允许应用程序将窗口放在屏幕上的系统,例如 Windows 上的 GDI 或 Linux 上的 X11)将保留屏幕上所有像素的内存副本(即帧缓冲区),以便可以在需要时再次将它们发送到 GPU。因此,它只是为程序提供检索该副本的功能。
例如,在 Windows 上有获取DC()和获取窗口DC()函数。在 Linux 上,X11 系统有一些类似的方法,例如获取图像()。这些只是为程序提供一个已经保存在系统 RAM 某处的位图图像,无需任何特殊硬件参与。
(尽管在某些情况下,例如在 Linux 上的 GNOME 中,窗口管理器实际上使用 GPU 来组成屏幕的内容 - 因此为了截屏,它实际上必须先将数据请求回 CPU。)
顺便提一下,帧缓冲区中的内容与实际显示的内容可能会有所不同。例如,许多视频游戏会产生非常暗的屏幕截图,因为它们使用了 GPU 的伽马校正功能来调整图像亮度,并且此校正仅在生成视频信号时作为最后一步应用 - 因此屏幕截图将仅捕获未校正的、看起来很暗的图像。(除非游戏实际上用自己的屏幕截图功能覆盖整个操作系统屏幕截图功能。)
答案2
观察差异的一种方法是考虑两者的结果。
屏幕截图相当于计算机以数字形式截取全屏图像并将其保存为文件。通过这种方式,数字信息会根据显示器和显示适配器的功能尽可能精确。如果您有 4K 显卡和显示器,您的屏幕截图将以 4K 分辨率完美呈现。
另一方面,相机拍摄的屏幕快照是数字到模拟再到数字的转换。第一个数字是来自显示适配器的上述信息。模拟部分是光线从显示器传输到您的眼睛和/或相机,而最终的数字是通过相机数字传感器将该光线转换为数字。
相机提供的图像质量与屏幕捕获的图像质量有很大差异。相机通过有像差和损耗的镜头以光的形式传递“信号”,这进一步降低了质量。
答案3
相机从光传感器读取数据并将数据存储在 RAM 或其他存储器中。与静态相机不同,摄像机会持续执行此操作。来自传感器的“原始”数据可能与显示设备(例如 PC 显卡或相机上的 LCD)所需的格式不兼容,因此如果带相机的设备需要显示相机所看到的内容,则需要从相机格式转换为显示设备格式。
屏幕截图是将已存在于 RAM 中的数据导出,这些数据由显卡使用或最终用于显示设备。通常,这些数据采用 PC 显卡或其他显示设备所需的格式。捕获后,必须将其从此格式转换为众所周知的图像格式。
因此主要的区别在于数据流:
相机 -> RAW 数据 -> 捕获(复制)到存储或 RAM -> 显示设备二进制格式 -> 显示设备视频 RAM -> 显示设备(如果相机看到的内容应直接显示)
相机 -> RAW 数据 -> 捕获(复制)到临时存储或 RAM -> 从那里转换为 JPEG 等(如果相机看到的内容应保存到文件中)
显示设备 -> 显示设备视频 RAM -> 显示设备二进制格式 -> 捕获(复制)到其他系统 RAM -> 从那里转换为 BMP、JPEG 等(保存显示设备用来生成图片到文件的内容)
答案4
我还没有看到提到的一件事是“屏幕截图”并不总是当前帧的快照,或者根本不是“屏幕”的捕获。
您会看到,现代分辨率要求每秒多次将大量像素数据从图形处理器 (GPU) 传输到显示器。软件和硬件都已发展到不再传输重复信息,因此,除非有请求,否则 GPU 渲染的像素只会发送到显示器,而不会发送到 CPU。
这样做的后果是,对于屏幕截图,像素数据通常必须“重建”,并且至少必须将其从 GPU 发送回 CPU,而从按下 PrtScrn 按钮开始,这两项操作都需要相当长的时间。
尽管如此,较新的 GPU 即使在高负载下也能够重建并将最近一帧的数据发送回 CPU,但这样做的后果是屏幕截图可能略显过时。当您尝试流式传输/录制时,您会更加注意到这种延迟,在某些硬件上可能超过一秒。
再次,造成这种情况的原因是信息溢出;GPU 上的数百万像素必须首先重建/转换/压缩/执行其他操作,然后才能以合理的速度和 CPU 可以理解的格式传输到 CPU。
请记住,在执行此操作时,CPU 和 GPU 都必须进行通信并花时间等待对方,同时还必须执行其他操作。
我们早已远离了直接将像素数据发送到显示器的时代,甚至不必担心发送像素数据(如今的软件正在发送纹理/模型/三角形,它们可以用更少的信息传达相同的图片)。我们习惯于多个/可移动/可重叠/透明的窗口,但实际上有许多复杂的系统允许这种情况发生,每个系统可能都有自己的方法来获取具有不同细节级别的“屏幕截图”。我知道至少有 4 种方法可以在我的 Linux 机器上获取屏幕截图,每种方法都有自己的优点和缺点。重要的是,这些方法都不能真正保证它们能够准确捕获屏幕上显示的内容。
有些系统可以无延迟地截取普通窗口的屏幕截图,但不能截取游戏或高负载下的屏幕截图,有些系统可能会每一帧都向 GPU 请求屏幕截图,这样您就可以获得想要的完美屏幕截图,即使您截取的内容被遮挡,有些系统一次只能“截取”一个窗口,而有些系统根本不支持实时屏幕截图。
虽然没有完全相同的系统,但每个截屏机制都有一个共同点,那就是它必须担心接收 1920x1080(或更多!)像素并将其转换为图像文件,而不会锁定整个计算机。为此,必须做出妥协,而相机则不必处理这些妥协。