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

Linux应用软件编程---UI技术(frambuffer、内存映射、函数封装、打印各类图形)

        UI技术:User interface 技术,称为人机交互界面。

一、RGB888

1、概念

        RGB888 是一种常见的RGB色彩编码格式,用于在数字设备(如显示屏、摄像头、图像传感器等)中表示和存储颜色。

        每个颜色通道(R红、G绿、B蓝)用二进制表示,能够表示 256*256*256 种颜色,适用于对色彩要求高的场景。

        RGB888 位数分配:

R(红):8位(取值范围0~255)
G(绿):8位(取值范围0~255)
B(蓝):8位(取值范围0~255)

2、对比

        RGB565 :对 RGB 通道进行位数压缩,色彩精度对于 RGB888 来说相对较低,能表示 32*64*32 种颜色,色彩过渡可能出现轻微色块,存在颜色损失(损失低位,保留高位)。

        位数分配:

R(红):5位(取值范围0~31)
G(绿):6位(取值范围0~63)
B(蓝):5位(取值范围0~31)

二、framebuffer

        framebuffer是一种帧缓冲、帧缓存技术,由 Linux 内核专门为图形显示提供的一套应用程序接口。

        关于上图,需要了解的是:

        显示屏的坐标系:

三、内存映射

        内存映射是一种设备直接映射到进程地址空间的技术,使得程序可以像访问内存一样读写文件/设备,实现共用空间,在将用户空间输入数据映射至现存空间。

1、典型接口

        1)mmap
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)
        2)munmap 解除映射

        int munmap(void *addr, size_t length);

        3)ioctl

        #include <sys/ioctl.h>

       int ioctl(int fd, unsigned long request, ...);

        fd:打开的设备文件(文件描述符)

2、操作步骤

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

3、函数封装

        1)int init_fb(char *devname) 初始化函数的封装

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

 //1. 打开显示设备(/dev/fb0)fb = open(devname, O_RDWR);if (-1 == fb){perror("open fb error");return -1;}

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

  //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)建立显存空间和用户空间的内存映射

 //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;
}
        2)void draw_point(int x, int y, unsigned int col) 颜色映射函数的封装
//4. 向映射的用户空间写入RGB颜色值
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.yres_virtual*y+x) = col;}
}
        3)int uninit_fb() 解除映射函数的封装

        (5)解除映射关系
(6)关闭显示设备

int uninit_fb()
{//5. 解除映射关系//6. 关闭显示设备size_t len = vinfo.xres_virtual * vinfo.yres_virtual * vinfo.bits_per_pixel/8;munmap(pmem, len);close(fb);}
        4)横线 (x) 绘制函数封装
/*横线*/
void draw_xline(int x, int y, int xmax, unsigned int col)
{int i = x;for(i; i <= xmax; i++){draw_point(i, y, col);}
}
        5)竖线 (y) 绘制函数封装
/*竖线*/
void draw_yline(int x, int y, int ymax,unsigned int col)
{int i = y;for(i; i <= ymax; i++){draw_point(x, i, col);}
}
        6)矩形绘制函数封装
/*矩形*/
void draw_rest(int x, int y, int xmax, int ymax, unsigned int col)
{draw_xline(x, y, xmax, col);draw_xline(x, ymax, xmax, col);draw_yline(x, y, ymax, col);draw_yline(xmax, y, ymax, col);}
        7)面绘制函数封装
/*面*/
void draw_area(int x, int y,int xmax, int ymax, unsigned int col)
{int i, j;for(i = x; i < xmax; i++){for(j = y; j < ymax; j++){draw_point(i, j, col);}}
}
        8)圆形绘制函数封装
/*圆形*/
void draw_Q(int x, int y, int r, unsigned int col)
{int i, a, b;for(i = 0; i < 360; i++){a = x + r * cos(i / 180.0 * PI);b = y + r * sin(i / 180.0 * PI);draw_point(a, b, col);}
}
        9)bmp图形绘制函数封装

        (1)获取bmp图片信息

/*获取信息*/
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;
}

        (2)bmp图片绘制

/*bmp图片绘制*/
void draw_bmp(int x, int y, char *bmpname)
{Bmp_file_head_t headinfo;Bmp_info_t bmpinfo;get_bmp_head_info("./7.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++){  //RGB在内u才能中的读取顺序为 B G Rb = *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);
}
        10)文字绘制函数封装

        文字绘制需将文字的字模点阵数据写入一个结构体中,例如:普

unsigned char pu[24/8*21] = {
/*--  鏂囧瓧:  鏅? --*/
/*--  浠垮畫16;  姝ゅ瓧浣撲笅瀵瑰簲鐨勭偣闃典负锛氬x楂?22x21   --*/
/*--  瀹藉害涓嶆槸8鐨勫€嶆暟锛岀幇璋冩暣涓猴細瀹藉害x楂樺害=24x21  --*/
0x00,0x04,0x00,0x03,0x0E,0x00,0x01,0x8E,0x00,0x01,0xCC,0x00,0x0F,0xFF,0xC0,0x1F,
0xFB,0x00,0x0C,0xDB,0x80,0x06,0xDB,0x00,0x07,0xDE,0x00,0x03,0xDF,0xE0,0x7F,0xFF,
0xE0,0x3C,0x02,0x00,0x07,0xFF,0x00,0x03,0xF7,0x00,0x03,0x16,0x00,0x03,0xFE,0x00,
0x03,0x06,0x00,0x03,0xFE,0x00,0x07,0xFE,0x00,0x03,0x06,0x00,0x00,0x00,0x00
};
/*文字绘制*/
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);}tmp = tmp << 1;}}}
}

4、声明部分(头文件)

#ifndef __FRAMEBUFFER_H__
#define __FRAMEBUFFER_H__#define RGB_FMT_888 32
#define RGB_FMT_565 16
#define PI 3.1415926
#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_xline(int x, int y, int xmax, unsigned int col);
extern void draw_yline(int x, int y, int ymax,unsigned int col);
extern void draw_rest(int x, int y, int xmax, int ymax, unsigned int col);
extern void draw_area(int x, int y,int xmax, int ymax, unsigned int col);
extern void draw_Q(int x, int y, int r, unsigned int col);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

5、主函数运行格式

#include <stdio.h>
#include "framebuffer.h"int main(void)
{ int ret = init_fb("/dev/fb0");if (ret < 0){return -1;}draw_xline(100, 200, 400, 0xFF0000);draw_yline(100, 100, 600, 0x00FF0000);draw_rest(100, 200, 400, 400, 0x00FF0000);draw_area(100,  100, 600, 400, 0x00FF0000);draw_Q(300, 400, 50, 0x00FF0000);//图片、文字绘制draw_bmp(0, 0, "./7.bmp");draw_word(100, 200, s, 6, 48, 0x00FF0000);uninit_fb();return 0;
}

【END】

http://www.dtcms.com/a/328969.html

相关文章:

  • 数据结构初阶(12)排序算法—插入排序(插入、希尔)(动图演示)
  • 【Datawhale AI 夏令营】金融文档分析检索增强生成系统的架构演变与方法论进展
  • CAN仲裁机制的原理
  • Android中获取状态栏高度
  • 用好Spring AI向量存储,全面释放AI潜能:打造高效RAG应用的加速引擎
  • Jetson NX Python环境搭建:使用APT轻松安装NumPy, scikit-learn, OpenCV
  • 【OSPP 开源之夏】Good First issue 第一步—— openEuler Embedded 计划
  • 机器学习⑤【线性回归(Linear Regression】
  • 记录RK3588的docker中启动rviz2报错
  • C++11新特性详解:从列表初始化到线程库
  • Linux系统编程Day13 -- 程序地址空间(进阶)
  • uniapp组件的开关选择器可以这个携带多参数
  • CVPR2025敲门砖丨机器人结合多模态+时空Transformer直冲高分,让你的论文不再灌水
  • docker network 与host的区别
  • Uni-app + Vue3+editor富文本编辑器完整实现指南
  • 学习STM32 脉冲计数实验
  • MySQL相关概念和易错知识点(6)(视图、用户管理)
  • Java 大视界 -- 基于 Java 的大数据可视化在能源互联网全景展示与能源调度决策支持中的应用
  • 深度学习与遥感入门(七)|CNN vs CNN+形态学属性(MP):特征工程到底值不值?
  • 一键自动化:Kickstart无人值守安装指南
  • 【unitrix数间混合计算】2.20 比较计算(cmp.rs)
  • Spring Boot (v3.2.12) + application.yml + jasypt 数据源加密连接设置实例
  • 25个自动化办公脚本合集(覆盖人工智能、数据处理、文档管理、图片处理、文件操作等)
  • 【电气】NPN与PNP
  • [C语言]第二章-从Hello World到头文件
  • 四分位数与箱线图
  • Redis持久化机制详解:RDB与AOF的全面对比与实践指南
  • 动静态库
  • FPGA的PS基础1
  • 【FPGA】初始Verilog HDL