c - 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
解决方案
推荐阅读
- python-3.x - 我想在 python 中添加两个非常大的数字,即使是 bignum 也无法处理
- docker - Kafka docker - 错误:“无法找到分区 0 的领导者”
- laravel - 如何在视图中查看控制器中检索到的数据?
- jquery - Jquery ui 图标未显示
- javascript - 有没有办法在相关表上使用 where 子句查询表,但仍然使用 Sequelize 将所有相关内容抓取到原始表?
- android - UI Automator Viewer 无法截屏
- python - 如果字符串有 X 个以 @#$ 开头的单词,则 Python 正则表达式匹配:
- javascript - JavaScript:从文件名打开文件作为对象
- c# - 测试之间的共享上下文
- javascript - 如何以角度将天数添加到当前日期