最近看GDK,看到一段抓屏的代码还不错,所以贴出来分享。
环境:Ubuntu 8.04
编译:gcc -o capture capture.c `pkg-config --libs --cflags gtk+-2.0`
执行:capture [-options...],不带参数延迟3秒,输出文件名为当前时间.jpg
-o outputfilename
-s delayseconds
除了这段代码外,还有几点相关的知识点:
1. GDK_WINDOW_XID(GdkWindow)或GDK_DRAWABLE_XID(GdkDrawable)可以将 GdkWindow/GdkDrawable转化为X window id,如果是GtkWindow,这么转:GTK_WIDGET(GtkWindow)->window
注意: windows id必须在show(比如gtk_widget_show)以后才能得到id的,否则会报warning并返回0
2. 在Ubuntu里测试的结果root window是0x41,而桌面的id往往是0X12000xx,桌面背景覆盖在root窗口上,所以root window你在GNOME环境下看不见,不过如果开机启动到控制台然后执行xinit(或者有些机器在进入GNOME加载显卡驱动前)你看到的灰色网格背景的窗口就是root window了;
3. 你可以自己新建一个窗口让mplayer的video输出到这个窗口上:mplayer -wid 0Xxxxx xxx.avi
4. 参考Ubuntu下的一个工具xwininfo,可以抓窗口的id,位置,大小等信息
usage: xwininfo [-options ...]
where options include:
-help print this message
-display host:dpy X server to contact
-root use the root window
-id windowid use the window with the specified id
-name windowname use the window with the specified name
-int print window id in decimal
-children print parent and child identifiers
-tree print children identifiers recursively
-stats print window geometry [DEFAULT]
-bits print window pixel information
-events print events selected for on window
-size print size hints
-wm print window manager hints
-shape print shape extents
-frame don't ignore window manager frames
-english print sizes in english units
-metric print sizes in metric units
-all -tree, -stats, -bits, -events, -wm, -size, -shape
/*--------------Begin:capture.c------------------*/
#include <gtk/gtk.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>
#include <gdk/gdkx.h>
void do_capture_screenshot (char *file, int sec)
{
gint x, y;
GdkScreen* cur_screen = NULL;
GdkWindow* window = NULL;
GdkPixbuf* pixbuf_screenshot = NULL;
GdkRectangle rect;
GdkRectangle screen_rect;
g_printf("ready to capture.....\r\n");
sleep(sec);
if (cur_screen == NULL)
cur_screen = gdk_screen_get_default (); //get screen
screen_rect.x = 0;
screen_rect.y = 0;
screen_rect.width = gdk_screen_get_width (cur_screen); //get screen width
screen_rect.height = gdk_screen_get_height (cur_screen); //get screen height
g_print("screen_rect: x=%d,y=%d,w=%d,h=%d\n",screen_rect.x,screen_rect.y,screen_rect.width,screen_rect.height);
window = gdk_screen_get_root_window (cur_screen); //get window by screen
//Window xwin = GDK_WINDOW_XID(window); //get window id
//g_print("xwindow id is %x\n",xwin);
gdk_window_get_origin (window, &x, &y); //get origin point
rect.x = x;
rect.y = y;
gdk_drawable_get_size (GDK_DRAWABLE (window), &rect.width,&rect.height); //get drawable size
g_print("rect: x=%d,y=%d,w=%d,h=%d\n",rect.x,rect.y,rect.width,rect.height);
if (! gdk_rectangle_intersect (&rect, &screen_rect, &rect)) { //obtain the intersect area from rect and screen_rect
g_print("Capture failed!...\r\n");
return;
}
g_print("capture rect: x=%d,y=%d,w=%d,h=%d\n",rect.x,rect.y,rect.width,rect.height);
pixbuf_screenshot =
gdk_pixbuf_get_from_drawable (NULL, window,
NULL,rect.x - x, rect.y - y, 0, 0,
rect.width, rect.height); //get pixbuf from drawable widget
gdk_pixbuf_save (pixbuf_screenshot, file, "jpeg", NULL, "quality","100", NULL); //save pixbuf to jpeg format file
g_object_unref (pixbuf_screenshot); //free pixbuf
g_print("Capture saved!!!\r\n");
return;
}
int main( int argc, char *argv[])
{
int cmd, sec;
char *file = NULL;
time_t tt;
struct tm *tm_ptr = NULL;
file = (char *)malloc(32);
time(&tt);
tm_ptr = localtime(&tt);
strftime(file, 32, "%Y%m%d%H%M%S", tm_ptr);
strcat(file, ".jpg");
sec = 3;
gtk_init (&argc, &argv);
while ((cmd = getopt(argc, argv, "o:s:")) != -1) {
switch (cmd) {
case 'o':
file = optarg;
break;
case 's':
sec = atoi(optarg);
break;
default:
break;
}
}
do_capture_screenshot(file, sec);
return 0;
}