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】