J'essaie d'obtenir une capture d'écran de l'écran ou une fenêtre. J'ai essayé d'utiliser des fonctions de x11 et ça marche bien. Le problème est que l'obtention des pixels de Ximage prend beaucoup de temps. Que j'ai essayé de rechercher des réponses sur la façon de le faire en utilisant OpenGL. Voici ce que j'ai:
#include <stdlib.h> #include <stdio.h> #include <cstdio> #include <GL/glut.h> #include <GL/gl.h> #include <GL/glx.h> #include <X11/Xlib.h> int main(int argc, char **argv) { int width=1200; int height=800; //_____________________________---- Display *dpy; Window root; GLint att[] = { GLX_RGBA, GLX_DEPTH_SIZE, 24, GLX_DOUBLEBUFFER, None }; XVisualInfo *vi; GLXContext glc; dpy = XOpenDisplay(NULL); if ( !dpy ) { printf("\n\tcannot connect to X server\n\n"); exit(0); } root = DefaultRootWindow(dpy); vi = glXChooseVisual(dpy, 0, att); if (!vi) { printf("\n\tno appropriate visual found\n\n"); exit(0); } glXMakeCurrent(dpy, root, glc); glc = glXCreateContext(dpy, vi, NULL, GL_TRUE); printf("vendor: %s\n", (const char*)glGetString(GL_VENDOR)); //____________________________________________ glXMakeCurrent(dpy, root, glc); glEnable(GL_DEPTH_TEST); GLubyte* pixelBuffer = new GLubyte[sizeof(GLubyte)*width*height*3*3]; glReadBuffer(GL_FRONT); GLint ReadBuffer; glGetIntegerv(GL_READ_BUFFER,&ReadBuffer); glPixelStorei(GL_READ_BUFFER,GL_RGB); GLint PackAlignment; glGetIntegerv(GL_PACK_ALIGNMENT,&PackAlignment); glPixelStorei(GL_PACK_ALIGNMENT,1); glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_INT, pixelBuffer); int i; for (i=0;i<100;i++) printf("%u\n",((unsigned int *)pixelBuffer)[i]); return 0; }
3 Réponses :
Je ne pense pas ce que vous essayez de faire est possible. Vous ne pouvez pas utiliser OpenGL pour lire des pixels de la fenêtre que vous ne possédez pas et que vous n'utilisez probablement pas OpenGL. Vous devez vous tenir à X11. P>
Si vous avez ximage code> Vous pouvez obtenir des pixels bruts à partir de
xImage-> données code>. Assurez-vous simplement que vous le lisez au format correct. P>
Merci pour la réponse.Mais est-il possible de l'accélérer? Je ne pense pas que les pixels de ximage soient présentés linéairement par les données XImage->. Je pense que les pixels sont composés de multiples bits dispersés sur plusieurs octets. Vous avez donc besoin de nombreuses opérations de bits pour obtenir des valeurs de pixels. J'utilise la fonction xgepixel et xypixmap, image = xgetimage (DIS, DEFAULTIMAGEWINDOWWINDOW (DIS), 0, 0, Largeur, Hauteur, Allplanes, XYPIXMAP) ;. Peut-être que je shodld utiliser différents pixmap, tels que ZPIXMAP? Je dois obtenir des valeurs de pixels dans certains millisecondes, mais l'obtention de tous les pixels prend parfois une seconde. Est-ce que quelqu'un a des suggestions?
Utilisez XSHMGETImage () pour une méthode plus rapide. Pour un exemple, voir le code dans lien < / a>
xypixmap code> est un très mauvais format. Ce que vous voulez, c'est code> zpixmap code>, dans lequel les pixels sont présentés linéairement par le tampon
ximage-> data code>, comme vous le dites. Vous pouvez utiliser
xcb_image_get () code>, mais j'utilise
xcb_image_shm_get () code> et je peux obtenir tout
1920 * 1080 code> pixels à environ 600 fps ( c'est-à-dire moins de 2 ms) (
xcb_image_get () code> me donne 200 fps)
Vous pouvez utiliser XIHMGetImage, mais vous devez d'abord interroger les extensions du serveur X11 afin de vous assurer que l'extension MIT-SHM est disponible. Vous devez également savoir comment configurer et utiliser un segment de mémoire partagé pour cela. P>
Querifier l'extension: P>
http: // git .Videolan.org /? p = ffmpeg.git; a = blob; f = libavdevice / x11grab.c # L224 P>
Obtenir l'image: P>
http: // git .videolan.org /? p = ffmpeg.git; a = blob; f = libavdevice / x11grab.c # L537 P>
Les travaux suivants sont exécutés une fois à 140 fps sur ma plate-forme. xcb_image_get () code> (appelé avec
xcb_image_format_z_pixmap x />) stockera tous les pixels dans
ximg-> données code>, pixel par pixel. Sur ma plate-forme, chaque pixel est de 32 bits, chaque canal est de 8 bits, et il y a 3 canaux (à 8 bits par pixel n'est pas utilisé).
/*
gcc ss.c -o ss -lxcb -lxcb-image && ./ss
*/
#include <stdio.h>
#include <xcb/xcb_image.h>
xcb_screen_t* xcb_get_screen(xcb_connection_t* connection){
const xcb_setup_t* setup = xcb_get_setup(connection); // I think we don't need to free/destroy this!
return xcb_setup_roots_iterator(setup).data;
}
void xcb_image_print(xcb_image_t* ximg){
printf("xcb_image_print() Printing a (%u,%u) `xcb_image_t` of %u bytes\n\n", ximg->height, ximg->width, ximg->size);
for(int i=0; i < ximg->size; i += 4){
printf(" ");
printf("%02x", ximg->data[i+3]);
printf("%02x", ximg->data[i+2]);
printf("%02x", ximg->data[i+1]);
printf("%02x", ximg->data[i+0]);
}
puts("\n");
}
int main(){
// Connect to the X server
xcb_connection_t* connection = xcb_connect(NULL, NULL);
xcb_screen_t* screen = xcb_get_screen(connection);
// Get pixels!
xcb_image_t* ximg = xcb_image_get(connection, screen->root, 0, 0, screen->width_in_pixels, screen->height_in_pixels, 0xffffffff, XCB_IMAGE_FORMAT_Z_PIXMAP);
// ... Now all pixels are in ximg->data!
xcb_image_print(ximg);
// Clean-up
xcb_image_destroy(ximg);
xcb_disconnect(connection);
}
Bonjour, Savez-vous pourquoi la taille de l'image n'est pas 1024 * 768 * 3? (3 Parce que RVB) Sortie: xcb_image_print () Impression A (1024 768) xcb_image_t code> de 1572864 octets, profondeur: 16, BPP: 16
Je pense que c'est toujours 1024 * 768 * 4 code>, car chaque pixel est rembourré pour occuper exactement 4 octets. Donc, chaque pixel a 3 canaux (parce que RVB), mais il occupe 4 octets (un octet est donc toujours zéro). Je pense que c'est comme ça que ça se passe, bien que cela dépend probablement de votre chauffeur graphique ...
Qu'est-ce qui vous fait que l'utilisation de GL va le rendre plus rapide? Cela devrait être le même.
Combien de temps faut-il? Y a-t-il une transmission réseau impliquée? Êtes-vous juste en train de regarder stdout dans un terminal? Essayez de rediriger vers un fichier et utilisez la commande code> code>. Les caractères d'impression sur le terminal utilisent le même serveur X qui essaie désespérément de copier une image et de le marshall sur un protocole. Heisenberg peut s'appliquer; Votre technique d'inspection peut déformer les informations mêmes que vous recherchez.