Linux应用程序--FrameBuffer帧缓冲应用
文章说明: Linux显示基于FrameBuffer帧缓冲
硬件平台: 树莓派4B
测试说明: 由于桌面系统会一直刷新屏幕,需要关闭桌面,进入单用户模式测试(init 3);
打开设备文件:
#include <linux/fb.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
int fb;
fb = open("/dev/fb0", O_RDWR);
if (fd < 0)
{
perror("can not open device");
exit(1);
}
// 获取显示器可变参数
if (ioctl(fb, FBIOGET_VSCREENINFO, &vinfo))
{
perror("get screen var info");
exit(2);
}
printf("屏幕分辨率: %dx%d %dbit\r\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);
// 获取显示器固定参数
if (ioctl(fb, FBIOGET_FSCREENINFO, &finfo))
{
perror("get screen fix info");
exit(3);
}
// 每行字节数 = 行像素数*每个像素的字节数
printf("每行字节数: %d\r\n", finfo.line_length);
将FrameBuff映射至内存区:
int mem_size = vinfo.xres*vinfo.yres*vinfo.bits_per_pixel/8;
// 内存映射
pfb = (char*)mmap(0, mem_size, PROT_READ | PROT_WRITE, MAP_SHARED, fb, 0);
if(pfb == NULL)
{
perror("mmap error");
}
int x, y;
int offset;
// 画一个300*200的蓝色矩形
for (y = 0; y < 200; y++)
{
offset = y * finfo.line_length;
for (x = 0; x < 300; x++)
{
// 计算内存位置(bpp=32bit)
*(pfb + offset) = 255; // B
*(pfb + offset + 1) = 0; // G
*(pfb + offset + 2) = 0; // R
*(pfb + offset + 3) = 0; // 透明度(没发现啥用)
offset += 4; // 下一个位置(vinfo.bits_per_pixel / 8)
}
}
从文件读取24位图BMP文件并显示:
由于24位图文件仅存了RGB信息,与fb的32bit的不匹配,所以不能直接用cat命令显示,设置第4个字节的信息。
int fd;
int ret;
char buff[100];
char* p = pfb;
fd = open("./Tulips.bmp", O_RDONLY);
if(fd < 1)
{
perror("can not open file");
}
// 跳过54字节的BMP文件头
ret= read(fd, buff, 54);
while(cnt)
{
ret = read(fd, buff, 3);
*p++ = buff[0]; // 将前3个字节的RGB信息原样输出
*p++ = buff[1];
*p++ = buff[2];
*p++ = 0; // 设置第4字节的信息
}
close(fd);
显示的图倒立的,原因是BMP格式本身的问题,需要进行显示调整:
int *p = (int *)(pfb + mem_size) - 1;
while (read(fd, (char *)p--, 3))
{
if (p < pfb)
{
break;
}
}