Linux上最快的屏幕捕获方法

Fastest method for screen capturing on Linux

本文关键字:方法 屏幕 Linux      更新时间:2023-10-16

这个问题与类似

屏幕捕获的最快方法

但适用于linux/X11。

更具体地说,我需要一种方法来捕捉X11 diplay上运行的一个窗口(相当于windows中alt打印屏幕的程序)的像素图像。

注意事项和要求:

1) 即使新窗口被放置在正在捕获的窗口的顶部,像素图像仍然应该指向原始应用程序窗口,而没有任何遮挡

2) 不需要用户看到应用程序窗口,我只需要存储用于视频目的的像素缓冲区/图像

我探索过的其他选择是:

1) xvfb-它可以工作,但它确实进行CPU渲染,这很慢浪费了一个好的GPU

2) x11在许多lxc中-理论上可以工作,但很复杂设置,我不确定它是否能很好地扩展许多窗口捕获的

建议和想法欢迎

在硬件加速的服务器中使用VirtualGL是可能的。基本上只需适当配置服务器,然后在同一台机器上或同一网络中的机器上运行

export DISPLAY=<your xvfb display>
vglrun <your_app>

这将具有以下优点:

1) 您的应用程序将使用virtualGL进行渲染,virtualGL将使用硬件

2) VirtualGL将在Xfvb显示器中显示您的3D上下文,这将只在CPU 中呈现2D窗口小部件

3) 配置Xvfb以渲染到帧缓冲区

4) 利润!

这在纯X11中是不可能的。

你可以通过合成获得你想要的东西,但只能在支持它的服务器上(大多数现代服务器都支持)。这实际上与窗口管理器无关。WM只是另一个客户,尽管有一些特殊的能力,但这些能力与合成无关。您可以使用相同的合成API。

man xcomposite应该让你开始。

我看到评论说这在X11中无法完成,所以可能有一些我不理解的地方,但我可以使用以下代码捕获屏幕。

#include <X11/Xlib.h> //-lX11
#include <X11/Xutil.h>
#include <X11/Xmd.h> 
#include <X11/Xatom.h>
#include <jpeglib.h> //-ljpeg 
void CopyDesktopImage(std::string sFilePath_Name)
{  
Display *dis=XOpenDisplay((char *)0);
Screen *scr = XDefaultScreenOfDisplay(dis);
Drawable drawable = XDefaultRootWindow(dis);
XImage *image = XGetImage(dis, drawable, 0, 0, scr->width, scr->height, AllPlanes, ZPixmap);
Save_XImage_to_JPG(image, sFilePath_Name.c_str(), 75);
XDestroyImage(image);
XCloseDisplay(dis); 
}
void Save_XImage_to_JPG(XImage *image, std::string FileName, int Quality)
{
FILE* outfile = fopen(FileName.c_str(), "wb");
if(outfile == NULL) return;
jpeg_compress_struct cinfo;
jpeg_error_mgr       jerr;
cinfo.err = jpeg_std_error(&jerr);
jpeg_create_compress(&cinfo);
jpeg_stdio_dest(&cinfo, outfile);
cinfo.image_width      = image->width;
cinfo.image_height     = image->height;
cinfo.input_components = image->bitmap_unit >> 3;
cinfo.in_color_space   = JCS_EXT_BGRX;
jpeg_set_defaults(&cinfo);
/*set the quality [0..100]  */
jpeg_set_quality(&cinfo, Quality, true);
jpeg_start_compress(&cinfo, true);
JSAMPROW row_pointer;          /* pointer to a single row */
while (cinfo.next_scanline < cinfo.image_height) 
{
row_pointer = (JSAMPROW) &image->data[cinfo.next_scanline*image->bytes_per_line];
jpeg_write_scanlines(&cinfo, &row_pointer, 1);
}
jpeg_finish_compress(&cinfo);
fclose(outfile);
}

您可以使用xwd(1)转储X11窗口(使用xwud(1)显示它)。ImageMagick和Netpbm工具知道如何处理XWD格式。但这些并不是特别快。而且它们不会暴露窗口的隐藏部分。

这只是一个猜测,但我认为您可以将x11vnc与-id[windowid]一起使用(http://www.karlrunge.com/x11vnc/x11vnc_opts.html#opt-id)选项,以通过VNC流式传输该单个窗口。这将显示整个窗口,与主屏幕中的位置完全相同(您可能会丢失一些弹出菜单),即使它被覆盖。您可以从真正的X11屏幕获取窗口坐标。

我会获取gnome-screenshot或其他现有开源工具的来源,并找出它们是如何做到的。

你可以在这里找到Ubuntu使用的来源:http://packages.ubuntu.com/quantal/gnome-screenshot

但是,在剪切和粘贴大部分代码之前,不要忘记检查许可证!

Xpaint是一个非常古老的X11实用程序,使用MIT Athena小部件集构建。文件>拍摄快照将从屏幕上抓取窗口或鼠标选择的矩形。

MagiCapture是X Window系统的屏幕捕获和预览实用程序。用户可以捕捉单个窗口、带有装饰的单个窗口、显示器的矩形区域或整个显示器本身。用户可以将捕获的图像保存到ImageMagick工具包支持的图形文件中,该工具包支持大多数(如果不是全部的话)流行的图形格式。MagiCapture将GLIB和GTK+库用于用户界面,将ImageMagick和GdkMagick库用于所有图形处理。需要ImageMagick。

Zscreen:-这个仅限Windows的屏幕捕获应用程序有很多功能。它抓取活动窗口、选定窗口或整个屏幕的快照。一旦你得到了图像,就可以在图像编辑器中自动打开它,或者将它上传到Twitpic、YFrog、Flickr或其他一些受支持的服务中。ZScreen会缓存您的所有图像,甚至是剪贴板上的图像,因此您的屏幕截图历史记录总是触手可及。

在本地网络中使用X远程功能打开X侦听端口,然后使用env-var将导出设置为X侦听端口