Задать вопрос

X11 Си — как написать функцию для поиска пикселя на экране?

Хочу создать аналог UOpilot для Линукс. На данный момент пробую создать нормальную функцию для поиска пикселя конкретного цвета на экране. Немного бродил по просторам интернета и склепал следующий код:
char *findColor_range(int startX, int startY,
					  int endX, int endY,
					  int startRed, int endRed, int startGreen, int endGreen, int startBlue, int endBlue) {
	Display *d = XOpenDisplay((char *) NULL);
	XImage *image;
	int x, y;
	XColor c;
	char *res;

	for(x = startX; x <= endX; x++) {
		for(y = startY; y <= endY; y++) {
			image = XGetImage(d, RootWindow(d, DefaultScreen(d)), x, y, 1, 1, AllPlanes, XYPixmap);
			c.pixel = XGetPixel(image, 0, 0);
			XFree(image);
			XQueryColor(d, DefaultColormap(d, DefaultScreen(d)), &c);
			if(c.red / 256 >= startRed && c.red / 256 <= endRed &&
			   c.green / 256 >= startGreen && c.green / 256 <= endGreen &&
			   c.blue / 256 >= startBlue && c.blue / 256 <= endBlue) {
				asprintf(&res, "%d,%d", x, y);
				return res;
			}
		}
	}
	asprintf(&res, "0");
	return res;
}


Здесь работает поиск не по конкретному цвету, а по диапазону цветов. По названию переменных и коде думаю поймете. Это работает (хотя не очень-то и быстро, 300х300 прочесало секунды так за 4). А вот функция где по конкретному цвету, но другой алгоритм поиска:
char *findColor(int startX, int startY,
				int endX, int endY,
				int red, int green, int blue) {
	Display *d = XOpenDisplay((char *) NULL);
	XImage *image;
	int x, y;
	XColor c;
	char *res;

	image = XGetImage(d, RootWindow(d, DefaultScreen(d)), startX, startY, endX - startX, endY - startY, AllPlanes, XYPixmap);

	for(x = startX; x <= endX; x++) {
		for(y = startY; y <= endY; y++) {
			c.pixel = XGetPixel(image, x - startX, y - startY);
			XFree(image);
			XQueryColor(d, DefaultColormap(d, DefaultScreen(d)), &c);
			if(c.red / 256 == red && c.green / 256 == green && c.blue / 256 == blue) {
				asprintf(&res, "%d,%d", x, y);
				return res;
			}
		}
	}
	asprintf(&res, "0");
	return res;
}


Здесь я хотел сделать, чтобы XGetImage вызывалось только раз, а соответственно нужно будет искать и этой "картинке". Ну, зато не надо каждый раз брать его отдельно для каждого пикселя. Так вот, во время выполнения этой второй функции у меня куча ошибок (в общем, ошибка адресации). Если надо, можете увидеть ее ниже.
*** glibc detected *** ./test01: double free or corruption (top): 0x000000000150dda0 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x7eb96)[0x7f3d2451eb96]
/usr/lib/x86_64-linux-gnu/libX11.so.6(XFree+0x9)[0x7f3d248a06a9]
./test01[0x400e6b]
./test01[0x400ffe]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7f3d244c176d]
./test01[0x4006f9]
======= Memory map: ========
00400000-00402000 r-xp 00000000 08:06 2224180                            /home/tolik/Dropbox/C_and_CPP/BotFramework/test01
00601000-00602000 r--p 00001000 08:06 2224180                            /home/tolik/Dropbox/C_and_CPP/BotFramework/test01
00602000-00603000 rw-p 00002000 08:06 2224180                            /home/tolik/Dropbox/C_and_CPP/BotFramework/test01
014d6000-01519000 rw-p 00000000 00:00 0                                  [heap]
7f3d23a5f000-7f3d23a74000 r-xp 00000000 08:05 135186                     /lib/x86_64-linux-gnu/libgcc_s.so.1
7f3d23a74000-7f3d23c73000 ---p 00015000 08:05 135186                     /lib/x86_64-linux-gnu/libgcc_s.so.1
7f3d23c73000-7f3d23c74000 r--p 00014000 08:05 135186                     /lib/x86_64-linux-gnu/libgcc_s.so.1
7f3d23c74000-7f3d23c75000 rw-p 00015000 08:05 135186                     /lib/x86_64-linux-gnu/libgcc_s.so.1
7f3d23c75000-7f3d23c7a000 r-xp 00000000 08:05 661801                     /usr/lib/x86_64-linux-gnu/libXdmcp.so.6.0.0
7f3d23c7a000-7f3d23e79000 ---p 00005000 08:05 661801                     /usr/lib/x86_64-linux-gnu/libXdmcp.so.6.0.0
7f3d23e79000-7f3d23e7a000 r--p 00004000 08:05 661801                     /usr/lib/x86_64-linux-gnu/libXdmcp.so.6.0.0
7f3d23e7a000-7f3d23e7b000 rw-p 00005000 08:05 661801                     /usr/lib/x86_64-linux-gnu/libXdmcp.so.6.0.0
7f3d23e7b000-7f3d23e7d000 r-xp 00000000 08:05 661790                     /usr/lib/x86_64-linux-gnu/libXau.so.6.0.0
7f3d23e7d000-7f3d2407c000 ---p 00002000 08:05 661790                     /usr/lib/x86_64-linux-gnu/libXau.so.6.0.0
7f3d2407c000-7f3d2407d000 r--p 00001000 08:05 661790                     /usr/lib/x86_64-linux-gnu/libXau.so.6.0.0
7f3d2407d000-7f3d2407e000 rw-p 00002000 08:05 661790                     /usr/lib/x86_64-linux-gnu/libXau.so.6.0.0
7f3d2407e000-7f3d24080000 r-xp 00000000 08:05 135178                     /lib/x86_64-linux-gnu/libdl-2.15.so
7f3d24080000-7f3d24280000 ---p 00002000 08:05 135178                     /lib/x86_64-linux-gnu/libdl-2.15.so
7f3d24280000-7f3d24281000 r--p 00002000 08:05 135178                     /lib/x86_64-linux-gnu/libdl-2.15.so
7f3d24281000-7f3d24282000 rw-p 00003000 08:05 135178                     /lib/x86_64-linux-gnu/libdl-2.15.so
7f3d24282000-7f3d2429f000 r-xp 00000000 08:05 662409                     /usr/lib/x86_64-linux-gnu/libxcb.so.1.1.0
7f3d2429f000-7f3d2449e000 ---p 0001d000 08:05 662409                     /usr/lib/x86_64-linux-gnu/libxcb.so.1.1.0
7f3d2449e000-7f3d2449f000 r--p 0001c000 08:05 662409                     /usr/lib/x86_64-linux-gnu/libxcb.so.1.1.0
7f3d2449f000-7f3d244a0000 rw-p 0001d000 08:05 662409                     /usr/lib/x86_64-linux-gnu/libxcb.so.1.1.0
7f3d244a0000-7f3d24655000 r-xp 00000000 08:05 135165                     /lib/x86_64-linux-gnu/libc-2.15.so
7f3d24655000-7f3d24855000 ---p 001b5000 08:05 135165                     /lib/x86_64-linux-gnu/libc-2.15.so
7f3d24855000-7f3d24859000 r--p 001b5000 08:05 135165                     /lib/x86_64-linux-gnu/libc-2.15.so
7f3d24859000-7f3d2485b000 rw-p 001b9000 08:05 135165                     /lib/x86_64-linux-gnu/libc-2.15.so
7f3d2485b000-7f3d24860000 rw-p 00000000 00:00 0 
7f3d24860000-7f3d24990000 r-xp 00000000 08:05 661788                     /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0
7f3d24990000-7f3d24b90000 ---p 00130000 08:05 661788                     /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0
7f3d24b90000-7f3d24b91000 r--p 00130000 08:05 661788                     /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0
7f3d24b91000-7f3d24b95000 rw-p 00131000 08:05 661788                     /usr/lib/x86_64-linux-gnu/libX11.so.6.3.0
7f3d24b95000-7f3d24bb7000 r-xp 00000000 08:05 135145                     /lib/x86_64-linux-gnu/ld-2.15.so
7f3d24d05000-7f3d24d4c000 rw-p 00000000 00:00 0 
7f3d24d93000-7f3d24d98000 rw-p 00000000 00:00 0 
7f3d24db3000-7f3d24db7000 rw-p 00000000 00:00 0 
7f3d24db7000-7f3d24db8000 r--p 00022000 08:05 135145                     /lib/x86_64-linux-gnu/ld-2.15.so
7f3d24db8000-7f3d24dba000 rw-p 00023000 08:05 135145                     /lib/x86_64-linux-gnu/ld-2.15.so
7fff24a57000-7fff24a78000 rw-p 00000000 00:00 0                          [stack]
7fff24bd5000-7fff24bd7000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]

Скорее всего, ошибка где-то в алгоритме.
P.S. Вызывал через
printf("%s\n", findColor(1, 1, 300, 300, 255, 255, 255));
  • Вопрос задан
  • 3333 просмотра
Подписаться 3 Оценить 1 комментарий
Решения вопроса 1
@Korobochka
У вас во втором примере XFree(image); вызывается в цикле, а image = XGetImage(...) вызывается только один раз перед циклом, в отличии от первого примера. Вот и происходит "double free".
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы