如何从 Linux 帧缓冲区获取 RGB 像素值?

Ser*_*gio 5 c linux framebuffer device-driver linux-kernel

我想使用 Linux 以最有效的方式获取屏幕像素的 RGB 值。所以我决定使用 C 中的帧缓冲库(fb.h)来访问帧缓冲设备(/dev/fb0)并直接从中读取。

这是代码:

#include <stdint.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/mman.h>

int main() {

    int fb_fd;
    struct fb_fix_screeninfo finfo;
    struct fb_var_screeninfo vinfo;
    uint8_t *fb_p;

    /* Open the frame buffer device */
    fb_fd = open("/dev/fb0", O_RDWR);
    if (fb_fd < 0) {
        perror("Can't open /dev/fb0\n");
        exit(EXIT_FAILURE);
    }

    /* Get fixed info */
    if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo) < 0) {
        perror("Can't get fixed info\n");
        exit(EXIT_FAILURE);
    }

    /* Get variable info */
    if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo) < 0) {
        perror("Can't get variable info\n");
        exit(EXIT_FAILURE);
    }

    /* To access to the memory, it can be mapped*/
    fb_p = (uint8_t *) mmap(0, finfo.smem_len, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0);
    if (fb_p == MAP_FAILED) {
        perror("Can't map memory\n");
        exit(EXIT_FAILURE);
    }

    /* Print each byte of the frame buffer */
    for (int i = 0; i < finfo.smem_len; i++) {
        printf("%d\n", *(fb_p + i));

        // for (int j = 0; j < 500000000; j++);       /* Delay */
    }

    munmap(fb_p, 0);
        close(fb_fd);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是当我打印这些值时,我没有得到我所期望的......

如果我使用像grapc这样的工具选择像素(0, 0)的RGB值,我会得到这个:

#85377e
133,55,126
Run Code Online (Sandbox Code Playgroud)

但是我的代码的第一次打印是:

126
145
198
...
Run Code Online (Sandbox Code Playgroud)

看起来我很好地获得了第一个像素的第一个值,对应于蓝色,但其余部分是错误的。

pau*_*sm4 6

如果您查看grabc源代码(https://www.muquit.com/muquit/software/grabc/grabc.html),您会发现他正在查询X Windows(而不是硬件帧缓冲区本身)。

root_window=XRootWindow(display,XDefaultScreen(display));
target_window=selectWindow(display,&x,&y);
...
ximage=XGetImage(display,target_window,x,y,1,1,AllPlanes,ZPixmap);
...
color->pixel=XGetPixel(ximage,0,0);
XDestroyImage(ximage);
Run Code Online (Sandbox Code Playgroud)

无论它的价值如何 - 并且出于多种不同的原因 - 我强烈鼓励您考虑这样做。

你也可能对此有兴趣:

  • @Sergio `/dev/fb` 不是“直接来自设备”。是一位司机发来的。驱动程序可能对设备实际在做什么一无所知 - 因为 X 服务器*正在*直接与设备通信。 (7认同)