从零开始用C语言实现图片解码播放器(有源码)

2023-11-18

1、项目描述

1.1、项目硬件平台介绍

(1)硬件平台:九鼎公司的X210开发板,S5PV210(Cortex-A8内核);
(2)软件平台:linux2.6.35.7内核,直接基于linux API操作

1.2、项目功能介绍

(1)调用编译好的可执行程序时传入图片的存放路径,程序会自动将路径里的图片显示在屏幕上;
(2)程序会自动检索图片路径下包括子目录在内的所有图片文件;
(3)支持的文件格式包括BMP(8bit、16bit、24bit、32bit)、JPG、PNG;
(4)支持触摸屏翻页功能,点击左侧屏幕则向前翻页,点击右侧屏幕可向后翻页,支持循环翻页;

1.3、项目涉及到的技术

(1)C语言和linux基础操作;
(2)通用Makefile管理工程的相关知识;
(3)应用层操作屏幕的代码分析;
(4)bmp、jpg、png格式解码库的移植;
(5)应用层操作触摸屏的代码分析;
(6)linux中递归遍历文件夹内容的操作;
(7)动态库的编译和移植;
(8)实际项目中目录结构的分析;

2、项目代码目录结构介绍

.
├── bin			——存放生成的可执行程序
├── build		——Makefile编译脚本
├── doc			——项目说明文档
├── image		——存放要播放的图片
│   ├── bmp
│   ├── jpg
│   └── png	
├── include		——相关头文件
│   ├── common	——公共的配置头文件
│   ├── decode	——图片解码相关的头文件
│   │   ├── bmp
│   │   ├── jpg
│   │   ├── png
│   │   │   └── libpng16
│   │   └── zlib
│   ├── fb				——屏幕显示相关头文件
│   ├── imageManager	——图片管理头文件
│   └── touchScreen		——触摸屏管理头文件
├── lib					——依赖的动态库
└── src					——源码目录
    ├── decode			——图片解码相关源码
    ├── fb				——屏幕显示相关源码
    ├── imageManager	——图片管理相关源码
    └── touchScreen		——触摸屏相关源码

参考博客:《实际工作开发中C语言工程的目录结构分析》

3、Makefile介绍

项目管理使用的通用Makefile模板,具体参考博客:《项目通用Makefile的编写(包含Makefile.build文件分析)》

4、屏幕显示模块

4.1、屏幕驱动的移植

《嵌入式开发(S5PV210)——LCD显示器》
《Linux 帧缓冲子系统详解:LCD介绍、framebuffer驱动框架、LCD驱动源码分析》
《LCD驱动源码分析(s3cfb.c)》

4.2、应用层操作屏幕的代码

//表示一个屏幕设备
typedef struct
{
	unsigned int *pfb;		  	// pfb指向framebuffer内存地址首地址
	int fp;					  	// 打开设备节点得到的文件描述符
	int width;					//屏幕的实际宽
	int height;					//屏幕的实际高
	int virWidth;				//屏幕的虚拟宽
	int virHeight;				//屏幕的虚拟高
	int	bpp;					//每个像素占用的位数
}fbHandle;

// 结构体用来封装一个图片的各种信息
typedef struct pic_info
{
	char *pathname;			// 图片在文件系统中的路径名+文件名
	unsigned int width;		// 图片分辨率之宽
	unsigned int height;	// 图片分辨率之高
	unsigned int bpp;		// 图片bpp
	char *pData;			// 指向图片有效数据存储的buf数据
}pic_info;

//传入屏幕的设备节点路径,返回屏幕的设备信息
fbHandle *fb_open(char* devPath)
{
	int ret = -1;
	fbHandle *fbDev = NULL;
	struct fb_fix_screeninfo finfo;
	struct fb_var_screeninfo vinfo;

	fbDev = malloc(sizeof(fbHandle));
	memset(fbDev, 0, sizeof(fbHandle));

	// 第1步:打开设备
	fbDev->fp = -1;
	fbDev->fp = open(devPath, O_RDWR);
	if (fbDev->fp < 0)
	{
		perror("open error");
		goto fail;
	}
	 
	debug("open %s success.\n", devPath);

	// 第2步:获取设备的硬件信息
	ret = ioctl(fbDev->fp, FBIOGET_FSCREENINFO, &finfo);
	if (ret < 0)
	{
		perror("ioctl");
		goto fail;
	}
	debug("smem_start = 0x%lx, smem_len = %u.\n", finfo.smem_start, finfo.smem_len);
	 
	ret = ioctl(fbDev->fp, FBIOGET_VSCREENINFO, &vinfo);
	if (ret < 0)
	{
		perror("ioctl");
		goto fail;
	}
	 
	debug("xres = %u, yres = %u.\n", vinfo.xres, vinfo.yres);
	debug("xres_virtual = %u, yres_virtual = %u.\n", vinfo.xres_virtual, vinfo.yres_virtual);
	debug("bpp = %u.\n", vinfo.bits_per_pixel);


	fbDev->width = vinfo.xres;
	fbDev->height = vinfo.yres;
	fbDev->virWidth = vinfo.xres_virtual;
	fbDev->virHeight = vinfo.yres_virtual;
	fbDev->bpp = vinfo.bits_per_pixel;
	 
	// 第3步:进行mmap
	unsigned long len = vinfo.xres_virtual * vinfo.yres_virtual * vinfo.bits_per_pixel / 8;
	debug("len = %ld\n", len);
	fbDev->pfb = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, fbDev->fp, 0);
	if (NULL == fbDev->pfb)
	{
		perror("mmap error");
		goto fail;
	}
	 
	debug("pfb = %p.\n", fbDev->pfb);

	return fbDev;

fail:
	if(fbDev->fp >= 0)
	{
		close(fbDev->fp);
	}
	
	free(fbDev);
	return NULL;
}

//往屏幕显示图片
void fb_draw_rgb(fbHandle *fbDev, const struct pic_info *pPic)
{
	const char *pData = (const char *)pPic->pData;		// 指针指向图像数组
	unsigned int cnt = 0, a = 0;
	unsigned int x, y;

	a = 0;
	for (y = 0; y < pPic->height; y++)
	{
		for (x=0; x<pPic->width; x++)
		{ 
			//cnt表示当前像素点的编号
			cnt = fbDev->width * y + x; 
			// 当前像素点的数据
			*(fbDev->pfb + cnt) = ((pData[a+2]<<0) | (pData[a+1]<<8)| (pData[a+0]<<16)); 
			a += 3;
		}
	}
}

参考博客:《应用程序操作LCD源码分析》

5、图片解码模块

(1)bmp图片解码函数编写,参考博客:《C语言实现BMP格式转RGB格式、YUV格式》《C语言实现RGB888转BMP格式图片功能》
(2)jpg解码库移植,参考博客:《jpg解码库移植过程详解》
(2)png解码库移植,参考博客:《png格式解码库移植过程详解》

6、图片管理模块

(1)调用linux系统的文件夹操作的API,比如opendir、 readdir、lstat等函数去遍历文件夹下的所有文件;
(2)判断读取到的文件,如果是bmp、jpg、png图片则添加到数组中管理起来,后续在播放图片时会用到;

7、触摸屏模块

(1)通过操作触摸屏的设备节点来读取坐标信息,通过判断坐标来决定是向前翻页还是向后翻页;
(2)《嵌入式开发(S5PV210)——ADC和触摸屏》《gslx680触摸屏驱动源码码分析(gslX680.c)》《linux输入子系统详解——看这一篇就够了》

8、项目代码移植

8.1、硬件平台要求

(1)开发板必须有显示屏和触摸屏,并且显示屏和触摸屏的驱动移植正确,可以正常功能;
(2)在移植代码前,先通过设备节点,确认显示屏和触摸屏工作正常;

8.2、代码修改

// 屏幕的设备节点
#define FBDEVICE	"/dev/fb0"	

# 支持的图片最大的分辨率
#define PICTURE_BUFFER_MAX_SIZE (1920 * 1080 * 3 )

// 最多支持的图片数目
#define MAX_IMAGE_CNT			100

// 触摸屏设备的设备名
#define DEVICE_TOUCHSCREEN		"/dev/input/event2"

// 定义触摸翻页区域的宽度
#define TOUCH_WIDTH				200				

(1)修改主Makefile中的交叉编译工具链为自己平台的(CROSS_COMPILE);
(2)上面的配置都在config.h文件中,需要根据自己开发板的情况去修改,特别是屏幕和触摸屏的设备节点名称必须正确;

8.3、源码获取

《图片解码播放器源码下载》

9、参考资料

《朱友鹏——核心课程》

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从零开始用C语言实现图片解码播放器(有源码) 的相关文章

  • 强制卸载 NFS 安装目录 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 Locked 这个问题及其答案是locked help locked posts因为这个问题是题外话 但却具有历史意义 目前不接受新的答案
  • 跟踪 Linux 程序中活跃使用的内存

    我想跟踪各种程序在特定状态下接触了多少内存 例如 假设我有一个图形程序 最小化时 它可能会使用更少的内存 因为它不会重新绘制窗口 这需要读取图像和字体并执行大量库函数 这些对象仍然可以在内存中访问 但实际上并没有被使用 类似的工具top它们
  • 仅打印“docker-container ls -la”输出中的“Names”列

    发出时docker container ls la命令 输出如下所示 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a67f0c2b1769 busybox tail f dev
  • 应用程序无缘无故地被杀死。怀疑 BSS 高。如何调试呢?

    我已经在CentOs6 6中成功运行我的应用程序 最近 硬件 主板和内存 更新了 我的应用程序现在毫无理由地被杀死 root localhost PktBlaster PktBlaster Killed 文件和 ldd 输出 root lo
  • nginx 上的多个网站和可用网站

    通过 nginx 的基本安装 您的sites available文件夹只有一个文件 default 怎么样sites available文件夹的工作原理以及如何使用它来托管多个 单独的 网站 只是为了添加另一种方法 您可以为您托管的每个虚拟
  • Linux TUN/TAP:无法从 TAP 设备读回数据

    问题是关于如何正确配置想要使用 Tun Tap 模块的 Linux 主机 My Goal 利用现有的路由软件 以下为APP1和APP2 但拦截并修改其发送和接收的所有消息 由Mediator完成 我的场景 Ubuntu 10 04 Mach
  • gdb查找行号的内存地址

    假设我已将 gdb 附加到一个进程 并且在其内存布局中有一个文件和行号 我想要其内存地址 如何获取文件x中第n行的内存地址 这是在 Linux x86 上 gdb info line test c 56 Line 56 of test c
  • 如何查明CONFIG_FANOTIFY_ACCESS_PERMISSIONS是否启用?

    我想利用fanotify 7 http man7 org linux man pages man7 fanotify 7 html我遇到的问题是在某些内核上CONFIG FANOTIFY ACCESS PERMISSIONS不起作用 虽然C
  • 在哪里可以找到并安装 pygame 的依赖项?

    我对 Linux 比较陌生 正在尝试安装 python 的 pygame 开发环境 当我运行 setup py 时 它说我需要安装以下依赖项 我找到并安装了其中之一 SDL 然而 其他人则更加难以捉摸 Hunting dependencie
  • 使用 sed 更新 xml 属性(Windows + cygwin 和 Linux)?

    我需要使用 sed 命令对 xml 文件进行更新 但我在这方面遇到了麻烦 它需要在 Windows 使用 cygwin 和 Linux 上运行 XML 具有以下元素
  • 域套接字“sendto”遇到“errno 111,连接被拒绝”

    我正在使用域套接字从另一个进程获取值 就像 A 从 B 获取值一样 它可以运行几个月 但最近 A 向 B 发送消息时偶尔会失败 出现 errno 111 连接被拒绝 我检查了B域套接字绑定文件 它是存在的 我也在另一台机器上做了一些测试 效
  • 如何使用GDB修改内存内容?

    我知道我们可以使用几个命令来访问和读取内存 例如 print p x 但是如何更改任何特定位置的内存内容 在 GDB 中调试时 最简单的是设置程序变量 参见GDB 分配 http sourceware org gdb current onl
  • vector 超出范围后不清除内存

    我遇到了以下问题 我不确定我是否错了或者它是一个非常奇怪的错误 我填充了一个巨大的字符串数组 并希望在某个点将其清除 这是一个最小的例子 include
  • arm64和armhf有什么区别?

    Raspberry Pi Type 3 具有 64 位 CPU 但其架构不是arm64 but armhf 有什么区别arm64 and armhf armhf代表 arm hard float 是给定的名称Debian 端口 https
  • 两种情况或 if 哪个更快? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我必须制作一个 非常 轻的脚本 它将接受用户的选项并调用脚本中的函数来执行一些任务 现在我可以使用 IF 和 CASE 选项 但我想知道两
  • CentOS:无法安装 Chromium 浏览器

    我正在尝试在 centOS 6 i 中安装 chromium 以 root 用户身份运行以下命令 cd etc yum repos d wget http repos fedorapeople org repos spot chromium
  • 如何在shell中输出返回码?

    我正在尝试通过调用自定义 shell 脚本sh bin sh c myscript sh gt log txt 2 gt 1 echo 该命令的输出是创建的后台进程的 PID 我想指导 bin sh保存返回码myscript sh到某个文件
  • 使用 sh 运行 bash 脚本

    我有 bash 脚本 它需要 bash 另一个人尝试运行它 sh script name sh 它失败了 因为 sh 是他的发行版中 dash 的符号链接 ls la bin sh lrwxrwxrwx 1 root root 4 Aug
  • ftrace:仅打印trace_printk()的输出

    是否可以只转储trace printk 输出于trace文件 我的意思是过滤掉函数跟踪器 或任何其他跟踪器 中的所有函数 一般来说 您可以在选项目录中关闭选项 sys kernel debug tracing options Use ls显
  • 如何使用 GOPATH 的 Samba 服务器位置?

    我正在尝试将 GOPATH 设置为共享网络文件夹 当我进入 export GOPATH smb path to shared folder I get go GOPATH entry is relative must be absolute

随机推荐

  • 基于蜣螂算法优化的SVM数据分类预测-附代码

    基于蜣螂算法优化的SVM数据分类预测 附代码 文章目录 基于蜣螂算法优化的SVM数据分类预测 附代码 1 数据集 2 SVM模型建立 3 基于蜣螂算法优化的SVM 4 测试结果 5 参考文献 6 Matlab代码 7 python代码 摘要
  • IP数据包格式各字段详解说明

    1 版本 指IP协议的版本 为0100或0110 即IPv4和IPv6两种版本 通信双方使用的IP协议版本必须一致 2 首部长度 占 4 位 可表示的最大十进制数值是15 请注意 这个字段所表示数的单位是32位字 即0001表示1个32位字
  • android 中的的 sp/wp/RefBase

    转自 http blog csdn net innost article details 6752443 5 1 概述 初次接触Android源码时 见到最多的一定是sp和wp 即使你只是沉迷于Java世界的编码 那么Looper和Hand
  • STM32CubeIDE IAP原理讲解,及UART双APP交替升级IAP实现

    随言 IAP应该是我唯一想写的文章 从创建这个账号开始 但是不知不觉几年过去了 一直没去写这文章 现在就随便写写吧 曾做过4G模块UART协议与STM32通讯实现远程无线迭代升级 一共2个APP bootloader优先选择稳定高版本的AP
  • 最详解决:jupyter notebook不会自动打开浏览器问题

    一 宝刀未老的老Amy回归之 问题描述 好久木有在 csdn 上写文章了 那是什么原因让 开摆一年 的老Amy 开写 了呢 噔噔蹬蹬 答案是 老Amy的一颗责任心 言归正传 最近替别的老师上几节课 刚好告诉大家如何安装 jupyter 以及
  • 线程复习(针对面试)

    问题一 请说明一下进程和线程的区别 一个进程运行要给他分配系统资源 维护他的代码段和数据段 堆栈等 而线程跟他共享这些 节俭的多任务操作方式 典型的UNIX Linux进程可以看成只有一个控制线程 一个进程在同一时刻只做一件事情 有了多个控
  • (附源码)spring boot西安市中小学生护眼平台开发 毕业设计 080855

    springboot西安市中小学生护眼平台开发 摘要 俗话说 眼睛是心灵的窗户 可在这个科学技术日新月异发展的大千世界里 戴眼镜的人却随处可见 特别是我国在校学生3 2亿 平均近视率超过60 其中小学生为35 初中生为65 高中生达79 更
  • CAD螺纹lisp程序_公英制螺纹标注方法及加工大全

    普通螺纹的标记 螺纹公差带代号的标注在螺纹代号之后 中间用 分开 如果螺纹的中径公差带代号不同 则分别注出 前者表示中径公差带 后者表示顶径公差带 如果中径公差带与顶径公差带代号相同 则只标注一个代号 例如 M10 5g6g M10 1 6
  • shell是什么?ssh 与 git bash linux或cmd与 shell区别

    什么是shell Bash介绍及内容 1 认识Bash这个Shell 管理整个计算机硬件就是操作系统的内核 而内核是需要被保护的 不能让用户随便去修改不然系统崩溃了怎么办 所以一般用户只能通过Shell来跟内核沟通 shell的定义 什么是
  • ajax上传netcore插件,.NET Core Web 文件分片上传,带进度条实用插件

    git CMD命令 git initgit add 添加文件至暂存区 git commit m 描述性语句 随意写即可 git branch gh pages 创建仓库分支 git checkou 使用ARM模板部署自动扩展的Linux V
  • canvas圆形和正方形碰撞检测

    1 圆形碰撞检测 弧度转角度 function d2a n return n Math PI 180 角度转弧度 function a2d return n 180 Math PI window onload function let oC
  • 技术干货的选择性问题

    今天准备整理下微信的收藏夹 因为我发现好像在里面已经收藏了太多文章 这些收藏的文章并不是已经读过觉得不错故而收藏的 而是全没读过的 而其中的很大部份都是所谓的技术干货型文章 因为这类文章一方面比较长 另一方面比较费脑 所以我总是习惯在碰到的
  • 微软2013暑假实习生笔试题

    自己mark一下 以作后备 下面提交原文链接 原文博客 部分题目答案不确定 会持续更新 1 Which of the following calling convention s support s supportvariable leng
  • 报警服务器物理内存,从内存告警谈ESXi主机内存管理——内存构成

    在 如何处理ESXi主机的黄色告警 一文中我们提到了在没有冗余的管理网络或启用SSH的情况下 ESXi主机图标右下方将会出现黄色的告警 除了上述配置导致告警之外 另一种常见的告警就是ESXi主机的内存使用率过高 ESXi主机内存告警 当ES
  • osgEarth的Rex引擎原理分析(六十七)TileNode中的_surface(SurfaceNode)作用是什么

    目标 五十五 中的问题138 每个瓦片TileNode都有一个 surface SurfaceNode 这里面会存放瓦片的几何信息 drawable TileDrawable 这个几何信息会传给DrawTileCommand 用于绘制该瓦片
  • protobuf的安装使用

    简介 Protobuf是Protocol Buffers的简称 它是Google公司开发的一种数据描述语言 是一种轻便高效的结构化数据存储格式 可以用于结构化数据串行化 即序列化 它很适合做数据存储或 RPC 数据交换格式 可用于通讯协议
  • 转 使用Android Studio 创建第一个Android 应用

    转自 https blog csdn net u013926216 article details 81977815 一 使用Android Studio 开发Android 应用的流程 二 一个简单的登陆界面程序 程序功能说明 创建And
  • 有关win10的C:/ProgramFiles\WindowsApps\文件系统错误(12007)问题

    win10电脑开机的时候 突然出现这二个系统错误 C ProgramFiles WindowsApps b9eced6f asusbatteryhealthcharging 1 0 7 0 86 qmba6 以及 C ProgramFile
  • mysql 如何转换数据结构_如何将SQL查询结果转换为PANDAS数据结构?

    在这个问题上的任何帮助将不胜感激 所以基本上我想对我的SQL数据库运行查询并将返回的数据存储为Pandas数据结构 我已附上查询代码 我正在阅读有关Pandas的文档 但是在识别查询的返回类型时遇到了问题 我试图打印查询结果 但没有提供任何
  • 从零开始用C语言实现图片解码播放器(有源码)

    1 项目描述 1 1 项目硬件平台介绍 1 硬件平台 九鼎公司的X210开发板 S5PV210 Cortex A8内核 2 软件平台 linux2 6 35 7内核 直接基于linux API操作 1 2 项目功能介绍 1 调用编译好的可执