在ubuntu虚拟机中使用framebuffer画图

条件一:使用ctrl+alt+F1切换到命令行显示模式(恢复ctrl+alt+F7);
(新版本ubuntu20,更改为ctrl+alt+F6进入命令行,ctrl+alt+F1恢复)
条件二:使用sudo运行程序。

代码参考如下:

fbmap.h

/*
 *  fb矩阵输出
 */
#ifndef _FBMAP_H_
#define _FBMAP_H_
#include <stdint.h>

//指定fb设备
#define FB_PATH "/dev/fb0"

//屏幕宽高(调用一次fb_output之后更新)
extern int fb_width, fb_height;
/*
 *  屏幕输出
 *  data: 图像数组,数据长度必须为 width*height*3, RGB格式
 *  offsetX, offsetY: 屏幕起始位置
 *  width, height: 图像宽高
 */
void fb_output(uint8_t *data, uint32_t offsetX, uint32_t offsetY, uint32_t width, uint32_t height);
#endif

fbmap.c

/*
 *  fb矩阵输出
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <linux/fb.h>

#include "fbmap.h"

typedef struct
{
    int fd;
    unsigned char *fb;
    size_t fbSize;
    struct fb_var_screeninfo fbInfo;
    //bytes per point
    int bpp;
    //bytes width, height
    int bw, bh;
} FbMap;

static FbMap *fbmap = NULL;
int fb_width = 1024, fb_height = 600;

void fb_release(void)
{
    if (!fbmap)
        return;
    if (fbmap->fb)
        munmap(fbmap->fb, fbmap->fbSize);
    if (fbmap->fd > 0)
        close(fbmap->fd);
    free(fbmap);
    fbmap = NULL;
}
//返回0正常
int fb_init(void)
{
    if (fbmap)
        return 0;

    fbmap = (FbMap *)calloc(1, sizeof(FbMap));

    fbmap->fd = open(FB_PATH, O_RDWR);
    if (fbmap->fd < 1)
    {
        fprintf(stderr, "fb_init: open %s err \r\n", FB_PATH);
        fb_release();
        return -1;
    }

    if (ioctl(fbmap->fd, FBIOGET_VSCREENINFO, &fbmap->fbInfo) < 0)
    {
        fprintf(stderr, "fb_init: ioctl FBIOGET_VSCREENINFO err \r\n");
        fb_release();
        return -1;
    }
    printf("frameBuffer: %s, %d x %d, %dbytes / %dbpp\r\n",
           FB_PATH, fbmap->fbInfo.xres, fbmap->fbInfo.yres, fbmap->fbInfo.bits_per_pixel / 8, fbmap->fbInfo.bits_per_pixel);

    fbmap->bpp = fbmap->fbInfo.bits_per_pixel / 8;
    fbmap->bw = fbmap->bpp * fbmap->fbInfo.xres;
    fbmap->bh = fbmap->bpp * fbmap->fbInfo.yres;
    fbmap->fbSize = fbmap->fbInfo.xres * fbmap->fbInfo.yres * fbmap->bpp;

    fb_width = fbmap->fbInfo.xres;
    fb_height = fbmap->fbInfo.yres;

    fbmap->fb = (unsigned char *)mmap(0, fbmap->fbSize, PROT_READ | PROT_WRITE, MAP_SHARED, fbmap->fd, 0);
    if (!fbmap->fb)
    {
        fprintf(stderr, "fb_init: mmap size %ld err \r\n", fbmap->fbSize);
        fb_release();
        return -1;
    }
    return 0;
}
/*
 *  屏幕输出
 *  data: 图像数组,数据长度必须为 width*height*3, RGB格式
 *  offsetX, offsetY: 屏幕起始位置
 *  width, height: 图像宽高
 */
void fb_output(uint8_t *data, uint32_t offsetX, uint32_t offsetY, uint32_t width, uint32_t height)
{
    int x, y, offset;
    //初始化检查
    if (fb_init())
        return;
    //参数检查
    if (!data || width < 1 || height < 1)
        return;
    //起始坐标限制
    if (offsetX < 0)
        offsetX = 0;
    else if (offsetX >= fbmap->fbInfo.xres)
        return;
    if (offsetY < 0)
        offsetY = 0;
    else if (offsetY >= fbmap->fbInfo.yres)
        return;
    //范围限制
    if (width < 1)
        return;
    else if (offsetX + width - 1 >= fbmap->fbInfo.xres)
        width = fbmap->fbInfo.xres - offsetX;
    if (height < 1)
        return;
    else if (offsetY + height - 1 >= fbmap->fbInfo.yres)
        height = fbmap->fbInfo.yres - offsetY;
    //覆盖画图
    for (y = 0; y < height; y++)
    {
        //当前行在fb数据的偏移
        offset = (y + offsetY) * fbmap->bw + (0 + offsetX) * fbmap->bpp;
        //画data中的一行数据
        for (x = 0; x < width; x++)
        {
            if (fbmap->bpp == 4)
                fbmap->fb[offset + 3] = 0x00; //A
            fbmap->fb[offset + 2] = *data++;  //R
            fbmap->fb[offset + 1] = *data++;  //G
            fbmap->fb[offset + 0] = *data++;  //B
            offset += fbmap->bpp;
        }
    }
}

main.c

#include <stdio.h>
#include <stdint.h>
#include <unistd.h>

#include "fbmap.h"

#define WIDTH 300
#define HEIGHT 300

// 设置颜色
void set(uint8_t *map, uint32_t mapSize, uint32_t rgbColor)
{
    uint32_t offset;
    uint8_t r = (rgbColor >> 16) & 0xFF;
    uint8_t g = (rgbColor >> 8) & 0xFF;
    uint8_t b = (rgbColor >> 0) & 0xFF;
    for (offset = 0; offset < mapSize;)
    {
        map[offset++] = r;
        map[offset++] = g;
        map[offset++] = b;
    }
}

int main(void)
{
	uint8_t rgbMap[WIDTH * HEIGHT * 3];
	while(1)
	{
		set(rgbMap, sizeof(rgbMap), 0xFF0000);//红
		fb_output(rgbMap, 0, 0, WIDTH, HEIGHT);
		sleep(1);

		set(rgbMap, sizeof(rgbMap), 0x00FF00);//绿
		fb_output(rgbMap, 0, 0, WIDTH, HEIGHT);
		sleep(1);

		set(rgbMap, sizeof(rgbMap), 0x0000FF);//蓝
		fb_output(rgbMap, 0, 0, WIDTH, HEIGHT);
		sleep(1);
	}
    return 0;
}

编译:gcc -o out main.c fbmap.c
运行:sudo ./out (一定要切换命令行显示模式)

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值