LCD屏幕显示PNG图像
正点原子LCD屏幕显示PNG图像
本文概要
这段时间在学习正点原子的IMX6ULL开发板,在应用编程中有一个代码练习是需要在LCD屏幕上显示PNG图像,但由于我的屏幕参数和教程中的有些出入,于是经过自己查阅和修改,终于成功在自己的LCD屏幕上显示PNG图像。
LCD 屏幕参数
我的LCD参数如下所示:

这里面出现一个问题,我的屏幕参数显示的是32位,但是实际上RGBA的位数只有24位。那么多出来的8位是什么呢?起初我以为是透明度A,但是参数显示的是透明度所占位数为0。
后面我猜测这8位可能不是RGBA中的一种,而是用来数据对齐的一种方式。由于和我们的代码主体无关,所以后面也就不管它了。
总而言之,这几个参数就是LCD显示中最重要的参数:
屏幕分辨率:1024*600
像素深度:32位
像素格式:RGB888
代码流程
zlib和libpng库
zlib和libpng库是PNG图像的解析库,在Linux系统中直接下载源码然后编译移植到开发板文件系统即可。
zlib库下载地址: https://www.zlib.net/fossils/
libpng库下载地址:https://github.com/glennrp/libpng/releases
其中libpng也有帮助文档:http://www.libpng.org/pub/png/libpng-1.4.0-manual.pdf
这里我使用的是zlib-1.2.10 和 libpng-1.6.35,版本根据自己的需求选择。
解析图像流程
使用libpng库解析图像的流程基本是固定的,无非就是:
获取文件描述符:打开PNG图像文件获取文件描述符
解码对象:使用
png_create_read_struct函数创建png_structp结构体指针,即为解码对象。解码对象在后续操作中就相当于一个句柄的作用;图像信息对象:使用
png_create_info_struct函数创建png_infop结构体指针,即为图像信息对象,用于存储图像的宽、高等属性;错误处理:使用
setjmp(png_jmpbuf(png_ptr))设置错误处理,这里setjmp函数的作用就是设置错误跳点,当发送错误时就跳到这里来执行后续函数;指定数据源:使用
png_init_io函数设置数据源,表明我们要解码的就是这个图像文件;读取图像信息:这里使用
png_read_png()函数来直接读取PNG图像信息,这个函数会自动开辟一个内存空间用来存储图像信息。因为这个内存信息和png_structp结构体对象绑定了,所以后续可以用png_get_rows()函数来获取该内存地址;获取图像数据: 使用
png_get_rows()函数获取图像数据,并返回一个png_bytep类型的指针,指向的是图像数据中每一行的地址,所以该指针指向的是一个数组,数组每个元素是图像数据中一行的数据,元素大小为image_width*bytes_per_pixel/8;转换为RGB888格式:这里外层循环的作用是遍历图像数据的每一行,内存循环的作用是遍历图像数据的每一列。并且用指针
png_bytep px指向图像数据中每3个数据为一组的地址,指针unsigned char *dst指向图像显存地址中每4个数据为一组的地址,然后对RGB进行数据转换,这里为什么是将RGB的顺序互换,我也不太清楚,可能与图片原先的RGB格式有关,反正只要转换为LCD屏幕的RGB格式就好;
点击查看代码
/* 将24位RGB图像转换为32位RGB888格式 */
for (int y = 0; y < image_height; y++) {
for (int x = 0; x < image_width; x++) {
png_bytep px = &(row_pointers[y][x * 3]);
unsigned char *dst = &image_data[(y * image_width + x) * 4];
dst[0] = px[2]; // R
dst[1] = px[1]; // G
dst[2] = px[0]; // B
dst[3] = 0xFF; // A (Alpha channel set to 255)
}
}
- 分配内存并写入显存:使用
malloc()函数分配内存,并使用memcpy()函数将图像数据写入内存中;
点击查看代码
/* 将图像数据写入显存 */
for (int y = 0; y < image_height && y < screen_height; y++) {
memcpy(screen_base + y * line_length, image_data + y * image_width * 4, image_width * 4);
}
- 释放内存:使用
free()函数释放内存。
最终显示效果
显示效果如下:

总结与对比
相较于教程的代码流程,卡住我的主要就是理解我的LCD屏幕为32位的含义所在,不是RGBA,而是有8位作为数据对齐。以及还有转化为RGB888格式的代码,但是这个我是交给Copilot自动生成了,在这里狠狠安利一波Copilot!!
其实理解了代码的含义也不难,最重要的就是掌握好libpng库的使用框架和API,当然还有图像的存储方式:图像的image_width和image_height指的是图像的宽和高分别有多少个像素点,而图像的存储是按行优先排列的,所以用png_get_rows()函数获取的是指向图像数据一行一行地址的指针,其实可以当作是一个二维矩阵来看,所以通过两层循环也就可以遍历图像数据了。
LCD屏幕显示PNG图像的更多相关文章
- tiny210V2开发板hdmi输出到10.1寸LCD,无图像
tiny210V2开发板hdmi输出到10.1寸LCD,无图像... 用tiny210V2开发板的HDMI接口输出到的10.1寸LCD,LCD无任何现象.说明一下我的情况,我的10.1寸屏LCD是HD ...
- hud项目lcd调试过程的一些见解
1.帧缓冲(FrameBuffer)设备驱动帧缓冲设备为标准的字符型设备,在Linux中主设备号29,定义在/include/uapi/linux/major.h中的FB_MAJOR,次设备号定义帧缓 ...
- 【雕爷学编程】MicroPython动手做(05)——零基础学MaixPy之LCD液晶屏
配套 2.4寸LCD屏 ST7789驱动器芯片(24P 320X240) ST7789驱动器芯片2.4寸LCD屏(24P 320X240)主要参数 1. 模块名称:液晶显示模块2. 型号:KD024C ...
- [nRF51822] 1、一个简单的nRF51822驱动的天马4线SPI-1.77寸LCD彩屏DEMO
最近用nRF51822写了个天马4线SPI的1.77寸LCD彩屏驱动,效果如下: 屏幕的规格资料为:http://pan.baidu.com/s/1gdfkr5L 屏幕的驱动资料为:http://pa ...
- 高通安卓调试LCD几方面总结
来公司上班现在已经整整一个月了,蔽人不才,能力有限,学习进度缓慢,不过也是有一点点的收获与心得,在这里写出来与大家分享,养成良好的记录习惯也免得后忘记. 不啰嗦了,开入正题.来公司一个月左右的时间,主 ...
- 基于FPGA的LCD+CMOS视频采集显示使用小结
基于FPGA的LCD+CMOS视频采集显示 液晶显示器采用扫描模式,RGB888 电源采用:+5V供电 usb供电有时候会出现供电不足的问题 显示器接口有两种选择:16bit或24bit 分别对应 ...
- 第47章 QR-Decoder-OV5640二维码识别—零死角玩转STM32-F429系列
第47章 QR-Decoder-OV5640二维码识别 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.y ...
- 第46章 DCMI—OV5640摄像头—零死角玩转STM32-F429系列
第46章 DCMI—OV5640摄像头 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com ...
- 第45章 DCMI—OV2640摄像头—零死角玩转STM32-F429系列
第45章 DCMI—OV2640摄像头 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com ...
- LCD12864 液晶显示-汉字及自定义显示(并口)
LCD12864带字库,型号:CM12864-12.其相关数据手册可以在百度中搜索“ST7920 系列中文图形液晶模块使用说明书”,里面有详细的介绍.这里就不在多描述. 其原理简图:(我们只需关心接口 ...
随机推荐
- Odoo17.0 基于企业微信的备用金和费用报销
前面讲过了企业微信的基础应用,现在我们来看一下如何借助企业微信的审批端能力结合odoo来实现企业中的两大常规业务流程备用金和费用报销. 企业微信端设置 我们这里使用的是企业微信的原生审批流程,因此我们 ...
- 【java深入学习第2章】Spring Boot 结合 Screw:高效生成数据库设计文档之道
在开发过程中,数据库设计文档是非常重要的,它可以帮助开发者理解数据库结构,方便后续的维护和扩展.手动编写数据库设计文档不仅耗时,而且容易出错.幸运的是,可以使用Spring Boot和Screw来自动 ...
- 3. set 的使用
3. set 的使用 因为在实际工程中,我们不会将具体文件全部写出来,这是一件费力不讨好的事情. 3.1 set 定义变量 在 CMake 文件中,默认的变量数据类型是字符串,如果要用别的类型,需要进 ...
- Sonar 扫描之SonarScanner介绍
Sonar扫描之SonarScanner介绍 SonarScanner用于在构建系统没有指定scanner时使用. 项目配置 在你的项目根目录中创建一个名为 sonar-project.propert ...
- Fiddler+proxifier解决抓取不到客户端接口的问题
工作中偶尔会遇到Fiddler抓不到客户端接口问题,那么就要借助第三方工具proxifier来实现了: 下载地址: 原地址:链接: https://pan.baidu.com/s/1JPJ4cILEs ...
- c++ 快速复习第一部份
去年有事无事学过一c++ ,,由于工作用不上,学来没有用,所以学得乱七八的,最近需要复习一下,因为最近想学习一下硬 件相关 第一 引用头文件和自定义头 #include <iostream& ...
- 解决SpringMVC/SpringBoot @RequestBody无法注入基本数据类型
我们都知道SpringMVC使用 @RequestBody 注解可以接收请求content-type 为 application/json 格式的消息体.但是我们必须使用实体对象,Map或者直接用St ...
- 如何在mysql中删除重复数据
#分组去重法 讲重复的列进行分组 之后用min(id) #取其中最小的保留,其余的删除 -- 步骤 1: 创建临时表,保存每组最小的ID CREATE TEMPORARY TABLE tmp_keep ...
- 【Hibernate】04 主键策略 & CRUD
实体类编写规范: - 每个属性不应该被公开的访问,设置私有 - 提供可以访问和设置的方法,GETTER & SETTER - 必须编写一个主键属性[ID 唯一值] - 建议使用基本类型的包装类 ...
- 【DataBase】XueSQL Training
地址: http://xuesql.cn/ Lesson0 -- 认识SQL -- [初体验]这是第一题,请你先将左侧的输入框里的内容清空,然后请输入下面的SQL,您将看到所有电影标题: SELECT ...