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

framebuffer

文件io:

b 文件io

c 文件io

d 目录io

- 标准io,文件io

l 具体看连接箱

s 文件io

p 文件io

UI技术:usr interface

framebuffer:帧缓冲,帧缓存技术

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

常见像素格式:

RGB888:红、绿、蓝各占 8 位,共 24 位(3 字节),通常扩展为 32 位(4 字节)以便对齐内存访问。

RGB565:红 5 位、绿 6 位、蓝 5 位,共 16 位(2 字节)。

颜色值范围:每个颜色分量为 0–255(8 位无符号整数),全满为白色,全零为黑色。显卡负责将显存中的数字信号转换为模拟信号驱动显示屏。显存中数据为线性排列,需映射到二维屏幕坐标。坐标 (x, y) 对应的显存偏移量为:offset = y * width + x

显存位于内核空间,用户程序无法直接访问,需通过 内存映射(mmap) 将其映射到用户空间。

内存映射后,用户可通过指针访问映射区域,写入像素数据即等效于写入显存。

指针类型应为 unsigned int*(4 字节),以匹配 RGB888 扩展后的像素大小。指针每加 1,偏移 4 字节,对应一个像素点。

示例:在 800×600 分辨率下点亮中心点 (400, 300) 为红色,应向 p_memory + 300 * 800 + 400 写入 0x00FF0000

实现步骤总结:

  1. 打开显示设备:操作 /dev/fb0 文件,代表帧缓冲设备。
  2. 获取设备参数:读取分辨率、像素格式等信息,以计算显存大小。
  3. 建立内存映射:使用 mmap 将显存映射到用户空间,获取可操作的内存首地址。
  4. 写入像素数据:通过映射后的指针写入 RGB 颜色值,实现图形绘制。
  5. 解除映射关系
  6. 关闭显示设备
#include <linux/fb.h>
struct fb_var_screeninfo vinfo;
int ret = ioctl(fb, FBIOGET_VSCREENINFO, &vinfo);
if (ret < 0) {printf("ioctl error\n");return -1;
}

使用 ioctl() 与用户层与内核交互,获取屏幕信息。

请求命令为 FBIOGET_VSCREENINFO,对应宏定义在 linux/fb.h 头文件中。

定义结构体 struct fb_var_screeninfo vinfo 存储参数。

建立内存映射
  • 使用 mmap() 将显存映射到用户空间。
  • 映射大小计算公式:xres * yres * (bits_per_pixel / 8)
  • 参数设置:
    • addr: NULL(由系统自动分配)
    • length: 计算得到的显存大小,映射的空间大小
    • prot: PROT_READ | PROT_WRITE
    • flags: MAP_SHARED(共享)
    • fd: fb(设备文件描述符)
    • offset: 0(从起始地址映射)偏移量

munmap(p_memory, vinfo.xres * vinfo.yres * (vinfo.bits_per_pixel / 8));
close(fb);

解除映射,关闭设备。

错误处理机制
单纯使用 printf 打印错误信息缺乏具体原因,不利于调试。
引入 perror() 函数:可同时输出自定义错误信息和系统提供的错误原因(如 "No such file or directory")。
系统在函数调用失败时会设置全局变量 errno,其值对应特定错误类型。
可通过 strerror(errno) 将 errno 数值转换为可读的错误字符串。
推荐使用 perror() 替代 printf 输出错误信息,因其自动附加换行且包含系统错误说明。

该函数是在某坐标点上一个点。

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_heng(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(x = 0; x < vinfo.xres_virtual; ++x){*(p+vinfo.xres_virtual*y+x) = col;}}else if(vinfo.bits_per_pixel == RGB_FMT_565){unsigned short *p = pmem;for(x = 0; x < vinfo.xres_virtual; ++x){*(p+vinfo.xres_virtual*y+x) = col;}}
}
void draw_shu(int x, int y, unsigned int col) { if (x < 0 || x >= vinfo.xres || y < 0 || y >= vinfo.yres) {return;}if (vinfo.bits_per_pixel == RGB_FMT_888) {unsigned int *p = (unsigned int *)pmem; for (; y < vinfo.yres_virtual; y++) { *(p + y * vinfo.xres_virtual + x) = col; }} else if (vinfo.bits_per_pixel == RGB_FMT_565) {unsigned short *p = (unsigned short *)pmem;for (; y < vinfo.yres_virtual; y++) { *(p + y * vinfo.xres_virtual + x) = col; }}
}
void draw_juxing(int x, int y ,unsigned int col)
{if(x >= vinfo.xres || y >= vinfo.yres){return  ;}if(vinfo.bits_per_pixel == RGB_FMT_888){for(; y < vinfo.yres_virtual; ++y){draw_heng(0, y ,0x00FF0000);}}
}

图像显示技术实现摘要

一、图像格式基础

  • 常见网络图片格式为JPG或PNG,属于压缩格式,体积小但可能存在图像损失(有损压缩)。
  • BMP(位图)为未压缩的无损图像格式,数据完整,便于直接读取像素值。
  • 由于压缩图像需解压才能获取RGB值,因此在嵌入式设备贴图时通常使用BMP格式。

二、BMP文件结构

  • BMP文件前14字节为文件头信息,后40字节为图像信息头,共54字节头部数据。
  • 第55字节起为实际像素颜色值(RGB),但存储顺序为BGR(蓝绿红),而非RGB。
  • 显示前需跳过前54字节头部信息,读取后续像素数据。

三、图像处理流程

  1. 图像准备

    • 从网络下载图片并保存为JPG格式。
    • 使用系统“画图”工具打开,调整分辨率至目标显示屏大小(如800×600)。
    • 另存为BMP格式(不可仅修改后缀名,必须通过工具转换以确保数据格式正确)。
  2. 文件读取与头部解析

    • 使用open()函数以只读方式打开BMP文件。
    • 读取前54字节头部信息,获取图像分辨率(biWidth, biHeight)和位深度(如24位)。
    • 关闭文件后重新打开,用于读取像素数据。
  3. 像素数据读取

    • 使用lseek()将文件指针偏移54字节,跳过头部。
    • 计算所需内存空间:width × height × 3(24位 = 3字节/像素)。
    • 在堆上分配内存,使用read()一次性读取所有BGR数据。
  4. 颜色值转换与绘制

    • 定义指针遍历BGR数据,依次读取B、G、R三个字节。

    • 根据目标显示格式进行颜色拼接:

      RGB888格式

      • R左移16位,G左移8位,B不移。
      • 按位或运算合成32位颜色值:color = (R << 16) | (G << 8) | B

      RGB565格式

      • 存在颜色损失,需压缩为2字节。
      • R保留高5位(右移3位),G保留高6位(右移2位),B保留高5位(右移3位)。
      • 分别左移至对应位置后按位或合成:
        color = ((R >> 3) << 11) | ((G >> 2) << 5) | (B >> 3)
  5. 图像绘制逻辑

    • 使用双层循环遍历图像行列(i为列,j为行)。
    • 绘制坐标为 (x + i, y + j),其中(x,y)为起始位置。
    • 调用draw_point()在对应位置绘制颜色。
  6. 图像倒置问题处理

    • BMP图像数据按“从下到上”方式存储,即第一行数据对应图像最底行。
    • 解决方案:将行索引倒序处理,即j = height - 1 - current_row
    • 实现方式:循环中j从height - 1递减至0,确保像素正确映射。

四、验证与调试

  • 编译运行后发现fopen失败,原因为文件路径中使用了错误的文件名(如3.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;
}
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);
}

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

相关文章:

  • 深入理解Java Set集合特性
  • windows下以all-in-one模式快速启动jaeger
  • Linux学习-UI技术
  • ROS2实用工具
  • Spring AI 的特性 及其 最佳实践
  • CompletableFuture介绍及使用方式
  • 天猫商品评论API:获取商品热门评价与最新评价
  • Jmeter TPS与QPS
  • Ant Design 的 `Image` 组件,通过 `preview.src` 加载本地图片文件
  • Dockerhub 代理设置
  • 破解测试数据困境:5招兼顾安全与真实性
  • Nature Communications 西湖大学姜汉卿教授:弹电磁驱动新范式--赋能昆虫级软体机器人的肌肉仿生策略
  • HTML第三次作业
  • Redis ubuntu下载Redis的C++客户端
  • Ubuntu 20.04 虚拟机安装完整教程:从 VMware 到 VMware Tools
  • 如何在 Ubuntu 24.04 LTS Noble Linux 上安装 FileZilla Server
  • Python【算法中心 03】Docker部署Django搭建的Python应用流程实例(Docker离线安装配置+Django项目Docker部署)
  • java中list的api详细使用
  • MySQL宝典
  • 【Golang】 Context.WithCancel 全面解析与实战指南
  • 使用内联汇编获取在线OJ平台CPU的信息
  • 玩转Docker | 使用Docker部署WordPress网站服务
  • 基本计算器 II
  • 回归分析预测原神深渊血量
  • 【金仓数据库产品体验官】_从实践看金仓数据库与 MySQL 的兼容性
  • Windows系统设置内外网同时访问(小白友好版)
  • Docker部署 Neo4j 及集成 APOC 插件:安装与配置完整指南(docker-compose)
  • 【Android】RecyclerView多布局展示案例
  • Kubernetes(K8S)中,kubectl describe node与kubectl top pod命令显示POD资源的核心区别
  • C语言:队列的实现和剖析