blo*_*gsh 3 x11 gtk screen cairo gdk
我想编写一个程序来连续捕获屏幕并对图像进行一些修改。可以在以下位置找到完整的测试程序:
https://gist.github.com/blogsh/eb4dd4b96aca468c8bfa
但是,我遇到了一些问题。我做的第一个实验是使用 Gdk 根窗口,从中创建一个 Cairo 上下文,然后使用它的目标作为另一个窗口的源,其中的内容被绘制为:
mScreenContext = Gdk::Screen::get_default()->get_root_window()->create_cairo_context()
...
context->set_source(mScreenContext->get_target(), 0, 0);
context->paint();
Run Code Online (Sandbox Code Playgroud)
这工作得很好(上面源代码中的变体 1)。它只是将整个屏幕绘制到另一个窗口中。所以我的下一步是尝试将内容保存到 Cairo ImageSurface 中以便对其进行修改:
mImageContext->set_source(mScreenContext->get_target(), 0, 0);
mImageContext->paint();
context->set_source(mImageSurface, 0, 0);
context->paint();
Run Code Online (Sandbox Code Playgroud)
令人惊讶的是,对于 Gtk 窗口的第一次绘制,屏幕被捕获并绘制。不幸的是之后没有发生任何事情,仍然显示初始屏幕。如何解释这种行为?我必须承认我对这里的底层流程了解不多,所以也许有人可以提供一些提示?
使用的第三个变体Gdk::Pixbuf产生完全相同的行为:
mScreenBuffer = Gdk::Pixbuf::create(mGdkRootWindow, 0, 0, mScreenWidth, mScreenHeight);
Gdk::Cairo::set_source_pixbuf(context, mScreenBuffer, 0, 0);
context->paint();
Run Code Online (Sandbox Code Playgroud)
最后(变体 4)我尝试X11直接使用:
Display *display = XOpenDisplay((char*)0);
XImage *image = XGetImage(display, RootWindow(display, DefaultScreen(display)), 0, 0, mScreenWidth, mScreenHeight, AllPlanes, XYPixmap);
mScreenBuffer = Gdk::Pixbuf::create_from_data((const guint8*)image->data, Gdk::COLORSPACE_RGB, 0, 8, mScreenWidth, mScreenHeight, mScreenWidth);
Gdk::Cairo::set_source_pixbuf(context, mScreenBuffer, 0, 0);
context->paint();
XFree(image);
Run Code Online (Sandbox Code Playgroud)
实际上,这是有效的(尽管我还没有努力正确匹配像素格式),但是速度非常慢!
所以我很感激关于两个 Gdk 变体的问题是什么和/或如何加速 X11 方法的任何提示。或者也许有人知道一种完全不同的快速捕获屏幕的方法。
不幸的是,我对整个主题不太熟悉,但另一个想法是使用基于 OpenGL 的窗口管理器,在那里我可以直接读取帧缓冲区?那有意义吗?
该程序的主要思想是我有一台不能直接放在墙前的投影仪。所以我的想法是捕捉屏幕,做一些双线性变换来解决投影的偏斜,然后在另一个窗口中显示修改后的屏幕,这将在投影仪上显示......
小智 5
XShmGetImage 和 XShmPutImage 比 XGetImage 和 XPutImage 快。在下一个示例中,我创建了两个图像:src 和 dst。在每次迭代中,我在 src 中保存一个屏幕截图,然后在 dst 中渲染它的缩放版本。
下图显示了在名为“screencap”的窗口中运行的示例。在低需求时,它以 60 fps 的速度运行(如右上角的终端所示)。在高需求下,性能可能会下降到 25fps。
测试电脑:
Display resolution: 1920x1080
Graphic card: ATI Radeon HD 4200 (integrated)
CPU: AMD Phenom(tm) II X4 945, 3013.85 MHz
Window manager: XFCE 4.12 (compositing off)
Operating system: OpenBSD 5.9
Tested also in Linux (openSUSE Leap 42.1)
Run Code Online (Sandbox Code Playgroud)
Display resolution: 1920x1080
Graphic card: ATI Radeon HD 4200 (integrated)
CPU: AMD Phenom(tm) II X4 945, 3013.85 MHz
Window manager: XFCE 4.12 (compositing off)
Operating system: OpenBSD 5.9
Tested also in Linux (openSUSE Leap 42.1)
Run Code Online (Sandbox Code Playgroud)
这只是一个例子。如果你喜欢它的表现,你应该考虑添加一个更好的合适的缩放算法并支持所有像素格式。
您可以像这样编译示例:
gcc screencap.c -o screencap -std=c99 -I/usr/X11R6/include -L/usr/X11R6/lib -lX11 -lXext -lm
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2641 次 |
| 最近记录: |