一、UI技术: User interface

(1)framebuffer: 帧缓冲、帧缓存技术
Linux内核专门为图形化显示提供的一套应用程序接口。

流程如下:

1. 打开显示设备 (/dev/fb0)
2. 获取显示设备相关参数(分辨率,像素格式)---》ioctl
3. 建立显存空间和用户空间的内存映射
4. 向映射的用户空间写入RGB颜色值
5. 解除映射关系
6. 关闭显示设备

二、mmap(内存映射)函数使用:将显存映射到用户空间,方便直接读写:

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
功能: 建立内存映射
参数:
addr: 映射的用户空间首地址
NULL: 让操作系统自己分配用户空间
length: 要映射的空间大小
prot: 操作权限
PROT_READ Pages may be read.
PROT_WRITE Pages may be written
flag: MAP_SHARED
fd: 显示设备文件描述符
offset: 偏移量
0: 从显存开头映射
返回值:
成功: 映射的用户空间首地址
失败: MAP_FAILED ((void *)-1)

三、练习:

1. 封装函数绘制横线
2. 封装函数绘制竖线
3. 封装函数绘制矩形
4. 封装函数绘制圆
5. 封装函数绘制bmp图片
6. 封装函数绘制文字

framebuffer.c

//framebuffer.c文件:#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"
#include <math.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_x_line(int x1,int x2,int y,unsigned int col)
{if(x1 >= vinfo.xres || x2 >= vinfo.xres || y >= vinfo.yres){return;}for(int i = 0;i < x2 - x1;++i){if(vinfo.bits_per_pixel == RGB_FMT_888){unsigned int *p =pmem;*(p+vinfo.xres_virtual*y+(x1+i))= col;}else if(vinfo.bits_per_pixel == RGB_FMT_565){unsigned short *p = pmem;*(p+vinfo.xres_virtual*y+(x1+i))=col;}}}
void draw_y_line(int x,int y1,int y2,unsigned int col)
{if(x >= vinfo.xres || y1 >= vinfo.yres || y2 >=vinfo.yres){return;}for(int i = 0;i < y2-y1;++i){if(vinfo.bits_per_pixel == RGB_FMT_888){unsigned int *p = pmem;*(p + vinfo.xres_virtual*(y1+i)+x) = col;}else if(vinfo.bits_per_pixel == RGB_FMT_565){unsigned short *p =pmem;*(p+vinfo.xres_virtual*(y1+i)+x) = col;}}
}void draw_rect(int x, int y, int w, int h, unsigned int col) 
{if (w <= 0 || h <= 0) return;  // 宽度或高度无效draw_x_line(x, x + w - 1, y, col);        // 上边draw_x_line(x, x + w - 1, y + h - 1, col);// 下边draw_y_line(x, y, y + h - 1, col);        // 左边draw_y_line(x + w - 1, y, y + h - 1, col);// 右边
}void draw_circle(int x, int y, int r, unsigned int col)
{int x0 = 0;int y0 = 0;int si = 0;for (si = 0; si <= 360; si++){x0 = r * sin(3.14 * 2 / 360 * si) + x; y0 = r * cos(3.14 * 2 / 360 * si) + y;draw_point(x0, y0, col);}
}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("./1.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);}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;}}}
}
//framebuffer.h文件:#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_x_line(int x1,int x2,int y,unsigned int col);
extern void draw_y_line(int x,int y1,int y2,unsigned int col);
extern void draw_rect(int x,int y,int w,int h,unsigned int col);
extern void draw_circle(int x, int y, int r, unsigned 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
//main.c文件:#include <stdio.h>
#include "framebuffer.h"/*
1. 打开显示设备(/dev/fb0)
2. 获取显示设备相关参数(分辨率,像素格式)
3. 建立显存空间和用户空间的内存映射
4. 向映射的用户空间写入RGB颜色值
5. 解除映射关系
6. 关闭显示设备
*/unsigned char D[2*33]={/*--  文字:  D  --*/
/*--  仿宋24;  此字体下对应的点阵为:宽x高=16x33   --*/
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x80,0xFF,0xE0,
0x38,0x78,0x38,0x3C,0x38,0x1C,0x38,0x1E,0x38,0x1E,0x38,0x1E,0x38,0x0E,0x38,0x0E,
0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x0E,0x38,0x1E,0x38,0x1E,0x38,0x1E,0x38,0x1C,
0x38,0x3C,0x38,0x78,0x38,0xF0,0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00};int main(void)
{int ret = init_fb("/dev/fb0");if (ret < 0){return -1;}//4. 向映射的用户空间写入RGB颜色值//draw_point(400, 300, 0x00FF0000);draw_x_line(200,500,200,0xFF00FF00);draw_y_line(300,100,500,0xFFFFFFFF);draw_rect(100,100,200,150,0xFFFFFFFF);draw_circle(100, 100, 50, 0xFF0000); // draw_bmp(0, 0, "./1.bmp");//draw_word(200, 300, D, 2, 33, 0x00FF0000);uninit_fb();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/93147.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/93147.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/93147.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

408每日一题笔记 41-50

答案&#xff1a;A 解析&#xff1a;CSMA/CD 协议里&#xff0c;“争用期” 就是信号在总线上最远两个端点之间往返传输的时间&#xff0c;也叫冲突窗口&#xff0c;选 A。

【物联网】基于树莓派的物联网开发【26】——树莓派开启串口并配置串口助手Minicom

串口配置 &#xff08;1&#xff09;打开串口&#xff0c;终端输入命令&#xff1a; sudo raspi-config &#xff08;2&#xff09;串口设置选择Interfacing Options→Serial port→No→Yes→ok&#xff08;3&#xff09;设置开启&#xff0c;打开串口 &#xff08;4&#xff0…

考研/考公知识共享平台的设计与实现-项目分享

考研/考公知识共享平台的设计与实现-项目分享项目介绍项目摘要学生前台用例图管理员用例图系统流程图系统功能结构图实体图学生信息实体图资料信息管理实体图报考指南管理写在最后项目介绍 使用者&#xff1a;管理员、学生前台、学生后台 开发技术&#xff1a;MySQLJavaSpring…

一键设置 NTP 时区的脚本(亲测,适用于部署 K8S 的前置环境)

文章目录一、时区和时间同步的配置命令二、完整脚本ntp_timezone_setup.sh三、使用方法3.1、创建脚本3.2、赋予执行权限3.3、运行脚本3.4、验证一、时区和时间同步的配置命令 整理用于做时区和时间同步的配置几条命令分别如下&#xff1a; 1️⃣ 编辑 chrony 配置 vim /etc/…

BPMN编辑器技术实现总结AI时代的工作流编辑器

项目概述 基于 diagram.js 的 BPMN 流程设计器&#xff0c;通过依赖注入(DI)实现模块化扩展&#xff0c;自定义模块扩展与SVG图形渲染。后端工作流引擎自定义统一任务调度函数&#xff0c;实现异构模型统一调用。 核心技术架构 1. diagram.js 架构基础 核心模块组成 Canv…

两阶段最小二乘法(2SLS)与 工具变量(IV)模型

以下是关于两阶段最小二乘法&#xff08;2SLS&#xff09;与工具变量&#xff08;IV&#xff09;模型关系的系统解析&#xff0c;结合计量经济学理论与论文上下文进行说明&#xff1a;一、核心关系&#xff1a;2SLS是IV模型的实现方法 1. IV模型&#xff1a;解决内生性的理论框…

熬夜面膜赛道跑出的新物种

在快节奏的现代生活中&#xff0c;熬夜已成为都市人群的常态&#xff0c;深夜11点后的朋友圈总是一片“失眠”哀嚎。随之而来的是“熬夜肌”问题的激增——暗沉、干燥、屏障受损等诉求催生了庞大的熬夜面膜市场。2025年&#xff0c;中国面膜线上规模已达484亿元&#xff0c;其中…

20250813测试开发岗(凉)面

1. 自我介绍2. 你如何理解测开&#xff0c;你认为测开的工作有哪些3. 测试的时候包括哪些部分4. 就功能层面&#xff0c;你认为需要从那些部分考虑&#xff0c;形成一个完整并可执行的trace&#xff08;是这个词吧&#xff09;5. 你了解数据库吗&#xff08;我说只会比较基础的…

面向Python/C#开发者入门Java与Bukkit API

本教程将以"手持发射器箭矢机枪"功能为例&#xff0c;带你掌握Java语言基础和Bukkit API的核心概念&#xff0c;最终实现自主开发插件。 我们将通过剖析一个实际Java代码文件&#xff0c;逐步解析其运作机制&#xff0c;帮助你顺利将现有编程知识迁移到Java和Bukkit…

从100到0.3美元:GPT-5用价格战血洗大模型赛道

————————— 一、从 100 美元到 0.3 美元&#xff1a;史无前例的效率革命 ————————— 互联网女王 Mary Meeker 在《AI 趋势报告 2025》里写下这组数字&#xff1a; • 训练成本 8 年飙升 2400 倍&#xff1b; • 推理成本 2 年暴跌 99.7%。OpenAI 把“暴跌”推到…

第三十二天(文件操作安全)

文件遍历上传下载删除编辑包含等 $_FILES&#xff1a;PHP中一个预定义的超全局变量&#xff0c;用于在上传文件时从客户端接收文件&#xff0c;并将其保存到服务器上。它是一个包含上传文件信息的数组&#xff0c;包括文件名、类型、大小、临时文件名等信息。 $_FILES"表…

系统集成项目管理工程师【第十一章 规划过程组】规划风险应对、规划采购管理篇

系统集成项目管理工程师【第十一章 规划过程组】规划风险应对、规划采购管理篇 一、规划风险应对&#xff1a;为项目穿上"防护衣" 1. 什么是规划风险应对&#xff1f; 规划风险应对是基于风险量化分析结果&#xff0c;制定可选方案、选择应对策略并商定具体行动的过程…

20250813比赛总结

题目T1.volumeT2.storyT3.treeT4.game预计分数6060030实际分数306000T1.volume 确实是暴力&#xff0c;但我是用数组统计每个可能出现的数&#xff0c;于是3AC 3WA 4TLE。拿到全部分应该直接按照题目模拟。 T2.story 暴力dfs&#xff0c;由于忘记优化所以60pts&#xff0c;而且…

适合物流/应急/工业的对讲机,AORO M6 Pro构建高效指挥调度方案

在物流调度、应急救援与工业协同等对通信可靠性要求极高的领域中&#xff0c;专业对讲设备的技术迭代直接关系到任务执行效率与安全保障。AORO M6 Pro对讲机作为新一代融合通信终端&#xff0c;正以多模融合技术与国产化自主创新&#xff0c;为复杂场景下的高效调度提供坚实的技…

类和对象----中

这里写目录标题<font color"#FF00FF">1. 类和对象(中)<font color"#FF00FF">2. 构造函数<font color"#FF00FF">3. 析构函数<font color"#FF00FF">4. 拷⻉构造函数1. 类和对象(中) 类的默认成员函数&#xff1…

CAD 的 C# 开发中,对多段线(封闭多边形)内部的点进行 “一笔连线且不交叉、不出界

本质上是约束条件下的路径规划问题&#xff0c;核心是找到一条连续路径遍历所有点&#xff0c;同时满足&#xff1a; 路径不与自身交叉&#xff1b; 路径全程在多段线&#xff08;多边形&#xff09;内部&#xff1b; 路径连续&#xff08;一笔画&#xff09;。核心思路与算法步…

ZED 2i相机调试

1. 测试 ZED SDK /usr/local/zed/tools/ZED_Diagnostic/usr/local/zed/tools/ZED_Explorer2. 安装SDK How to Install ZED SDK on Linux - Stereolabs 安装命令&#xff1a; sudo apt install zstd./ZED_SDK_Ubuntu20_cuda12.1_tensorrt8.6_v5.0.5.zstd.run

Go语言select并发编程实战指南

一、select作用Go 语言中的 select 语句是处理多通道&#xff08;Channel&#xff09;操作的核心控制结构&#xff0c;专为高效并发通信而设计。通过巧妙运用 select 语句&#xff0c;开发者能够高效实现并发控制、超时处理和非阻塞通信等功能&#xff0c;使其成为 Go 语言并发…

OpenCV常见问题汇总

1、深度拷贝的问题我对整张图像通过裁剪分别进行识别&#xff0c;出现识别结果与期望不同的问题&#xff0c;经过大量排查是OpenCV深度拷贝问题&#xff0c;我原来有问题的写法cv::Mat matCrop matZoom(roi); cv::Mat matCrop1 matCrop(roi1); cv::Mat matCrop2 matCrop(roi2)…

【Unity开发】Unity核心学习(一)

一、2D相关1、图片导入相关设置 &#xff08;1&#xff09;Unity支持的图片格式 支持BMP、TIF、JPG、PNG、TGA、PSD 常用格式具体介绍&#xff1a; JPG&#xff1a;指JPGE格式&#xff0c;属于有损压缩格式&#xff0c;无透明通道 PNG&#xff1a;无损压缩格式&#xff0c;有透…