2011-05-19 17 views
8

estoy tratando de obtener una captura de pantalla de la pantalla o una ventana. Intenté usar funciones de X11 y funciona bien. El problema es que obtener los píxeles de XImage lleva mucho tiempo. Que intenté buscar algunas respuestas sobre cómo hacerlo usando OpenGL. Esto es lo que tengo:captura de pantalla usando OpenGL y/o X11

#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; 
} 

cuando ejecuto el programa devuelve un error: error X de solicitudes con error: BadAccess (intento de acceder a recursos privados denegado) opcode mayor de solicitudes con error: 199() código de operación Menor de solicitudes con error: 26 número de serie de la solicitud ha fallado: 20 número de serie actual en la corriente de salida: 20

Si comento la línea con glXMakeCurrent (dpy, raíz, GLC); antes glc = glXCreateContext (dpy, vi, NULL, GL_TRUE); no devuelve errores, pero todos los píxeles son 0.

¿Cómo debo solucionar este problema? Soy nuevo en openGL y tal vez me esté perdiendo algo importante aquí. Tal vez también existe otra forma de obtener píxeles de la pantalla o ventana específica?

+0

¿Qué le hace lo que el uso de GL hará que sea más rápido? Debería ser lo mismo. –

+0

¿Cuánto tiempo está tomando? ¿Hay transmisión de red involucrada? ¿Estás viendo stdout en una terminal? Intente redireccionar a un archivo y use el comando 'time'. La impresión de caracteres en el terminal utiliza el mismo servidor X que está tratando desesperadamente de copiar una imagen y ordenarla sobre un protocolo. Heisenberg puede aplicar; su técnica de inspección puede estar distorsionando la información que busca. –

Respuesta

7

No creo que lo que intentas hacer sea posible. No puede usar OpenGL para leer píxeles de la ventana que no posee y que probablemente ni siquiera usan OpenGL. Debes apegarte a X11.

Si tiene XImage puede obtener píxeles brutos desde ximage->data. Solo asegúrate de leerlo en el formato correcto.

http://tronche.com/gui/x/xlib/graphics/images.html

+0

Gracias por la respuesta. ¿Pero es posible acelerarlo? No creo que los píxeles de XImage sean presentados linealmente por ximage-> data. Creo que los píxeles están compuestos de múltiples bits dispersos en múltiples bytes, por lo que necesita una gran cantidad de operaciones de bits para obtener valores de píxeles. Estoy usando la función XGetPixel y XYPixmap, image = XGetImage (dis, DefaultRootWindow (dis), 0, 0, ancho, alto, AllPlanes, XYPixmap) ;. ¿Tal vez debería usar Pixmap diferente, como ZPixmap? Tengo que obtener valores de píxeles en algunos milisegundos, pero la obtención de todos los píxeles lleva a veces hasta un segundo. ¿Alguien tiene alguna sugerencia? –

+1

Use XShmGetImage() para un método más rápido. Para ver un ejemplo, vea el código en [link] (http://git.videolan.org/?p=ffmpeg.git;a=blob;f=libavdevice/x11grab.c) – Christian

Cuestiones relacionadas