2011-11-23 23 views
22

Tôi đang cố chụp ảnh màn hình để sử dụng trong truyền hình. Vì vậy, tôi cần một giải pháp nhanh, và không thể dựa vào các chương trình shell như import hay xwd.Làm cách nào để chụp ảnh màn hình chính xác với xlib?

Đây là mã tôi đã viết cho đến nay, nhưng nó không thành công và cho tôi một hình ảnh rác, mà dường như chỉ ra những mảnh của một số hình ảnh với màu sắc lẻ ném với nhau.

http://s9.postimage.org/dqnkgkwr1/blah.png

Bất kỳ ý tưởng nào về những gì tôi đang làm sai?

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

Xin chào @lalaland, bạn có thể chia sẻ mã cuối cùng của mình không, điều này có hỗ trợ nhiều màn hình không? – Noitidart

+2

@Noitidart Có, tôi đã hỗ trợ nhiều màn hình. Tôi nghĩ https://github.com/Lalaland/ScreenCap/blob/master/src/screenCapturerImpl.cpp có thể là tệp phù hợp. Đã không chạm vào mã trong năm mặc dù. Mã này được viết kém, nhưng nếu bạn muốn sử dụng nó, tôi sẽ ném một giấy phép BSD lên đó. – Lalaland

+0

Cảm ơn rất nhiều @ lalaland đã trả lời rất nhanh! Nếu bạn có thời gian là ok nếu tôi đăng trên trang vấn đề của bạn vì vậy tôi có thể hiểu làm thế nào nó hoạt động với nhiều màn hình – Noitidart

Trả lời

14

Bạn đang nhầm lẫn về cách array được đặt ra trong bộ nhớ, như bạn có thể tìm hiểu bằng cách tuyên bố img trước khi vòng lặp và thêm printf này để lặp bên trong của bạn:

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

sản lượng này (trên màn hình 1920x1200 của tôi):

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

và cứ như vậy, cho biết các hình ảnh con màu đỏ/xanh/xanh được giữ "cùng" thay vì ba các thành phần màu của một điểm ảnh duy nhất nằm cạnh nhau.

Các accessors CImg BUILTIN sẽ làm cho công việc mã của bạn:

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

Bạn đã đúng :) – Lalaland

4

Bạn có thể sử dụng 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); 
0

hình ảnh phải được lưu trữ trong bộ nhớ như R1R2R3R4R5R6 ...... G1G2G3G4G5G6 ... .... B1B2B3B4B5B6. cimg storage

Các vấn đề liên quan