百问FB显示开发图像处理 - PNG图像处理
2.3 PNG图像处理
2.3.1 PNG文件格式和libpng编译
跟JPEG文件格式一样,PNG也是一种使用了算法压缩后的图像格式,与JPEG不同,PNG使用从LZ77派生的无损数据压缩算法。对于PNG文件格式,也有相应的开源工具libpng。
libpng库可从官网上下载最新的源代码:
http://www.libpng.org/pub/png/libpng.html
在使用libpng之前,我们先要交叉编译libpng的库文件和头文件并存到开发板的文件系统中。以下是libpng的编译过程:
- 解压并进入文件目录
tar xzf libpng-1.6.37.tar.gz
cd libpng-1.6.37/
- 交叉编译
./configure --prefix=/work/projects/libpng-1.6.37/tmp/ --host=arm-linux
make
make install
- 将编译出来的头文件和库文件拷贝到交叉编译器的相应目录下
cd /work/projects/libpng-1.6.37/tmp/include
cp * /usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/usr/include
cd /work/projects/libpng-1.6.37/tmp/lib
cp *so* -d /usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t/lib
- 将编译出来的头文件和库文件拷贝到开发板文件系统的相应目录下
cd /work/projects/libpng-1.6.37/tmp/lib
cp *.so* /work/nfs_root/fs_mini_mdev_new/lib/ -d
2.3.2 libpng接口函数的解析和使用
libpng的使用方法可以参考解压包中的使用说明libpng-manual.txt和例程example.c。libjpeg的使用步骤简单总结如下:
-
分配和初始化两个与libpng相关的结构体png_ptr,info_ptr
A. png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
参数2,3,4分别是用户自定义的错误处理函数,若无,则填NULL。
B. info_ptr = png_create_info_struct(png_ptr);
-
设置错误返回点
setjmp(png_jmpbuf(png_ptr));
当出现错误时,libpng将会自动调用返回到这个点。在这个点我们可以进行一些清理工作。如果在调用png_create_read_struct时没有设置自定义的错误处理函数,这一步是必须要做的。
-
指定源文件
png_init_io(png_ptr, fp);
参数1是步骤1中分配的png_ptr结构体,参数2是需要解析的PNG文件的文件句柄。
-
获取PNG图像的信息
A. 解析图片数据信息
png_read_png(png_ptr, info_ptr, png_transforms, png_voidp_NULL);
该函数会把所有的图片数据解码到info_ptr数据结构中。至于转化为什么格式,由参数png_transforms决定,它是一个整型参数,可以使用libpng库中定义的宏进行传参。这个参数相关的宏有很多,具体的可以参考库中的相关文件的解析。
B.查询图像信息
此外,我们还可以通过png_get_image_width,png_get_image_height,png_get_color_type等函数获得png图像的宽度,高度,颜色类型等信息,更多的图像信息获取函数可以在文件pngget.c中找到。
-
将info_ptr中的图像数据读取出来
有两种读取PNG图像信息的方法:
A. 一次性把所有的数据读入内存
png_read_image(png_ptr, row_pointers);
参数1是步骤1中分配的png_ptr,参数2是存放图片数据的指针。
B. 也可以逐行读取
row_pointers = png_get_rows(png_ptr, info_ptr);
参数1和参数2分别是步骤1中分配的png_ptr, info_ptr,返回值是每行数据的首地址。
参数1是步骤1中分配的png_ptr,参数2是存放图片数据的指针。
-
销毁内存
png_destroy_read_struct(&png_ptr, &info_ptr, 0);
2.3.3 使用libpng把png文件转为rgb格式,在LCD上显示
代码清单2.3
1. /**********************************************************************
2. * 函数名称: IsnotPng
3. * 功能描述:判断是否为PNG文件
4. * 输入参数: ppFp - 文件句柄指针
5. strFileName - 文件名
6. * 返 回 值:0 - 是PNG格式 其他-不是PNG格式
7. ***********************************************************************/
8. int IsnotPng(FILE **ppFp, const char *strFileName)
9. {
10. char strCheckHeader[8];
11. *ppFp= fopen(strFileName, "rb");
12. if (*ppFp== NULL) {
13. return -1;
14. }
15. /* 读取PNG文件前8个字节,使用库函数png_sig_cmp即可判断是否为PNG格式 */
16. if (fread(strCheckHeader, 1, 8, *ppFp) != 8)
17. return -1;
18. return png_sig_cmp(strCheckHeader, 0, 8);
19.
20. }
21.
22. /**********************************************************************
23. * 函数名称: DecodePng2Rgb
24. * 功能描述:把PNG文件解析为RGB888格式
25. * 输入参数: ptData - 内含文件信息
26. * strFileName - 文件名
27. * 输出参数:PT_PictureData->pucRgbData - 内含rgb数据
28. * 返 回 值:0 - 成功 其他-失败
29. ***********************************************************************/
30. static int DecodePng2Rgb(const char *strFileName, PT_PictureData ptData)
31. {
32. int i, j;
33. int iPos = 0;
34. png_bytepp pucPngData;
35. /* 0.判断该文件是否为PNG格式 */
36. if (IsnotPng(&ptData->ptFp, strFileName)) {
37. printf("file is not png ...\n");
38. return -1;
39. }
40.
41. /* 1.分配和初始化两个与libpng相关的结构体png_ptr,info_ptr */
42. ptData->ptPngStrPoint = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
43. ptData->ptPngInfoPoint= png_create_info_struct(ptData->ptPngStrPoint);
44.
45. /* 2.设置错误的返回点 */
46. setjmp(png_jmpbuf(ptData->ptPngStrPoint));
47. rewind(ptData->ptFp); //等价fseek(fp, 0, SEEK_SET);
48.
49. /* 3.指定源文件 */
50. png_init_io(ptData->ptPngStrPoint, ptData->ptFp);
51.
52. /* 4.获取PNG图像数据信息和通道数,宽度,高度等
53. * 使用PNG_TRANSFORM_EXPAND宏做参数的作用是根据通道数的不同,
54. * 将PNG图像转换为BGR888或ABGR8888格式*/
55. png_read_png(ptData->ptPngStrPoint, ptData->ptPngInfoPoint, PNG_TRANSFORM_EXPAND, 0);
56. ptData->iChannels = png_get_channels(ptData->ptPngStrPoint, ptData->ptPngInfoPoint);
57. ptData->iWidth = png_get_image_width(ptData->ptPngStrPoint, ptData->ptPngInfoPoint);
58. ptData->iHeight = png_get_image_height(ptData->ptPngStrPoint, ptData->ptPngInfoPoint);
59.
60.
61. /* 5.将info_ptr中的图像数据读取出来 */
62. pucPngData = png_get_rows(ptData->ptPngStrPoint, ptData->ptPngInfoPoint); //也可以分别每一行获取png_get_rowbytes();
63. if (ptData->iChannels == 4) { //判断是24位还是32位
64. ptData->iRawSize= ptData->iWidth * ptData->iHeight*4; //申请内存先计算空间
65. ptData->pucRawData= (unsigned char*)malloc(ptData->iRawSize);
66. if (NULL == ptData->pucRawData) {
67. printf("malloc rgba faile ...\n");
68. png_destroy_read_struct(&ptData->ptPngStrPoint, &ptData->ptPngInfoPoint, 0);
69. fclose(ptData->ptFp);
70. return -1;
71. }
72. /* 从pucPngData里读出实际的RGBA数据出来
73. * 源数据为ABGR格式*/
74. for (i = 0; i < ptData->iHeight; i++)
75. for (j = 0; j < ptData->iWidth * 4; j += 4) {
76. ptData->pucRawData[iPos++] = pucPngData[i][j + 3];
77. ptData->pucRawData[iPos++] = pucPngData[i][j + 2];
78. ptData->pucRawData[iPos++] = pucPngData[i][j + 1];
79. ptData->pucRawData[iPos++] = pucPngData[i][j + 0];
80. }
81.
82. /* 将得到的RGBA转换为RGB888格式 */
83. if(RgbaToRgb(ptData)!=0)
84. return -1;
85.
86. }
87. else if (ptData->iChannels == 3 ) { //判断颜色深度是24位还是32位
88. ptData->iRgbSize= ptData->iWidth * ptData->iHeight*3; //申请内存先计算空间
89. ptData->pucRgbData = (unsigned char*)malloc(ptData->iRgbSize);
90. if (NULL == ptData->pucRgbData) {
91. printf("malloc rgba faile ...\n");
92. png_destroy_read_struct(&ptData->ptPngStrPoint, &ptData->ptPngInfoPoint, 0);
93. fclose(ptData->ptFp);
94. return -1;
95. }
96. /* 从pucPngData里读出实际的RGB数据
97. * 源数据为BGR格式*/
98. for (i = 0; i < ptData->iHeight; i ++) {
99. for (j = 0; j < ptData->iWidth*3; j += 3) {
100. ptData->pucRgbData[iPos++] = pucPngData[i][j+2];
101. ptData->pucRgbData[iPos++] = pucPngData[i][j+1];
102. ptData->pucRgbData[iPos++] = pucPngData[i][j+0];
103. }
104. }
105. ptData->iBpp = 24;//转化之后的格式为RGB888格式
106. }
107. else return -1;
108.
109.
110. /* 6:销毁内存 */
111. png_destroy_read_struct(&ptData->ptPngStrPoint, &ptData->ptPngInfoPoint, 0);
112. fclose(ptData->ptFp);
113.
114.
115. return 0;
116. }
相关文章:
百问FB显示开发图像处理 - PNG图像处理
2.3 PNG图像处理 2.3.1 PNG文件格式和libpng编译 跟JPEG文件格式一样,PNG也是一种使用了算法压缩后的图像格式,与JPEG不同,PNG使用从LZ77派生的无损数据压缩算法。对于PNG文件格式,也有相应的开源工具libpng。 libpng库可从…...
【JavaWeb后端学习笔记】MySQL多表查询(内连接、外连接、子查询)
MySQL 多表查询 1、连接查询1.1 内连接1.2 外连接 2、子查询2.1 标量子查询2.2 列子查询2.3 行子查询2.4 表子查询 3、多表查询案例 多表查询有两大类:连接查询和子查询。 连接查询又分为隐式/显式内连接和左/右外连接。 子查询又分为标量子查询、列子查询、行子查询…...
RocketMQ 过滤消息 基于tag过滤和SQL过滤
RocketMQ 过滤消息分为两种,一种tag过滤,另外一种是复杂的sql过滤。 tag过滤 首先创建producer然后启动,在这里创建了字符串的数组tags。字符串数组里面放置了多个字符串,然后去发送15条消息。 15条消息随着i的增长,…...
element-ui 基本样式的一些更改【持续更新】
1、 去除el-tabs的底部灰色横线 ::v-deep .el-tabs__nav-wrap::after {height: 0px;}2、el-table设置表头颜色 <el-table:data"tableData":header-cell-style"{background:#F7F8FA,color:#4E5869}"><el-table-columnlabel"序号"type&qu…...
element-ui radio和checkbox禁用时不置灰还是原来不禁用时的样式
把要紧用的内容加上一个class"notEdit-page" z注意要在style里面写不能加上scoped /*//checkBox自定义禁用样式*//*//checkBox自定义禁用样式*/ .notEdit-page.el-checkbox__input.is-disabled.is-checked.el-checkbox__inner::after {border-color: #fff; } .notEdi…...
第一部分:基础知识 6. 函数 --[MySQL轻松入门教程]
MySQL 提供了丰富的内置函数,涵盖了字符串处理、数值计算、日期时间操作、聚合分析以及控制流等多个方面。这些函数可以帮助用户更高效地进行数据查询和处理。 1.字符串函数 MySQL 提供了丰富的字符串函数来帮助用户处理和操作字符串数据。下面是一些常用的 MySQL…...
【蓝桥杯每日一题】扫雷
扫雷 知识点 2024-12-3 蓝桥杯每日一题 扫雷 dfs (bfs也是可行的) 题目大意 在一个二维平面上放置这N个炸雷,每个炸雷的信息有$(x_i,y_i,r_i) $,前两个是坐标信息,第三个是爆炸半径。然后会输入M个排雷火箭࿰…...
【算法】棋盘覆盖问题源代码及精简版
目录 一、题目 二、样例 三、示例代码 四、精简代码 五、总结 对于棋盘覆盖问题的解答和优化。 一、题目 输入格式: 第一行,一个整数n(棋盘n*n,n确保是2的幂次,n<64) 第二行,两个整数…...
Django的介绍
Django是一个高级的Python Web框架,它鼓励快速开发和干净、实用的设计。Django遵循MVC设计模式,即模型(Model)、视图(View)和控制器(Controller),并提供了一个即时可用的…...
【Spring工具插件】lombok使用和EditStarter插件
阿华代码,不是逆风,就是我疯 你们的点赞收藏是我前进最大的动力!! 希望本文内容能够帮助到你!! 目录 引入 一:lombok介绍 1:引入依赖 2:使用 3:原理 4&…...
掌控时间,成就更好的自己
在个人成长的道路上,时间管理是至关重要的一环。有效的时间管理能够让我们更加高效地完成任务,实现自己的目标,不断提升自我。 时间对每个人都是公平的,一天只有 24 小时。然而,为什么有些人能够在有限的时间里做出卓…...
Ruby On Rails 笔记2——表的基本知识
Active Record Basics — Ruby on Rails Guides Active Record Migrations — Ruby on Rails Guides 原文链接自取 1.Active Record是什么? Active Record是MVC模式中M的一部分,是负责展示数据和业务逻辑的一层,可以帮助你创建和使用Ruby…...
【AI系统】EfficientNet 系列
EfficientNet 系列 本文主要介绍 EffiicientNet 系列,在之前的文章中,一般都是单独增加图像分辨率或增加网络深度或单独增加网络的宽度,来提高网络的准确率。而在 EfficientNet 系列论文中,会介绍使用网络搜索技术(NAS)去同时探索…...
【Python小白|Python内置函数学习2】Python有哪些内置函数?不需要导入任何模块就可以直接使用的!现在用Python写代码的人还多吗?
【Python小白|Python内置函数学习2】Python有哪些内置函数?不需要导入任何模块就可以直接使用的!现在用Python写代码的人还多吗? 【Python小白|Python内置函数学习2】Python有哪些内置函数?不需要导入任何模块就可以直接使用的&a…...
蓝桥杯分治
P1226 【模板】快速幂 题目描述 给你三个整数 𝑎,𝑏,𝑝a,b,p,求 𝑎𝑏 mod 𝑝abmodp。 输入格式 输入只有一行三个整数,分别代表 𝑎,𝑏,𝑝a,b,p。…...
YOLOv8实战无人机视角目标检测
本文采用YOLOv8作为核心算法框架,结合PyQt5构建用户界面,使用Python3进行开发。YOLOv8以其高效的实时检测能力,在多个目标检测任务中展现出卓越性能。本研究针对无人机目标数据集进行训练和优化,该数据集包含丰富的无人机目标图像…...
三、【docker】docker和docker-compose的常用命令
文章目录 一、docker常用命令1、镜像管理2、容器管理3、容器监控和调试4、网络管理5、数据卷管理6、系统维护7、实用组合命令8、常用技巧二、docker-compose常用命令1、基本命令2、构建相关3、运行维护4、常用组合命令5、实用参数 一、docker常用命令 1、镜像管理 # 查看本地…...
Qt 2D绘图之五:图形视图框架的结构、坐标系统和框架间的事件处理与传播
参考文章链接: Qt 2D绘图之五:图形视图框架的结构和坐标系统 Qt 2D绘图之六:图形视图框架的事件处理与传播 图形视图框架的结构 在前面讲的基本绘图中,我们可以自己绘制各种图形,并且控制它们。但是,如果需要同时绘制很多个相同或不同的图形,并且要控制它们的移动、…...
基于SpringBoot+Vue的美妆购物网站
作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏:…...
MySQL之创建和管理表
目录 1. MySQL中的数据类型编辑编辑 2. 创建和管理数据库 方式1:创建数据库 方式2:创建数据库并指定字符集 方式3:判断数据库是否已经存在,不存在则创建数据库( 推荐 ) 总结 2.2 使用数据库 查看当…...
多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
