我想编写一个程序来连续捕获屏幕并对图像进行一些修改。可以在以下位置找到完整的测试程序:
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); …Run Code Online (Sandbox Code Playgroud)