17 años en Internet

01 agosto 2013

Realizando una captura de pantalla con XImage y CImg (aplicación C++)

Googleando por internet he encontrado un trozo de  código que me ha gustado y me he tomado la licencia de mejorar y de optimizar. En concreto se trata de una aplicación simple escrita en C++ que permite realizar capturas de pantalla en entornos X11 (Linux): Básicamente se realiza un volcado del buffer del entorno gráfico en una estructura XImage para posteriormente volcar píxel a píxel a un objeto CImg que acto seguido se guarda como archivo PNG. 

Como resultado tenemos una aplicación ligera, rápida y funcional.

Para compilar requiere las siguientes dependencias: build-essential, libstdc++6-4.7-dev y cimg-dev. En este fichero adjunto incluyo el main.cpp con un sencillo makefile que he elaborado para compilarlo de forma simple. Para descomprimir el adjunto basta con hacer un tar xzvf screenshot.tgz.

main.cpp:


Esta segunda parte es más difícil de entender, desglosamos cada píxel de la estructura XImage en formato Red, Green, Blue y lo almacenamos en el objeto CImg. El problema radica en que objeto CImg contiene una matriz de 3 valores para representar un color (siendo la primera posición el tono rojo, la segunda el verde y la tercera el azul). Esto entra en conflicto con la estructura XImage, puesto que ésta almacena los tres tonos en una única variable de 24 bits (siendo RED los 8 bits de mayor peso, BLUE los 8 bits de menos peso y los 8 restantes son para GREEN).

Es decir, un píxel de XImage podría representarse de la siguiente forma:
00000000RRRRRRRRGGGGGGGGBBBBBBBB
Mientras que un píxel de CImg se representaría así:
pixel[X, Y, 0] = R
pixel[X, Y, 1] = G
pixel[X, Y, 2] = B
Esto significa que para aislar el color ROJO debemos desplazar la variable 16 posiciones a la derecha y que por su parte el color verde debe realizar lo mismo pero con sólo 8 posiciones. Aún así, sólo con desplazar no basta, puesto que en el caso del AZUL o VERDE siguen existiendo bits más significativos (a la izquierda) que representan originalmente un color distinto. Para ello realizaremos una operación lógica (el famoso "& mask") que aplicaremos previamente para quitar los bits que sean de otros colores. En el caso de RED no hay necesidad de realizarlo, puesto que se pierden los bits BLUE y GREEN en el desplazamiento final.


2 comentarios:

  1. 1- Hola, lo primero que quiero es darte las gracias por compartir esta información.

    2- Me ha salido funcionando pero solo si guardo la imagen en formato bmp. En PNG o JPEG me dice que no se soporta ese formato nativo o no se qué.

    3- El verdadero problema que tengo que no se resolver, es que la imagen muestre el cursor. No entiendo por qué muestra todo menos el cursor y me gustaría entenderlo.

    4- En fin, si alguien lee este comentario y
    me quiere ayudar
    no duden en escribirme directamente un e-mail a: 4620971@gmail.com.

    ResponderEliminar
  2. Hola RaFr, el problema es que la estructura XImage pertenece al X Client, el cual no interacciona con el ratón. La capa de input out y su interacción depende del X Server. Aquí tienes un esquema aclaratorio: http://en.wikipedia.org/wiki/X_Window_System#mediaviewer/File:X_client_server_example.svg

    Para capturar el ratón, en caso de ser necesario, debería de buscarse otra solución distinta a esta.

    El tema del png, veo que el enlace al proyecto original está roto. Ahora mismo estoy desplazado por tema de empresa, este fin de semana resubiré el proyecto a ver si es que te falta algún dato de makefile que declarar.

    ResponderEliminar

Si te ha gustado la entrada o consideras que algún dato es erróneo o símplemente deseas dar algún consejo, no dudes en dejar un comentario. Todo feedback es bienvenido siempre que sea respetuoso. También puedes contactarme vía Twitter @Hamster_ruso si lo consideras necesario.