2013-03-19 66 views
1

我試圖讓使用Xlib的開羅截圖,但我不知道這樣做的好辦法,「步幅」實在是令人困惑我。製作使用的Xlib和開羅庫截圖[失效]

下面的代碼:

#include <stdio.h> 
#include <stdlib.h> 
#include <malloc.h> 
#include <cairo.h> 
#include <X11/Xlib.h> 
#include <X11/Xutil.h> 

int main(int argc, char** argv) { 

    int x, y; 

    Display *disp; 
    Window root; 
    XWindowAttributes watts; 
    XImage *image; 
    cairo_surface_t *surface; 
    unsigned int width; 
    unsigned int height; 
    int stride; 

    disp = XOpenDisplay(NULL); 
    root = DefaultRootWindow(disp); 
    XGetWindowAttributes(disp, root, &watts); 
    width = watts.width; 
    height = watts.height; 

    image = XGetImage(disp, root, watts.x, watts.y, width, height, AllPlanes, ZPixmap); 
    stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, width); 
    unsigned char *data = malloc(width * height * 3); 

    for (y = 0; y < height; ++y) 
     for (x = 0; x < width; ++x) { 

      unsigned long pixel = XGetPixel(image, x, y); 

      unsigned char red = (image->red_mask & pixel); 
      unsigned char green = (image->green_mask & pixel) >> 8; 
      unsigned char blue = (image->blue_mask & pixel) >> 16; 

      data[(y * width + x) * 3] = red; 
      data[(y * width + x) * 3 + 1] = green; 
      data[(y * width + x) * 3 + 2] = blue; 
     } 


    surface = cairo_image_surface_create_for_data(
      data, 
      CAIRO_FORMAT_RGB24, 
      width, height, 
      stride); 

    cairo_surface_write_to_png(
      surface, 
      "test.png"); 


    cairo_surface_destroy(surface); 
    free(data); 

    return (EXIT_SUCCESS); 
} 

當我編譯並運行程序,一切似乎都工作得很好。然而,這裏的結果圖像:?

quite a mess

挺亂的權利.. 什麼我可能做錯了嗎?

回答

2

TFM:

CAIRO_FORMAT_RGB24 
    each pixel is a 32-bit quantity, with the upper 8 bits unused 

TFM:

stride = cairo_format_stride_for_width (format, width); 
data = malloc (stride * height); 

因此,正確的索引計算是

data[y * stride + x * 4 + 0] = blue; 
data[y * stride + x * 4 + 1] = green; 
data[y * stride + x * 4 + 2] = red; /* yes, in this order */ 

另外,口罩從圖像拍攝,並轉移是硬編碼,這是絕對沒有意義的。計算蒙版的變化。

+0

你應該使用不同的指數計算,因爲像素大小是32位,而不是24查看更新。 – 2013-03-19 19:35:06

+0

謝謝,這會生成屏幕截圖,但它都是綠色的 – user544262772 2013-03-19 19:35:49

+0

這是因爲您沒有使用正確的班次和/或使用R,G和B的錯誤順序。 – 2013-03-19 19:37:25

4

而不是做這一切的複雜的魔法,讓開羅爲你做它:

#include <cairo.h> 
#include <cairo-xlib.h> 
#include <X11/Xlib.h> 

int main(int argc, char** argv) { 
    Display *disp; 
    Window root; 
    cairo_surface_t *surface; 
    int scr; 

    disp = XOpenDisplay(NULL); 
    scr = DefaultScreen(disp); 
    root = DefaultRootWindow(disp); 

    surface = cairo_xlib_surface_create(disp, root, DefaultVisual(disp, scr), 
      DisplayWidth(disp, scr), DisplayHeight(disp, scr)); 
    cairo_surface_write_to_png(
      surface, 
      "test.png"); 
    cairo_surface_destroy(surface); 

    return 0; 
} 
+0

非常感謝這個答案,我打算改變我的代碼到這個,似乎有點容易。 – user544262772 2013-03-23 10:06:44

+0

Hi @Uli。我發現你對我正在部署的概念證明的評論非常有用。您能否指出我需要的庫,以便鏈接到您的代碼並獲得可執行文件?謝謝 – lrleon 2015-10-12 19:34:47

+0

使用pkg-config:pkg-config --libs --cflags cairo x11 – 2015-10-13 07:48:06