【问题标题】:Fastest method for screen capturing on LinuxLinux 上最快的截屏方法
【发布时间】:2012-11-20 18:44:50
【问题描述】:

这个问题和这个问题类似

Fastest method of screen capturing

但对于 linux/X11。

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

注意事项和要求:

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

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

我探索过的其他替代方案是:

1) xvfb - 它可以工作,但它可以进行 CPU 渲染,这很慢而且 浪费了好GPU

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

欢迎提出建议和想法

【问题讨论】:

  • 如果窗口被覆盖,你读到的内容是未定义的。
  • 是的,CPU 渲染速度很慢而且很浪费,但是这样的性能慢到无法接受吗?此外,根据您使用的窗口管理器,如果它是一个合成窗口管理器,您可以寻找一个特定于 wm 的 API,它可以为您提供指向应用程序屏幕外缓冲区的指针。然后,您所要做的就是在应用程序重绘之前复制缓冲区。
  • @RobertMason,这会起作用,如果有人可以建议一个窗口管理器 1)支持 GPU 加速渲染(我知道关于 x11 架构的 zilch,但我想那是通过扩展完成)和 2)支持特定类型的 API
  • @RobertMason,(在 xvfb 中运行应用程序的)性能并没有令人无法接受的慢,只是足够慢,因此值得花时间寻找替代品
  • 如果可以的话,你可以使用 wmctrl 或 xdotool 来激活一个窗口,xwininfo 对于获取 xwd 的窗口 id 也很有用(如果你使用 xwd 将它输出到 > name.xwd 和一些图像程序将能够在本机打开它)

标签: c++ c linux screenshot x11


【解决方案1】:

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

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

这将具有以下优点:

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

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

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

4) 利润!

【讨论】:

  • 这很有趣!谢谢,我会检查它并尝试配置它
【解决方案2】:

这对于纯 X11 是不可能的。

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

man xcomposite 应该可以帮助您入门。

【讨论】:

  • 我已经在 compiz 邮件列表中问过这个问题,但他们认为复合经理这样做没有多大意义:lists.compiz.org/pipermail/dev/2012-November/thread.html#1545 我会审查 xcompòsite 并看看它会导致什么
  • 嗯,他们似乎和我说的差不多,只是更详细一些。代码 sn-p 使用来自xcomposite 的函数。
【解决方案3】:

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

【讨论】:

    【解决方案4】:

    我看到 cmets 说这不能在 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);
    }
    

    【讨论】:

      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

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

        您可以在此处找到 Ubuntu 使用的源代码:http://packages.ubuntu.com/quantal/gnome-screenshot

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

        【讨论】:

          【解决方案7】:

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

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

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

          【讨论】:

            【解决方案8】:

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

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2011-06-25
              • 2011-07-01
              • 2010-12-09
              • 2014-01-07
              • 1970-01-01
              • 2011-12-19
              相关资源
              最近更新 更多