我正在尝试使用 Xlib 和 Cairo 制作屏幕截图,但是我不确定这样做的好方法,“stride”让我很困惑
以下是代码:
#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);
}
当我编译并运行程序时,一切似乎都运行得很好。然而,这是结果图像:
好不好吧? 我可能做错了什么?
答案 0 :(得分:5)
不要做所有这些复杂的魔术,让cairo为你做:
#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;
}
答案 1 :(得分: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 */
此外,从图像中获取蒙版,并且移位是硬编码的,这完全没有意义。计算面具的变化。