首页 > 解决方案 > libx11 无法在 Fedora OS C 上截屏

问题描述

我不是 C 编程和 Linux 操作系统开发方面的专家,但我的任务是在 Ubuntu 和 Fedora 操作系统上制作屏幕截图。在网上搜索后,我发现了很多关于如何使用 C 语言和 libX11 进行操作的主题和问题。最后,我将所有我能找到的东西结合在一种方法中,该方法捕获屏幕截图并保存到 .png 文件。
我安装了两台虚拟机——一台是 Ubuntu 18.04,第二台是 Fedora 30。当我在 Ubuntu 上运行我的代码时——它运行良好,当我在 Fedora 上运行它时——我有一个带有黑色内容的屏幕截图文件。我的代码是:

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/extensions/XShm.h>
#include <stdio.h>
#include <inttypes.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <cairo.h>
#include <cairo-xlib.h>
#include <stdlib.h>

    int get_shift (int mask) {
        int shift = 0;
        while (mask) {
            if (mask & 1) break;
            shift++;
            mask >>=1;
        }
        return shift;
    }

   void takeScreenshot() {
    Display *d;
    int s;
    XImage *image;
    XShmSegmentInfo shminfo;
    d = XOpenDisplay(NULL);
    s = DefaultScreen(d);
    unsigned int width = DisplayWidth(d,s);
    unsigned int height = DisplayHeight(d,s);


    image = XShmCreateImage(d, 
        DefaultVisual(d,s), // Use a correct visual. Omitted for brevity     
        24,   // Determine correct depth from the visual. Omitted for brevity
        ZPixmap, NULL, &shminfo, width, height); 

    shminfo.shmid = shmget(IPC_PRIVATE,
        image->bytes_per_line * image->height,
        IPC_CREAT|0777);

    shminfo.shmaddr = image->data = shmat(shminfo.shmid, 0, 0);
    shminfo.readOnly = False;

    XShmAttach(d, &shminfo);

    XShmGetImage(d,
        RootWindow(d,s),
        image,
        0,
        0,
        AllPlanes);


    cairo_surface_t *surface;
    int stride;

    stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, width);
    unsigned char *data = malloc(stride * height);

    int redShift = get_shift(image->red_mask);
    int greenShift = get_shift(image->green_mask);
    int blueShift = get_shift(image->blue_mask);

    printf("r_shift: %d; g_shift: %d; b_shift: %d\n",redShift, greenShift, blueShift);
    printf("byte order: %d\n", image->byte_order);
    printf("bytes per line: %d\n", image->bytes_per_line);
    printf("bites per pixel: %d\n", image->bits_per_pixel);
    printf("r_mask: %lu; g_mask: %lu; b_mask: %lu\n", image->red_mask, image->green_mask, image->blue_mask);
    printf("bitmap_bit_order: %d  bitmap_pad: %d format: %d xoffset: %d\n", image->bitmap_bit_order, image->bitmap_pad, image->format, image->xoffset);

    int x, y;
     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)>>redShift;
            unsigned char green = (image->green_mask & pixel)>>greenShift;
            unsigned char blue = (image->blue_mask & pixel)>>blueShift;

            data[y * stride + x * 4 + 0] = blue;
            data[y * stride + x * 4 + 1] = green;
            data[y * stride + x * 4 + 2] = red;   
        }
    }

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

    cairo_status_t surfaceStatus = cairo_surface_status(surface);

   const char *r = cairo_status_to_string (surfaceStatus);
   printf("%s\n", &r[0]);

    int writepngRes = cairo_surface_write_to_png(
                surface,
                "test.png");

    printf("surf status: %d; write result: %d\n", surfaceStatus, writepngRes);
    cairo_surface_destroy(surface);
}


    int main(int argc, char* argv[]) {
        takeScreenshot();
        return 0;
    }

我使用以下命令构建此代码:
gcc code.c -o code.so -lXss -lX11 -lXext -fPIC -I/usr/include/cairo -lcairo

两台机器上的设置完全相同,我检查的是两个系统的位掩码、字节顺序和每像素字节数相等。我正在寻求有关如何找到错误原因的建议,也许建议要调试哪些东西。谢谢!
更新:
当我在两个平台上运行此代码时,我看到完全相同的输出:

r_shift: 16; g_shift: 8; b_shift: 0
byte order: 0
bytes per line: 5464
bites per pixel: 32
r_mask: 16711680; g_mask: 65280; b_mask: 255
bitmap_bit_order: 0  bitmap_pad: 32 format: 2 xoffset: 0
no error has occurred
surf status: 0; write result: 0

标签: clinuxx11cairo

解决方案


推荐阅读