c++ - programa - ¿Cómo hacer una captura de pantalla correctamente con xlib?
como hacer una captura de pantalla en el celular (3)
Estoy tratando de capturar una imagen de la pantalla para usarla en screencasting. Por lo tanto, necesito una solución rápida y no puedo confiar en programas shell como import o xwd.
Este es el código que he escrito hasta ahora, pero falla y me da una imagen basura, que parece mostrar fragmentos de varias imágenes con colores extraños juntos.
http://s9.postimage.org/dqnkgkwr1/blah.png
¿Alguna idea sobre lo que estoy haciendo mal?
#include <X11/Xlib.h>
#include <X11/X.h>
#include <cstdio>
#include <CImg.h>
using namespace cimg_library;
int main()
{
Display *display = XOpenDisplay(NULL);
Window root = DefaultRootWindow(display);
XWindowAttributes gwa;
XGetWindowAttributes(display, root, &gwa);
int width = gwa.width;
int height = gwa.height;
XImage *image = XGetImage(display,root, 0,0 , width,height,AllPlanes, ZPixmap);
unsigned char *array = new unsigned char[width * height * 3];
unsigned long red_mask = image->red_mask;
unsigned long green_mask = image->green_mask;
unsigned long blue_mask = image->blue_mask;
for (int x = 0; x < width; x++)
for (int y = 0; y < height ; y++)
{
unsigned long pixel = XGetPixel(image,x,y);
unsigned char blue = pixel & blue_mask;
unsigned char green = (pixel & green_mask) >> 8;
unsigned char red = (pixel & red_mask) >> 16;
array[(x + width * y) * 3] = red;
array[(x + width * y) * 3+1] = green;
array[(x + width * y) * 3+2] = blue;
}
CImg<unsigned char> pic(array,width,height,1,3);
pic.save_png("blah.png");
printf("%ld %ld %ld/n",red_mask>> 16, green_mask>>8, blue_mask);
return 0;
}
Está equivocado acerca de la forma en que se presenta la array
en la memoria, ya que puede averiguarlo declarando img
antes del bucle y agregando este printf
a su bucle interno:
printf("%ld %ld %u %u %u/n",x,y,pic.offset(x,y,0),pic.offset(x,y,1),pic.offset(x,y,2));
Esto rinde (en mi pantalla 1920x1200):
0 0 0 2304000 4608000
0 1 1920 2305920 4609920
0 2 3840 2307840 4611840
y así sucesivamente, lo que indica que las subimágenes rojas / verdes / azules se mantienen "juntas" en lugar de que los tres componentes de color de un solo píxel estén adyacentes entre sí.
Los accesores integrados de CImg harán que su código funcione:
pic(x,y,0) = red;
pic(x,y,1) = green;
pic(x,y,2) = blue;
La imagen debe almacenarse en la memoria como R1R2R3R4R5R6 ...... G1G2G3G4G5G6 ....... B1B2B3B4B5B6. almacenamiento cimg
Puedes usar libpng
int code = 0;
FILE *fp;
png_structp png_ptr;
png_infop png_info_ptr;
png_bytep png_row;
// Open file
fp = fopen ("test.png", "wb");
if (fp == NULL){
fprintf (stderr, "Could not open file for writing/n");
code = 1;
}
// Initialize write structure
png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr == NULL){
fprintf (stderr, "Could not allocate write struct/n");
code = 1;
}
// Initialize info structure
png_info_ptr = png_create_info_struct (png_ptr);
if (png_info_ptr == NULL){
fprintf (stderr, "Could not allocate info struct/n");
code = 1;
}
// Setup Exception handling
if (setjmp (png_jmpbuf (png_ptr))){
fprintf(stderr, "Error during png creation/n");
code = 1;
}
png_init_io (png_ptr, fp);
// Write header (8 bit colour depth)
png_set_IHDR (png_ptr, png_info_ptr, width, height,
8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
// Set title
char *title = "Screenshot";
if (title != NULL){
png_text title_text;
title_text.compression = PNG_TEXT_COMPRESSION_NONE;
title_text.key = "Title";
title_text.text = title;
png_set_text (png_ptr, png_info_ptr, &title_text, 1);
}
png_write_info (png_ptr, png_info_ptr);
// Allocate memory for one row (3 bytes per pixel - RGB)
png_row = (png_bytep) malloc (3 * width * sizeof (png_byte));
// Write image data
int x, y;
for (y = 0; y < height; y++){
for (x = 0; x < width; x++){
unsigned long pixel = XGetPixel (image, x, y);
unsigned char blue = pixel & blue_mask;
unsigned char green = (pixel & green_mask) >> 8;
unsigned char red = (pixel & red_mask) >> 16;
png_byte *ptr = &(png_row[x*3]);
ptr[0] = red;
ptr[1] = green;
ptr[2] = blue;
}
png_write_row (png_ptr, png_row);
}
// End write
png_write_end (png_ptr, NULL);
// Free
fclose (fp);
if (png_info_ptr != NULL) png_free_data (png_ptr, png_info_ptr, PNG_FREE_ALL, -1);
if (png_ptr != NULL) png_destroy_write_struct (&png_ptr, (png_infopp)NULL);
if (png_row != NULL) free (png_row);