嵌入式开发板屏幕显示图片(bmp)

devtools/2024/9/20 7:36:41/ 标签: c#, 开发语言

0.framebuffer简介

帧缓冲(framebuffer)是Linux为显示设备提供的一个接口,把显存抽象后的一种设备,他允许上层应用程序在图形模式下直接对显示缓冲区进行读写操作。framebuffer是LCD对应的一中HAL(硬件抽象层),提供抽象的,统一的接口操作,用户不必关心硬件层是怎么实施的。这些都是由Framebuffer设备驱动来完成的。

1.图片

图片

下载图片的大小应该和显示屏大小一致

显示屏大小可以通过代码来查看,参考:什么是framebuffer,怎么应用(一)————如何画点、线、矩形、圆

2.代码

参考:Linux framebuffer显示bmp图片

2.1位图文件头

位图文件头(BITMAPFILEHEADER)是BMP位图文件的一个重要组成部分,主要用于识别文件是否为位图文件,并提供文件大小和位图数据的位置等信息。以下是位图文件头的详细结构和说明:

  1. 结构定义

    • 位图文件头通常占据14个字节,其结构定义如下:
      typedef struct tagBITMAPFILEHEADER {WORD  bfType;       // 2字节,位图文件类型,必须为'BM'(0x4D42)DWORD bfSize;       // 4字节,文件大小(以字节为单位)WORD  bfReserved1;  // 2字节,保留字段,通常为0WORD  bfReserved2;  // 2字节,保留字段,通常为0DWORD bfOffBits;    // 4字节,从文件头到实际位图数据的偏移量(以字节为单位)
      } BITMAPFILEHEADER;
      
  2. 字段解释

    • bfType:该字段用于标识文件类型,对于BMP文件,这个值必须是’BM’(即0x4D42)。这是识别文件是否为位图文件的关键。
    • bfSize:该字段表示整个文件的大小,以字节为单位。这有助于确定文件是否已完整下载或传输。
    • bfReserved1bfReserved2:这两个字段是保留字段,通常设置为0。在某些情况下,这些字段可能被用于特定的用途,但在标准的BMP文件中,它们不被使用。
    • bfOffBits:该字段表示从文件头到实际位图数据的偏移量,以字节为单位。通过这个字段,程序可以快速地定位到位图数据的起始位置。
  3. 作用

    • 位图文件头的主要作用是标识文件类型,确保程序能够正确地解析文件。同时,它还提供了关于文件大小和位图数据位置的信息,这些信息对于读取和解析位图文件至关重要。

在解析BMP文件时,程序首先会读取文件头,并检查bfType字段的值是否为’BM’。如果不是,则该文件不是有效的BMP文件。然后,程序会根据bfSizebfOffBits字段的值来读取和解析文件的其余部分。

2.2具体实现

#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <fcntl.h>#include <string.h>#include <linux/fb.h>#include <sys/mman.h>#include <sys/ioctl.h>#include <arpa/inet.h>#include <errno.h>typedef struct{char cfType[2];long cfSize;long cfReserved;long cfoffBits;}__attribute__((packed)) BITMAPFILEHEADER;typedef struct{char ciSize[4];long ciWidth;long ciHeight;char ciPlanes[2];int ciBitCount;char ciCompress[4];char ciSizeImage[4];char ciXPelsPerMeter[4];char ciYPelsPerMeter[4];char ciClrUsed[4];char ciClrImportant[4];}__attribute__((packed)) BITMAPINFOHEADER;typedef struct{unsigned short blue;unsigned short green;unsigned short red;unsigned short reserved;}__attribute__((packed)) PIXEL;BITMAPFILEHEADER FileHead;BITMAPINFOHEADER InfoHead;static char *fbp = 0;static int xres = 0;static int yres = 0;static int bits_per_pixel = 0;int show_bmp();int show_bmp2();int fbfd = 0;static void fb_update(struct fb_var_screeninfo *vi){vi->yoffset = 1;ioctl(fbfd, FBIOPUT_VSCREENINFO, vi);vi->yoffset = 0;ioctl(fbfd, FBIOPUT_VSCREENINFO, vi);}int width, height;static int cursor_bitmpa_format_convert(char *dst,char *src){int i ,j ;char *psrc = src ;char *pdst = dst;char *p = psrc;int value = 0x00;pdst += (width * height * 4);for(i=0;i<height;i++){p = psrc + (i+1) * width * 3;for(j=0;j<width;j++){pdst -= 4;p -= 3;pdst[0] = p[0];pdst[1] = p[1];pdst[2] = p[2];value = *((int*)pdst);value = pdst[0];if(value == 0x00){pdst[3] = 0x00;}else{pdst[3] = 0xff;}}}return 0;}int show_bmp(char *path){FILE *fp;int rc;int line_x, line_y;long int location = 0, BytesPerLine = 0;char *bmp_buf = NULL;char *bmp_buf_dst = NULL;char * buf = NULL;int flen = 0;int ret = -1;int total_length = 0;printf("into show_bmp function____________________________\n");if(path == NULL){printf("path Error,return");return -1;}printf("path = %s\n", path);fp = fopen( path, "rb" );if(fp == NULL){printf("load > cursor file open failed");return -1;}fseek(fp,0,SEEK_SET);fseek(fp,0,SEEK_END);flen = ftell(fp);printf("File size: %d\n", flen); // Debug: print file sizebmp_buf = (char*)calloc(1,flen - 54);if(bmp_buf == NULL){printf("load > malloc bmp out of memory!");return -1;}fseek(fp,0,SEEK_SET);rc = fread(&FileHead, sizeof(BITMAPFILEHEADER),1, fp);if ( rc != 1){printf("read header error!\n");fclose( fp );return( -2 );}// Debug: print BMP header fieldsprintf("BMP Header:\n");printf("cfType: %c%c\n", FileHead.cfType[0], FileHead.cfType[1]);printf("cfSize: %ld\n", FileHead.cfSize);printf("cfReserved: %ld\n", FileHead.cfReserved);printf("cfoffBits: %ld\n", FileHead.cfoffBits);if (memcmp(FileHead.cfType, "BM", 2) != 0){printf("it's not a BMP file\n");fclose( fp );return( -3 );}rc = fread( (char *)&InfoHead, sizeof(BITMAPINFOHEADER),1, fp );if ( rc != 1){printf("read infoheader error!\n");fclose( fp );return( -4 );}width = InfoHead.ciWidth;height = InfoHead.ciHeight-224;total_length = width * height *3;fseek(fp, FileHead.cfoffBits, SEEK_SET);	buf = bmp_buf;while ((ret = fread(buf,1,total_length,fp)) >= 0) {//printf("ret = %d", ret);if (ret == 0) {if (feof(fp)) {printf("End of file reached.\n");break;}if (ferror(fp)) {perror("Error reading file");break;}usleep(100);continue;}printf("ret = %d\n", ret);buf = ((char*) buf) + ret;total_length = total_length - ret;if(total_length == 0)break;}total_length = width * height * 4;printf("total_length = %d\n", total_length);bmp_buf_dst = (char*)calloc(1,total_length);if(bmp_buf_dst == NULL){printf("load > malloc bmp out of memory!");return -1;}cursor_bitmpa_format_convert(bmp_buf_dst, bmp_buf);memcpy(fbp,bmp_buf_dst,total_length);printf("show logo return 0\n");return 0;}int show_picture(int fd, char *path){struct fb_var_screeninfo vinfo;struct fb_fix_screeninfo finfo;long int screensize = 0;struct fb_bitfield red;struct fb_bitfield green;struct fb_bitfield blue;printf("Enter show_logo\n");retry1:fbfd = fd;if (fbfd == -1){printf("Error opening frame buffer errno=%d (%s)",errno, strerror(errno));goto retry1;}if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo)){printf("Error:reading fixed information.\n");return -1;}if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)){printf("Error: reading variable information.\n");return -1;}printf("R:%d,G:%d,B:%d \n", vinfo.red, vinfo.green, vinfo.blue );printf("%dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel );xres = vinfo.xres;yres = vinfo.yres;bits_per_pixel = vinfo.bits_per_pixel;screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;printf("screensize=%d byte\n",screensize);fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);if ((int)fbp == -1){printf("Error: failed to map framebuffer device to memory.\n");return -1;}printf("sizeof file header=%d\n", sizeof(BITMAPFILEHEADER));show_bmp(path);sleep(2); // 暂停2秒fb_update(&vinfo);munmap(fbp, screensize);printf("Exit show_logo\n");return 0;}int main(int argc, char *argv[]) {if (argc != 2) {printf("Usage: %s <bmp file path>\n", argv[0]);return -1;}int fd = open("/dev/fb0", O_RDWR);if (fd == -1) {perror("Error opening framebuffer device");return -1;}if (show_picture(fd, argv[1]) == -1) {printf("Failed to display picture\n");close(fd);return -1;}close(fd);return 0;}

如果图片大小不一致,例如我使用的图片为:1280x1024
属性

	//这里要对图片的长宽进行校准width = InfoHead.ciWidth;height = InfoHead.ciHeight-224;

3.编译及远程传输

参考本人前文。

4.输出到开发板的效果图

效果图


http://www.ppmy.cn/devtools/54182.html

相关文章

深入探索 Nuxt3 Composables:掌握目录架构与内置API的高效应用

title: 深入探索 Nuxt3 Composables&#xff1a;掌握目录架构与内置API的高效应用 date: 2024/6/23 updated: 2024/6/23 author: cmdragon excerpt: 摘要&#xff1a;“本文深入探讨了Nuxt3 Composables&#xff0c;重点介绍了其目录架构和内置API的高效应用。通过学习本文&…

计算机视觉中,数据增强和扩充数据集规模的区别是什么?

数据增强和扩充数据集样本规模是两个常用于提高模型性能的方法&#xff0c;它们有着不同的目标和实现方式。以下是对它们的详细解释和比较&#xff1a; 数据增强&#xff08;Data Augmentation&#xff09; 定义&#xff1a; 数据增强是指在训练过程中对原始数据进行各种随机…

rust函数指针和闭包异同探索随笔

//rust需要在编译时确定某个类型的值究竟会占据多少内存&#xff0c;而且同一类型的所有值都必须使用相同大小的内存&#xff0c;否则编译无法进行。 //对于DST动态大小类型在编译器期间无法得知其确切大小&#xff0c;所以直接定义此种类型的变量&#xff0c;rust编译无法通过…

算法训练营第六十七天 | 卡码网110 字符串接龙、卡码网105 有向图的完全可达性、卡码网106 岛屿的周长

卡码网110 字符串接龙 这题一开始用的邻接表dfs&#xff0c;不幸超时 #include <iostream> #include <list> #include <string> #include <vector> using namespace std;int minLen 501;bool count(string a, string b) {int num 0;for (int i 0; …

SpringSecurity-重写默认配置

重写UserDetailService组件 1.注入Bean的方式 /*** author: coffee* date: 2024/6/22 21:22* description: 重写springsecurity默认组件&#xff1a;注入Bean的方式*/Configuration public class ProjectConfig {/*** 重写userDetailsService组件*/Beanpublic UserDetailsSer…

八爪鱼现金流-027,以后别再做软件开发了,累了,要有自己的作品

别做软件开发了&#xff0c;太恶心了。 裁员好几波人&#xff0c;他们的项目就给到剩下的人身上了。 然后工作量翻倍&#xff0c;主要是遗留的项目也一堆bug.人员流动性太大。 项目的产品也换人了。开发也换了。没有人熟悉这个项目了。 现状就是&#xff0c;先看页面&#xff…

【TensorFlow深度学习】异常检测与诊断:TensorFlow在故障预测中的应用

异常检测与诊断:TensorFlow在故障预测中的应用 异常检测与诊断:TensorFlow在故障预测中的应用1. 引言2. 数据准备与预处理3. 构建异常检测模型4. 异常分数计算与阈值设定5. 结果解释与可视化6. 模型优化与实时监控结语异常检测与诊断:TensorFlow在故障预测中的应用 在工业4…

Python中的多线程实现与GIL(全局解释器锁)的影响

Python中的多线程实现与GIL&#xff08;全局解释器锁&#xff09;的影响 在Python编程中&#xff0c;多线程是一种常见的并发编程技术&#xff0c;它允许程序同时执行多个任务。然而&#xff0c;Python的全局解释器锁&#xff08;GIL&#xff09;对多线程的性能和并发性有着显…

[FreeRTOS 基础知识] 互斥访问与回环队列 概念

文章目录 为什么需要互斥访问&#xff1f;使用队列实现互斥访问休眠和唤醒机制环形缓冲区 为什么需要互斥访问&#xff1f; 在裸机中&#xff0c;假设有两个函数&#xff08;func_A, func_B&#xff09;都要修改a的值&#xff08;a&#xff09;&#xff0c;那么将a定义为全局变…

前端小白指南:前端生成唯一设备标识的那些事儿

最近&#xff0c;我在使用javascript开发一个基于Chrome的插件&#xff0c;遇到了一个有意思的需求。插件需要生成一个授权码&#xff08;code&#xff09;&#xff0c;但为了确保安全性&#xff0c;这个code必须与设备绑定&#xff0c;防止被不同的设备使用&#xff0c;限制一…

L57---112.路径总和(广搜)---Java版

1.题目描述 给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径&#xff0c;这条路径上所有节点值相加等于目标和 targetSum 。如果存在&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。叶子节点 是指…

playwright vscode 插件源码解析

Playwright vscode插件主要功能 Playwright是微软开发的一款主要用于UI自动化测试的工具&#xff0c;在vscode中上安装playwright vscode插件&#xff0c;可以运行&#xff0c;录制UI自动化测试。 playwright vscode插件主要包括两块功能&#xff0c;功能一是在Test Explorer中…

Elasticsearch RestclientApi基础用法

Elasticsearch RestclientApi基础用法 索引 初始化 添加依赖 <dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId> </dependency>创建链接 package com.hmall.i…

LeetCode 算法: 合并 K 个升序链表 c++

原题链接&#x1f517;&#xff1a;合并 K 个升序链表 难度&#xff1a;困难⭐️⭐️⭐️ 题目 给你一个链表数组&#xff0c;每个链表都已经按升序排列。 请你将所有链表合并到一个升序链表中&#xff0c;返回合并后的链表。 示例 1&#xff1a; 输入&#xff1a;lists […

Springboot项目jar加密

部署的程序进行加密&#xff0c;防止第三方非法拷贝走项目进行二次开发或部署。我们知道java代码编译后生成的以.class结尾的字节码文件或者.jar/.war结尾的可执行文件都是可以反编译生成.java文件的&#xff0c;虽然反编译后生成的.java文件和原本的.java文件有些微差别&#…

【html】用html5+css3+JavaScript制作一个计数器

目录 简介&#xff1a; 效果图&#xff1a; 源码&#xff1a; html: CSS: JS: 源码解析&#xff1a; 简介&#xff1a; 在日常生活当中很多事情都需要用到计数器特别是在体育运动当中&#xff0c;可以我们那么我们可不可以通过网页来制作一个计数器呢答案是肯定的我们需要利…

ActiViz中的交互类Widget

文章目录 简介1. vtkBoxWidget2. vtkImplicitPlaneWidget3. vtkSphereWidget4. vtkLineWidget5. vtkHandleWidget6. 其他常用Widget7. 组合使用Widget8. 自定义Widget9. 最佳实践和性能优化10. 结论简介 ActiViz提供了丰富的交互类Widget,使用户能够与三维数据进行更直观的交…

PHP框架之CodeIgniter框架

CodeIgniter框架详细说明 CodeIgniter是一个简单而强大的PHP框架&#xff0c;专为快速开发Web应用程序而设计。它遵循MVC&#xff08;模型-视图-控制器&#xff09;设计模式&#xff0c;为开发者提供了丰富的功能和灵活性&#xff0c;同时保持代码的轻量级和易于管理。CodeIgn…

Mac电脑如何卸载Adobe Creative Cloud 苹果电脑adobe软件卸载不干净怎么办

Adobe Creative Cloud是许多创意工作者和设计师常用的软件套件&#xff0c;包括多个强大的应用程序。然而&#xff0c;有时用户可能需要卸载这些软件以释放磁盘空间或其他原因。下面我们来看看Mac电脑如何卸载Adobe Creative Cloud&#xff0c;苹果电脑adobe软件卸载不干净怎么…

细胞核的分割与分类模型·HoVer-Net|动手实操

小罗碎碎念 上一期推文已经介绍了hover net的背景和代码仓库情况&#xff0c;这一期则是根据作者提供的示例代码进行分析&#xff0c;详细你看完这一期推文&#xff0c;应该就能大致掌握这些套路了。如果觉得意犹未尽&#xff0c;那就等待下一期吧&#xff0c;哈哈。 一、编程…