当前位置: 首页 > 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.dtcms.com/a/331235.html

相关文章:

  • 初识CNN01——认识CNN
  • 计算机组成原理20250814
  • 网络通信---Axios
  • 在线进销存系统高效管理网站源码搭建可二开
  • 考研408《计算机组成原理》复习笔记,第三章(7)——虚拟存储器
  • 考公VS考研,拼哪个性价比高?
  • 什么是域名抢注?域名抢注常见问题汇总
  • 图书商城小程序怎么做?实体书店如何在微信小程序上卖书?
  • 使用vllm运行智谱GLM-4.5V视觉语言模型推理服务
  • 如何使用 AI 大语言模型解决生活中的实际小事情?
  • 数据结构——线性表(链表,力扣简单篇)
  • vscode的wsl环境,ESP32驱动0.96寸oled屏幕
  • 失败存储:查看未成功的内容
  • vscode使用keil5出现变量跳转不了
  • 如何让手机访问本地服务器部署的网页?无公网IP内网主机应用,自定义外网地址,给任意网设备访问
  • 利用 Java 爬虫按图搜索 1688 商品(拍立淘)实战指南
  • 第一章 java基础
  • 手写MyBatis第17弹:ResultSetMetaData揭秘:数据库字段到Java属性的桥梁
  • 《C++》哈希表解析与实现
  • 能源行业数字化转型:边缘计算网关在油田场景的深度应用
  • Python机器学习与深度学习;Transformer模型/注意力机制/目标检测/语义分割/图神经网络/强化学习/生成式模型/自监督学习/物理信息神经网络等
  • 基于51单片机倒计时器秒表定时器数码管显示设计
  • vue+后端
  • 微服务、分布式概念-以及集群部署 vs 分布式部署
  • 容器运行时支持GPU,并使用1panel安装ollama
  • 将 pdf 转为高清 jpg
  • 数巅中标中建科技AI知识库项目,开启建筑业数智化新篇章
  • CSS aspect-ratio 属性
  • Multimodal RAG Enhanced Visual Description
  • Linux 对 RPM 包的管理