如何使用xlib正确截取屏幕截图?

我正在尝试捕获屏幕图像以用于截屏。 因此我需要一个快速的解决方案,并且不能依赖shell程序,如import或xwd。

这是我到目前为止编写的代码,但是它失败并且给了我一个垃圾图像,它似乎只是显示了几个奇怪颜色的图像片段被拼凑在一起。

http://sofzh.miximages.com/c%2B%2B/blah.png

关于我做错的任何想法?

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

你错了关于array在内存中的布局方式,你可以通过在循环之前声明img并将这个printf添加到你的内循环来找到:

 printf("%ld %ld %u %u %u\n",x,y,pic.offset(x,y,0),pic.offset(x,y,1),pic.offset(x,y,2)); 

这会产生(在我的1920×1200屏幕上):

 0 0 0 2304000 4608000 0 1 1920 2305920 4609920 0 2 3840 2307840 4611840 

等等,表示红色/绿色/蓝色子图像保持“在一起”而不是单个像素的三个颜色分量彼此相邻。

内置的CImg访问器将使您的代码工作:

 pic(x,y,0) = red; pic(x,y,1) = green; pic(x,y,2) = blue; 

你可以使用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); 

图像必须存储在内存中,如R1R2R3R4R5R6 …… G1G2G3G4G5G6 ……. B1B2B3B4B5B6。 cimg存储