32

这个问题类似于这个问题

最快的截屏方法

但对于 linux/X11。

更具体地说,我需要一种方法来捕获在 X11 显示器上运行的一个窗口的像素图像(Windows 中 alt-print 屏幕的编程等效项)。

注意事项和要求:

1) 即使在正在捕获的窗口之上放置了一个新窗口,像素图像仍应指向原始应用程序窗口而没有任何遮挡

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

我探索过的其他选择是:

1) xvfb - 它可以工作,但它确实可以进行 CPU 渲染,这对一个好的 GPU 来说是缓慢和浪费的

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

欢迎提出建议和想法

4

8 回答 8

9

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

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

这将具有以下优点:

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

2) VirtualGL 将在 Xfvb 显示器内显示您的 3D 上下文,这只会在 CPU 中渲染 2D 小部件

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

4)利润!

于 2012-11-29T15:48:04.050 回答
8

这对于纯 X11 是不可能的。

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

man xcomposite应该让你开始。

于 2012-11-22T19:08:35.633 回答
3

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

于 2012-11-28T02:45:00.477 回答
3

我看到评论说这不能在 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);
}
于 2018-12-28T22:32:38.000 回答
1

我会获取 的源代码gnome-screenshot或其他一些现有的开源工具,并弄清楚它们是如何做到的。

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

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

于 2012-11-29T13:19:39.453 回答
1

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

于 2012-11-29T13:34:40.583 回答
0

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

或者

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

或者

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

于 2012-11-29T15:25:04.487 回答
0

您可以在本地网络中进行棘手的黑客攻击是使用 X 远程功能打开您的 X 侦听端口,然后使用 env var 将导出设置为 X 侦听端口,然后使用 XscreenCapture

于 2012-11-29T15:31:32.983 回答