lur*_*her 26 c c++ linux x11 screenshot
这个问题与此类似
但是对于linux/X11.
更具体地说,我需要一种方法来捕获在X11显示器上运行的一个窗口(在windows中的alt-print屏幕的程序化等效物)的像素图像.
注意事项和要求:
1)即使在正在捕获的窗口顶部放置一个新窗口,像素图像仍应指向原始应用程序窗口而没有任何遮挡
2)不需要用户看到应用程序窗口,我只需要存储像素缓冲区/图像用于视频目的
我探索的其他替代方案是:
1)xvfb - 它可以工作,但它确实可以进行CPU渲染,这很慢并且浪费了很好的GPU
2)x11里面很多lxc - 理论上可以工作,但设置很复杂,我不确定它会很好地扩展,许多窗口被捕获
欢迎提出建议和想法
纯X11无法实现这一点.
您可以通过合成获得所需的内容,但仅限于支持它的服务器(大多数现代服务器都可以).这实际上与窗口管理器无关.WM只是另一个客户端,虽然有一些特殊的能力,但那些与合成无关.您可以使用相同的合成API.
man xcomposite 应该让你开始.
这可以在具有硬件加速的服务器中使用VirtualGL.基本上只是适当地配置服务器,然后运行在同一台机器上或同一网络中的机器上
export DISPLAY=<your xvfb display>
vglrun <your_app>
Run Code Online (Sandbox Code Playgroud)
这将具有以下优点:
1)您的应用程序将使用虚拟GL渲染,它将使用硬件
2)VirtualGL将在Xfvb显示内部显示您的3D上下文,这只会在CPU中呈现2D小部件
3)配置Xvfb渲染到帧缓冲区
4)利润!
小智 5
我看到评论说这不能在 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);
}
Run Code Online (Sandbox Code Playgroud)