首页 > *nix技术 > 通过Xlib截屏

通过Xlib截屏

2022年11月6日 发表评论 阅读评论 594 次浏览

一,测试环境
硬件:VirtualBox 7.0
操作系统:UbuntuKylin 20.04.3 LTS

二,测试
参考:https://github.com/SollyBunny/screenshot
下载screenshot-main.zip,直接make报错,需要修改。

修改如下,去掉我暂时不关注的逻辑:

// filename: main.c

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/cursorfont.h>
#include <png.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>

/* LSBFirst: BGRA -> RGBA */
static void convertrow_lsb(unsigned char *drow, unsigned char *srow, XImage *img)
{
	int sx, dx;
	for(sx = 0, dx = 0; dx < img->bytes_per_line; sx += 4) {
		drow[dx++] = srow[sx + 2]; /* B -> R */
		drow[dx++] = srow[sx + 1]; /* G -> G */
		drow[dx++] = srow[sx];     /* R -> B */
		if (img->depth == 32) drow[dx++] = srow[sx + 3]; /* A -> A */
		else                  drow[dx++] = 255;
	}
}

/* MSBFirst: ARGB -> RGBA */
static void convertrow_msb(unsigned char *drow, unsigned char *srow, XImage *img)
{
	int sx, dx;
	for(sx = 0, dx = 0; dx < img->bytes_per_line; sx += 4) {
		drow[dx++] = srow[sx + 1]; /* G -> R */
		drow[dx++] = srow[sx + 2]; /* B -> G */
		drow[dx++] = srow[sx + 3]; /* A -> B */
		if (img->depth == 32) drow[dx++] = srow[sx]; /* R -> A */
		else                  drow[dx++] = 255;
	}
}

static void writeaspng(XImage *img, FILE *fp)
{
	png_structp png_struct_p;
	png_infop png_info_p;
	void (*convert)(unsigned char *, unsigned char *, XImage *);
	unsigned char *drow = NULL, *srow;
	int h;
	png_struct_p = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
	png_info_p = png_create_info_struct(png_struct_p);
	png_init_io(png_struct_p, fp);
	png_set_IHDR(
		png_struct_p, png_info_p, img->width, img->height, 8,
		PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
		PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE
	);          
	png_write_info(png_struct_p, png_info_p);
	srow = (unsigned char *)img->data;
	drow = calloc(1, img->width * 4);
	if(img->byte_order == LSBFirst) convert = convertrow_lsb;
	else                            convert = convertrow_msb;
	for(h = 0; h < img->height; ++h) {
		convert(drow, srow, img);
		srow += img->bytes_per_line;
		png_write_row(png_struct_p, drow);
	}
	png_write_end(png_struct_p, NULL);
	free(drow);
	png_free_data(png_struct_p, png_info_p, PNG_FREE_ALL, -1);
	png_destroy_write_struct(&png_struct_p, NULL);
}

int main(int argc, char* argv[]) 
{
	Display *display = XOpenDisplay(":0");
	int screen = XDefaultScreen(display);
	Window root = RootWindow(display, screen);

	XImage *image = XGetImage(
		display, root, 0, 0,
		DisplayWidth(display, screen), DisplayHeight(display, screen),
		AllPlanes, ZPixmap );

	char filename[64];
	sprintf(filename, "%ld.png", time(NULL));
	printf("Info: filename is %s\n", filename);

	FILE *fp;
	fp = fopen(filename, "wb");
	writeaspng(image, fp);
	fclose(fp);

	XCloseDisplay(display);
	return 0;	
}

编译:
$ gcc main.c -o screenshot -lX11 -lpng -O0 -g
运行:
$ ./screenshot
Invalid MIT-MAGIC-COOKIE-1 key段错误 (核心已转储)

因为是通过ssh远程到VirtualBox,找不到桌面?
直接登录桌面本地,在桌面里启用终端,再执行./screenshot,生成的图片是ok的,完美的截取了桌面屏幕。
再在ssh终端执行也正常了。

再试试注销掉本地桌面,退出到登录界面,此时在ssh终端执行仍然报段错误。
所以这个程序需要有用户登录桌面后才能正常执行?
通过gdb调试,挂在XDefaultScreen()函数里,看来如果未登录的话,这个函数无法执行?

错误相关帖子:

https://unix.stackexchange.com/questions/199891/invalid-mit-magic-cookie-1-key-when-trying-to-run-program-remotely

https://askubuntu.com/questions/1238389/invalid-mit-magic-cookie-1-key-message-while-running-a-program-with-the-termin

https://unix.stackexchange.com/questions/649651/invalid-mit-magic-cookie-1-keyxhost-unable-to-open-display-0

https://serverfault.com/questions/51005/how-to-use-xauth-to-run-graphical-application-via-other-user-on-linux

https://blog.csdn.net/Anne332/article/details/118903921

https://www.jb51.cc/linux/696301.html

看来,只能参考x11vnc的代码了

待续~

——–
更新:
通过参考x11vnc的代码运行,导出一个环境变量就可以了:
$ export XAUTHORITY=/var/run/lightdm/root/:0
$ sudo ./screenshot
Info: filename is 1667785594.png

参考:
快速了解X:https://tldp.org/HOWTO/Remote-X-Apps.html

https://tldp.org/HOWTO/Remote-X-Apps-6.html

转载请保留地址:http://www.lenky.info/archives/2022/11/3221http://lenky.info/?p=3221


备注:如无特殊说明,文章内容均出自Lenky个人的真实理解而并非存心妄自揣测来故意愚人耳目。由于个人水平有限,虽力求内容正确无误,但仍然难免出错,请勿见怪,如果可以则请留言告之,并欢迎来讨论。另外值得说明的是,Lenky的部分文章以及部分内容参考借鉴了网络上各位网友的热心分享,特别是一些带有完全参考的文章,其后附带的链接内容也许更直接、更丰富,而我只是做了一下归纳&转述,在此也一并表示感谢。关于本站的所有技术文章,欢迎转载,但请遵从CC创作共享协议,而一些私人性质较强的心情随笔,建议不要转载。

法律:根据最新颁布的《信息网络传播权保护条例》,如果您认为本文章的任何内容侵犯了您的权利,请以Email或书面等方式告知,本站将及时删除相关内容或链接。

分类: *nix技术 标签: ,
  1. 本文目前尚无任何评论.
您必须在 登录 后才能发布评论.