【发布时间】:2017-10-21 18:42:05
【问题描述】:
我想使用 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;
}
但是当我打印这些值时,我没有得到我所期望的......
如果我使用 grabc 之类的工具选择像素 (0, 0) 的 RGB 值,我会得到:
#85377e
133,55,126
但我的代码的第一次打印是:
126
145
198
...
看起来我很好地获得了第一个像素的第一个值,对应于蓝色,但其余的都是错误的。
【问题讨论】:
-
我没有使用 Linux 帧缓冲区的经验,但是您获得的像素缓冲区是否不是从您认为的 (0,0) 开始的?例如。您选择了左上角的值,但缓冲区从右下角开始。
-
当您尝试读取帧缓冲区数据时,您是否在 X Window 系统中?也许这是不可能的。
-
关键问题是 XWindow 可能根本不使用内核中的帧缓冲区。据我所知,像 amd 或 nvidia 这样的 gpu 不会在内核中的 fb 驱动程序上进行中继。但是当通过
ctrl+alt+fn切换到控制台时,我相信你可以得到正确的帧缓冲区 rgb 值。 -
fbgrab -b 24 test.png是否达到了您的预期? -
无论如何,如果您使用 X Window System,this 应该会有所帮助。只需打开
/tmp/fbe_buffer而不是/dev/fb0。
标签: c linux linux-kernel device-driver framebuffer