当前位置: 首页 > news >正文

Linux下的软件编程——framebuffer(文件操作的应用)

UI技术:User interface

framebuffer:帧缓冲,帧缓存技术

                      linux内核专门为图形化显示提供的一套应用程序接口

主要思想:

1.打开显示设备(/dev/fb0)

2.获取显示设备相关参数(分辨率,像素格式)—>  ioctl

3.建立显存空间和用户空间的内存映射

4.向映射的用户空间写入RGB颜色值

5.解除映射关系

6.关闭显示设备

void  *mmap(void *addr,size_t length,int prot,int flags,int fd,off_t offset)

(1)功能:建立内存映射

(2)参数:addr:映射的用户空间首地址

                                NULL:让操作系统自己分配用户空间

                    length:要映射的空间大小

                    prot:操作权限

                              PROT_READ  Pages may  be  read

                              PROT_WRITE  Pages  may  be  written

                    flag:MAP_SHARED

                    fd:显示设备文件描述符

                    offset:偏移量

                                0:从显存开头映射

(3)返回值:成功:映射的用户空间首地址

                        失败:MAP_FAILED((void *)-1)

像素格式:RGB888:3—> 4

                  RGB565:2

实现代码:

主函数:

#include <stdio.h>
#include "framebuffer.h"unsigned char miao[4*33] = {
/*--  文字:  苗  --*/
/*--  仿宋24;  此字体下对应的点阵为:宽x高=32x33   --*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x18,0x00,0x00,0x38,0x1C,0x00,
0x00,0x1C,0x1C,0x00,0x00,0x18,0x1C,0x00,0x00,0x1C,0x1C,0x00,0x00,0x1C,0x18,0xF8,
0x00,0x1F,0xFF,0xFC,0x3F,0xFF,0xFE,0x00,0x1F,0xFC,0x38,0x00,0x00,0x1C,0x30,0x00,
0x00,0x1C,0x70,0x00,0x00,0x18,0x70,0x00,0x07,0x00,0x01,0xC0,0x03,0x07,0xFF,0xC0,
0x03,0xFF,0xFF,0x80,0x03,0xF3,0x81,0x80,0x03,0x83,0x83,0x80,0x03,0x83,0x83,0x80,
0x03,0x83,0xFB,0x80,0x03,0xFF,0xFF,0x80,0x03,0xBF,0x83,0x80,0x03,0x83,0x83,0x80,
0x03,0x83,0x83,0x80,0x03,0x83,0x83,0x80,0x03,0x83,0x83,0x80,0x03,0xFF,0xFF,0x00,
0x03,0xFF,0xFF,0x00,0x03,0x80,0x03,0x00,0x01,0x80,0x02,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00};
unsigned char jia[4*33] = {
/*--  文字:  佳  --*/
/*--  仿宋24;  此字体下对应的点阵为:宽x高=32x33   --*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x70,0x00,
0x00,0x38,0x38,0x00,0x00,0x38,0x30,0x00,0x00,0x78,0x30,0x00,0x00,0x70,0x30,0x00,
0x00,0xE0,0x30,0x00,0x00,0xC0,0x33,0x80,0x01,0xC3,0xFF,0xC0,0x03,0xCF,0xFC,0x00,
0x07,0xC2,0x30,0x00,0x06,0xC0,0x30,0x00,0x0C,0xC0,0x33,0xF0,0x18,0xC3,0xFF,0xF8,
0x30,0xFF,0xFC,0x00,0x20,0xCC,0x70,0x00,0x00,0xC0,0x70,0x00,0x00,0xC0,0x70,0x00,
0x00,0xC0,0x70,0x80,0x00,0xC0,0xFF,0xC0,0x00,0xCF,0xFF,0x00,0x00,0xC7,0x70,0x00,
0x00,0xC0,0x70,0x00,0x00,0xC0,0x70,0x00,0x01,0xC0,0x7F,0xFC,0x01,0xFF,0xFF,0xFC,
0x01,0xFF,0xF0,0x00,0x00,0xC0,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00};
unsigned char yi[4*33] = {/*--  文字:  毅  --*/
/*--  仿宋24;  此字体下对应的点阵为:宽x高=32x33   --*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x70,0x63,0x00,
0x00,0x38,0x3F,0x80,0x00,0x3F,0xBF,0x80,0x0F,0xFF,0xF3,0x80,0x0F,0xFE,0x33,0x80,
0x01,0xCE,0x33,0x00,0x00,0xCC,0x73,0x00,0x00,0xFD,0x73,0x00,0x00,0xFF,0xF3,0xB0,
0x1F,0xFE,0x63,0xF8,0x0F,0x78,0xE1,0xF0,0x00,0xF3,0xC1,0xC0,0x01,0xF3,0x9F,0xC0,
0x03,0xB7,0xFF,0xC0,0x0F,0x7E,0x63,0x80,0x3C,0xFC,0x63,0x80,0x33,0xF8,0xE7,0x00,};int main(void)
{int ret = init_fb("/dev/fb0");if (ret < 0){return -1;}//4. 向映射的用户空间写入RGB颜色值//draw_point(400, 300, 0x00FF0000);// draw_Vertical_line(0,0,0x00FF0000);//draw_point(300,300,0x00FF0000);//draw_horizontal_line(0,0,0x00FF0000);draw_rectangle(200,100,400,300,0xFF0000);//draw_round(400,300,100,0xFF0000);// draw_bmp(0, 0, "./2.bmp");// draw_word(268, 305, miao, 4, 33, 0x00FF0000);// draw_word(100,200, jia, 4, 33, 0x00FF0000);// draw_word(200,300, yi, 4, 33, 0x00FF0000);// uninit_fb();return 0;
}
#ifndef __FRAMEBUFFER_H__
#define __FRAMEBUFFER_H__
#define RGB_FMT_888 32
#define RGB_FMT_565 16
#pragma pack(1)
//bmp文件相关信息
typedef struct tagBITMAPFILEHEADER {short    bfType;         // 文件类型标志int      bfSize;         // 文件大小,单位为字节short    bfReserved1;    // 保留字节short    bfReserved2;    // 保留字节int      bfOffBits;      // 数据偏移量,即实际图像数据开始的位置
}Bmp_file_head_t;
//bmp图像信息
typedef struct tagBITMAPINFOHEADER {int   biSize;         // BITMAPINFOHEADER的大小,单位为字节int    biWidth;        // 位图的宽度,单位为像素int    biHeight;       // 位图的高度,单位为像素short    biPlanes;       // 目标设备的位平面数,必须为1short    biBitCount;     // 每像素位数(颜色深度)int   biCompression;  // 图像压缩类型int   biSizeImage;    // 图像大小,单位为字节int    biXPelsPerMeter;// 水平分辨率,单位为像素/米int    biYPelsPerMeter;// 垂直分辨率,单位为像素/米int   biClrUsed;      // 实际使用颜色数int   biClrImportant; // 重要颜色数
}Bmp_info_t;
#pragma pack()
extern int init_fb(char *devname);
extern int uninit_fb();
extern void draw_point(int x, int y, unsigned int col);
extern void draw_Vertical_line(int x,int y,unsigned int col);
extern void draw_horizontal_line(int x,int y,unsigned int col);
extern void draw_rectangle(int x,int y,int height,int width,int col);
extern void draw_round(int x,int y,int r,int col);
extern int get_bmp_head_info(const char *bmpname, Bmp_file_head_t *pheadinfo, Bmp_info_t *pbmpinfo);
extern void draw_bmp(int x,int y, char *bmpname);
extern void draw_word(int x,int y,unsigned char *pword,int w,int h,unsigned int col);
#endif
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include "framebuffer.h"void *pmem = NULL;
int fb;
struct fb_var_screeninfo vinfo;int init_fb(char *devname)
{//1. 打开显示设备(/dev/fb0)fb = open(devname, O_RDWR);if (-1 == fb){perror("open fb error");return -1;}//2. 获取显示设备相关参数(分辨率,像素格式)int ret = ioctl(fb, FBIOGET_VSCREENINFO, &vinfo);if (ret < 0){perror("ioctl error");return -1;}printf("xres = %d, yres = %d\n", vinfo.xres, vinfo.yres);printf("xres_virtual = %d, yres_virtual = %d\n", vinfo.xres_virtual, vinfo.yres_virtual);printf("bits_per_pixel = %d\n", vinfo.bits_per_pixel);//3. 建立显存空间和用户空间的内存映射size_t len = vinfo.xres_virtual * vinfo.yres_virtual * vinfo.bits_per_pixel/8;pmem = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fb, 0);if (pmem == MAP_FAILED){perror("mmap error");return -1;}return 0;
}int uninit_fb()
{//5. 解除映射关系//6. 关闭显示设备size_t len = vinfo.xres_virtual * vinfo.yres_virtual * vinfo.bits_per_pixel/8;munmap(pmem, len);close(fb);}void draw_point(int x, int y, unsigned int col)
{if (x >= vinfo.xres || y >= vinfo.yres){return ;}if (vinfo.bits_per_pixel == RGB_FMT_888){unsigned int *p = pmem;*(p+vinfo.xres_virtual*y+x) = col;}else if (vinfo.bits_per_pixel == RGB_FMT_565){unsigned short *p = pmem;*(p+vinfo.xres_virtual*y+x) = col;}
}void draw_Vertical_line(int x,int y,unsigned int col)
{if(x >= vinfo.xres || y >= vinfo.yres){return ;}if(vinfo.bits_per_pixel == RGB_FMT_888){unsigned int *p = pmem;for(int i = 0;i < vinfo.yres_virtual;++i){*(p+vinfo.xres_virtual*(y+i)+x) = col;}}if(vinfo.bits_per_pixel == RGB_FMT_565){unsigned int *p = pmem;for(int i = 0;i < vinfo.yres_virtual;++i){*(p+vinfo.xres_virtual*(y+i)+x) = col;}}
}
void draw_horizontal_line(int x,int y,unsigned int col)
{if(x >= vinfo.xres || y >= vinfo.yres){return ;}if(vinfo.bits_per_pixel == RGB_FMT_888){unsigned int *p = pmem;for(int i = 0;i < vinfo.xres_virtual;++i){*(p+vinfo.xres_virtual*y+(x+i)) = col;}}if(vinfo.bits_per_pixel == RGB_FMT_565){unsigned int *p = pmem;for(int i = 0;i < vinfo.xres_virtual;++i){*(p+vinfo.xres_virtual*y+(x+i)) = col;}}
}
void draw_rectangle(int x,int y,int height,int width,int col)
{if(x >= vinfo.xres || y >= vinfo.yres){return ;}if(height+y >= vinfo.yres || width+x >= vinfo.xres){return ;}if(vinfo.bits_per_pixel == RGB_FMT_888){unsigned int *p = pmem;for(int i = 0;i < width;++i){*(p+vinfo.xres_virtual*y+(i+x)) = col;*(p+vinfo.xres_virtual*(y+height-1)+(x+i)) = col;}for(int j = 0;j < height;++j){*(p+vinfo.xres_virtual*(y+j)+x) = col;*(p+vinfo.xres_virtual*(y+j)+(x+width-1)) = col; }}if(vinfo.bits_per_pixel == RGB_FMT_565){unsigned int *p = pmem;for(int i = 0;i < width;++i){*(p+vinfo.xres_virtual*y+(i+x)) = col;*(p+vinfo.xres_virtual*(y+height-1)+(x+i)) = col;}for(int j = 0;j < height;++j){*(p+vinfo.xres_virtual*(y+j)+x) = col;*(p+vinfo.xres_virtual*(y+j)+(x+width-1)) = col; } }}
void draw_round(int x,int y,int r,int col)
{if(x >= vinfo.xres || y >= vinfo.yres){return ;}if(r > x || r > y ||r <=0 || x + r >= vinfo.xres || y + r >= vinfo.yres){return ;}if(vinfo.bits_per_pixel == RGB_FMT_888){   unsigned int *p = pmem;int dx = r;int dy = 0;int err = 0;while(dx >= dy){*(p+vinfo.xres_virtual*(y+dy) + (x + dx)) = col;*(p+vinfo.xres_virtual*(y+dx) + (x + dy)) = col;*(p+vinfo.xres_virtual*(y+dx) + (x - dy)) = col;*(p+vinfo.xres_virtual*(y+dy) + (x - dx)) = col; *(p+vinfo.xres_virtual*(y-dy) + (x - dx)) = col;*(p+vinfo.xres_virtual*(y-dx) + (x - dy)) = col;*(p+vinfo.xres_virtual*(y-dx) + (x + dy)) = col;   *(p+vinfo.xres_virtual*(y-dy) + (x + dx)) = col;if(err <= 0){dy +=1;err += 2*dy + 1;}if(err > 0){dx -= 1;err -= 2*dx + 1;}}}}int get_bmp_head_info(const char *bmpname, Bmp_file_head_t *pheadinfo, Bmp_info_t *pbmpinfo)
{FILE *fp = fopen(bmpname, "r");if (NULL == fp){perror("fopen error");return -1;}fread(pheadinfo, sizeof(Bmp_file_head_t), 1, fp);fread(pbmpinfo, sizeof(Bmp_info_t), 1, fp);fclose(fp);return 0;
}void draw_bmp(int x, int y, char *bmpname)
{Bmp_file_head_t headinfo;Bmp_info_t bmpinfo;get_bmp_head_info("./2.bmp", &headinfo, &bmpinfo);int fd = open(bmpname, O_RDONLY);if (-1 == fd){perror("open bmp error");return ;}lseek(fd, 54, SEEK_SET);unsigned char *buff = malloc(bmpinfo.biHeight*bmpinfo.biWidth*bmpinfo.biBitCount/8);read(fd, buff, bmpinfo.biHeight*bmpinfo.biWidth*bmpinfo.biBitCount/8);close(fd);unsigned char *p = buff;unsigned char r, g, b;for (int j = bmpinfo.biHeight-1; j >= 0; j--){for (int i = 0; i < bmpinfo.biWidth; i++){b = *p;++p;g = *p;++p;r = *p;++p;if (vinfo.bits_per_pixel == RGB_FMT_888){unsigned int col = (r << 16) | (g << 8) | (b << 0);draw_point(i+x, j+y, col);}else if  (vinfo.bits_per_pixel == RGB_FMT_565){unsigned short col = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);draw_point(i+x, j+y, col);}}}free(buff);}
//w = 2, h = 19
void draw_word(int x,int y,unsigned char *pword,int w,int h,unsigned int col)
{for(int j = 0;j < h;j++){for(int i = 0;i < w;i++){unsigned char tmp = pword[i+j*w];for(int k = 0;k < 8;k++){if(tmp & 0x80){draw_point(x+i*8+k,y+j,col);}else{}tmp = tmp << 1;}}}
}

          

http://www.xdnf.cn/news/1295929.html

相关文章:

  • 表达式树实战:Unity动态逻辑编程
  • tp5集成elasticsearch笔记
  • Unity中的神经网络遗传算法实战
  • 一篇文章读懂.Net的依赖注入
  • .NET 的 WebApi 项目必要可配置项都有哪些?
  • .Net4.0 WPF中实现下拉框搜索效果
  • 面试题之项目中git如何进行管理
  • 如何启动本机mysql数据库
  • 在mysql> 下怎么运行 .sql脚本
  • XCTF-warmup详细题解(含思考过程)
  • Morph Studio-一站式AI视频创作平台
  • Vue浅学
  • Elasticsearch 中如何配置 RBAC 权限-实现安全的访问控制
  • QT6(创建第一个QT项目)
  • Win10上Qt使用Libcurl库
  • Qt 实现Ymodem协议源码分享
  • MySQL工具包中的其他程序
  • 从概率填充到置信度校准:GPT-5如何从底层重构AI的“诚实”机制
  • 树莓派 4B 上部署 Minecraft PaperMC 1.20.x 的一键部署脚本
  • ASQA: 面向模糊性事实问题的长格式问答数据集与评估框架
  • C#WPF实战出真汁02--登录界面设计
  • 利用 Python 爬虫按图搜索 1688 商品(拍立淘)实战指南
  • Windows批处理脚本自动合并当前目录下由You-get下载的未合并的音视频文件
  • LeetCode 分类刷题:2302. 统计得分小于 K 的子数组数目
  • 我的第一个开源项目-jenkins集成k8s项目
  • 开疆智能Ethernet转ModbusTCP网关连接UR机器人配置案例
  • 区块链 + 域名Web3时代域名投资的新风口(上)
  • 《算法导论》第 25 章:所有结点对的最短路径问题
  • 常见的tls检测的绕过方案
  • Mybatis学习笔记(二)