罪恶克星 发表于 2024-8-1 07:00:42

在 LCD 上表现 png 图片-I.MX6U嵌入式Linux C应用编程学习笔记基于正点原子

在 LCD 上表现 png 图片

https://i-blog.csdnimg.cn/direct/f1f86de257b14538a90837028f5edecd.jpeg#pic_center
PNG 简介

无损压缩:PNG 使用 LZ77 派生算法举行无损压缩,确保图像质量不受损,且压缩比高

体积小:通过高压缩比,PNG 文件体积小,恰当网络传输

索引彩色模式:PNG-8 格式采用8位调色板,将RGB图像转换为索引彩色图像,镌汰数据量

优化的网络传输表现:PNG 支持流式浏览,允许图像在未完全下载前表现基本内容,恰当网络通讯

支持透明结果:PNG 提供256级透明度,使图像边缘与配景平滑融合,这是GIF和JPEG不具备的特性

libpng 简介

libpng 是用于处理 PNG 图像的库

功能:支持对 PNG 图像文件举行解码和编码

性子:免费、开源的 C 语言函数库

对比:与 libjpeg 类似

zlib 移植

zlib 简介



[*] zlib 是一个包含数据压缩算法的函数库,是免费、开源的 C 语言库
[*] libpng 依靠:libpng 依靠于 zlib 库,因此在移植 libpng 之前需要先移植 zlib
下载源码包



[*] 下载链接: https://www.zlib.net/fossils/
[*] 选择 1.2.10 版本的 zlib

[*]

编译源码



[*] 将下载的 zlib-1.2.10.tar.gz 压缩文件拷贝到 Ubuntu 系统的用户家目次下
[*] tar -xzf zlib-1.2.10.tar.gz

[*]解压之后就会得到 zlib-1.2.10 文件夹,这就是 zlib 的源代码目次

[*] 先在 tools 目次下创建一个名为 zlib 的文件夹,作为 zlib 库的安装目次
[*] 设置

[*] 先对交叉编译工具的情况举行初始化

[*]source /opt/fsl-imx-x11/4.1.15-2.1.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi

[*] 对 zlib 工程举行设置

[*] ./configure --prefix=/home/alientek/tools/zlib/
[*] –prefix 选项指定 zlib 库的安装目次


[*] 编译

[*]make

[*] 安装

[*]make install

安装目次下的文件夹先容



[*] 头文件目次 include
[*] 库文件目次 lib
移植到开发板



[*] 将出厂系统中原有的 zlib 库文件删除

[*]rm -rf /usr/lib/libz.* /lib/libz.*

[*] 将编译得到的 zlib 库文件拷贝到开发板/usr/lib 目次,拷贝库文件时,需要注意符号
链接的问题,不能破坏原有的符号链接

[*]开发板/usr/lib 目次下的 zlib 库文件

libpng 移植

下载源码包



[*]下载链接: https://github.com/glennrp/libpng/releases
编译源码



[*] 将下载的 libpng-1.6.35.tar.gz 压缩包文件拷贝到 Ubuntu 系统
[*] 解压:tar -xzf libpng-1.6.35.tar.gz
[*] 解压之后得到 libpng-1.6.35 文件夹,这便是 libpng 的源码目次
[*] 在编译 libpng 之前,先在 tools 目次下创建一个名为 png 的文件夹,作为 libpng 库的安装目次
[*] 设置

[*] 先对交叉编译工具的情况举行初始化

[*]source /opt/fsl-imx-x11/4.1.15-2.1.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi

[*] 得告知编译器 zlib 库的安装目次,将 zlib 库安装目次下的 include 和 lib 路径导出到情况变量

[*]export LDFLAGS=“                                                                           L                                           D                                           F                                           L                                           A                                           G                                           S                                                      −                                        L                                        /                                        h                                        o                                        m                                        e                                        /                                        d                                        t                                        /                                        t                                        o                                        o                                        l                                        s                                        /                                        z                                        l                                        i                                        b                                        /                                        l                                        i                                        b                                        "                                        e                                        x                                        p                                        o                                        r                                        t                                        C                                        F                                        L                                        A                                        G                                        S                                        =                                        "                                                {LDFLAGS} -L/home/dt/tools/zlib/lib" export CFLAGS="                                 LDFLAGS−L/home/dt/tools/zlib/lib"exportCFLAGS="{CFLAGS} -I/home/dt/tools/zlib/include”
export CPPFLAGS=“${CPPFLAGS} -I/home/dt/tools/zlib/include”

[*] 对 libpng 源码工程举行设置

[*] ./configure --prefix=/home/alientek/tools/png --host=arm-poky-linux-gnueabi
[*] –prefix 选项指定 zlib 库的安装目次


[*] 编译

[*]make

[*] 安装

[*]make install

安装目次下的文件夹先容



[*]同样包含了 bin、include、lib 这些目次
移植到开发板



[*] 将开发板出厂系统中已经移植好的
libpng 库文件删除

[*]rm -rf /lib/libpng* /usr/lib/libpng*

[*] 将编译得到的 libpng 库文件拷贝到开发板/usr/lib 目次

[*]开发板/usr/lib 目次下的 libpng 相关库文件

libpng 使用阐明

libpng 还包含编码功能,但本文不作先容。libpng 官方提供了详细使用文档



[*] PDF 文档:http://www.libpng.org/pub/png/libpng-1.4.0-manual.pdf
[*] TXT 文档:
http://www.libpng.org/pub/png/libpng-manual.txt
libpng 的数据结构



[*] 头文件:使用 libpng 需要包含头文件 <png.h>,此中包含 API 和数据结构的声明
[*] 关键数据结构:libpng 有两个重要的数据结构体:png_struct 和 png_info
[*] png_struct

[*] 用于 libpng 函数内部
[*] 作为通报给每个 libpng 函数调用的第一个变量
[*] 用户需要创建并初始化这个对象,但通常不会直接使用

[*] png_info

[*] 形貌 PNG 图像的信息
[*] 旧版本中,用户可以直接访问 png_info 成员,如图像宽、高、像素深度等
[*] 新版本中,建议通过 png_get_XXX 和 png_set_XXX 接口来访问和修改 png_info 成员,以避免问题

创建和初始化 png_struct 对象



[*] 使用 png_create_read_struct() 创建一个用于 PNG 解码的 png_struct 对象

[*] png_structp png_create_read_struct(png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn,
png_error_ptr warn_fn);
[*] 第一个参数 user_png_ver 通常设置为 PNG_LIBPNG_VER_STRING(png.h 头文件中界说的一个宏),包含 libpng 的版本信息

[*]#define PNG_LIBPNG_VER_STRING “1.6.35”

[*] error_ptr、error_fn、warn_fn 参数用于自界说错误处理和告诫处理函数,也可设置为 NULL,使用 libpng 默认的处理函数
[*] 返回一个指向 png_struct 对象的指针(png_structp)
[*] 假如创建失败,返回 NULL,通过判断返回值是否为 NULL 来确认函数实验是否乐成
[*] 示例:
png_structp png_ptr = NULL;
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr)
return -1;

[*] 使用 png_create_write_struct() 创建一个用于 PNG 编码的 png_struct 对象
创建和初始化 png_info 对象



[*] 创建 png_info 对象

[*] 使用 png_create_info_struct() 函数创建 png_info 对象
[*] png_infop png_create_info_struct(png_const_structrp png_ptr);
[*] 需要传入一个 png_struct 对象的指针,内部会建立 png_struct 和 png_info 对象之间的关联
[*] 返回一个指向 png_info 对象的指针(png_infop)
[*] 假如创建乐成,返回指向 png_info 对象的指针。
假如创建失败,返回 NULL,调用者可通过判断返回值是否为 NULL 来确认函数调用是否乐成

[*] 当销毁 png_struct 对象时,也可以销毁 png_info 对象

[*] 示例:
png_infop info_ptr = NULL;
info_ptr = png_create_info_struct(png_ptr);
if (NULL == info_ptr) {
png_destroy_read_struct(&png_ptr, NULL, NULL);
return -1;
}
[*] png_destroy_read_struct()函数用于销毁 png_struct 对象的函数

设置错误返回点



[*] 错误处理函数

[*] 调用 png_create_read_struct() 时,可以指定一个自界说的错误处理函数
[*] 假如未指定自界说错误处理函数,libpng 会使用默认的错误处理函数

[*] 默认错误处理函数

[*]默认的错误处理函数会实验一个跳转动作,跳转到步伐中的某个位置,这个位置称为错误返回点

[*] 错误返回点

[*] 当 libpng 遇到错误时,若使用默认错误处理函数,它会跳转到错误返回点
[*] 错误返回点是步伐中预先设定的一个位置,通常用于实验清算工作,如开释和销毁 png_struct 和 png_info 对象,避免内存走漏

[*] 避免直接终止

[*]发生错误时,不直接终止步伐,而是跳转到错误返回点实验必要的清算工作

[*] 设置错误返回点的方法

[*] 使用 setjmp 和 longjmp 库函数来设置错误返回点

[*] 函数跳转

[*] 在 C 语言中,goto 语句用于函数内部跳转,但不能跨越函数
[*] 使用 setjmp 和 longjmp 库函数可以实现跨越函数的跳转

[*] setjmp 函数

[*]setjmp(jmp_buf env) 用于设置跳转点,保存当进步程情况信息到 env 参数中

[*] longjmp 函数

[*] longjmp(jmp_buf env, int val) 用于实验跳转,跳转到 setjmp 设置的跳转点
[*] longjmp 调用后,类似于第二次调用 setjmp 返回

[*] 返回值区分

[*] setjmp 初次调用返回 0
[*] longjmp 调用后,setjmp 返回 val 参数指定的值,用于区分不同的起跳位置


[*] val 参数设置

[*]通常 longjmp 调用时,val 参数不为 0,以区分 setjmp 的初次返回和后续“伪”返回


[*] 编程举例

[*] 代码

[*]#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>




static jmp_buf buf;
static void hello(void)
{
printf(“hello world!\n”);
longjmp(buf,1);
printf(“Nice to meet you!\n”);
}
int main(void)
{
if(0 == setjmp(buf)) {
printf(“First return\n”);
hello();
}
else
printf(“Second return\n”);
exit(0);
}
                - 验证

                        -

- libpng 设置错误返回点

        - 错误处理机制:
libpng 库使用 setjmp/longjmp 组合处理错误跳转
        - 错误返回点设置:
使用 setjmp() 为 libpng 设置错误返回点
        - 错误处理流程:
当 libpng 遇到错误时,默认错误处理函数调用 longjmp() 举行跳转。
需要在代码中设置错误返回点,以便在错误发生时举行处理
                - /*设置错误返回点   */
if (setjmp(png_jmpbuf(png_ptr))) {
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
return -1;
}
指定命据源



[*] 需要指定举行解码的 PNG 图像,数据源可以是文件输入流、内存中的数据流等,这里以文件输入流为例
[*] png_init_io() 函数

[*] ibpng 提供 png_init_io() 函数来指定命据源,数据源以文件输入流的方式提供
[*] png_init_io(png_structrp png_ptr, png_FILE_p fp);
[*] 第一个参数是 png_ptr,指向 png_struct 对象
[*] 第二个参数 fp 是 png_FILE_p 类型指针,即标准 I/O 中的 FILE * 指针

[*] 打开文件

[*] 使用 fopen() 函数打开 PNG 文件,得到指向该文件的 FILE * 类型指针
[*] 示例:
FILE png_file = NULL;
/ 打开 png 文件 /
png_file = fopen(“image.png”, “r”); //以只读方式打开
if (NULL == png_file) {
perror(“fopen error”);
return -1;
}
/ 指定命据源 */
png_init_io(png_ptr, png_file);

读取 png 图像数据并解码



[*] 读取息争码 PNG 文件

[*]从 PNG 文件中读取数据并解码,将解码后的图像数据存放在内存中供用户读取

[*] 处理方式

[*] High-level 接口:封装了 low-level 接口,使用方便,只需一个函数,但灵活性不高
[*] Low-level 接口:灵活性高,但需要用户调用多个 API

[*] high-level 接口

[*] High-level 接口使用条件

[*] 内存空间足够大,可一次性存放解码后的数据
[*] 数据输出格式为 libpng 预界说的格式

[*]libpng 预界说的数据转换类型


[*] High-level 接口限定

[*]预界说的转换类型,不包罗配景颜色设置、伽马变动、抖动和填充物

[*] High-level 接口函数

[*] png_read_png(png_structrp png_ptr, png_inforp info_ptr, int transforms, png_voidp params);

[*] png_ptr:指向 png_struct 对象的指针
[*] info_ptr:指向 png_info 对象的指针
[*] transforms:整型参数,代表 libpng 预界说的转换类型

[*] 函数调用示例

[*]png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_ALPHA, NULL);


[*] High-level 接口调用顺序

[*] 调用 png_read_info 获取 PNG 图像信息
[*] 根据 transforms 设置数据输出格式
[*] 调用 png_read_image 解码并存放数据
[*] 调用 png_read_end 结束解码


[*] low-level 接口

[*] 使用 low-level 接口,需要用户将函数 png_read_png()所做的变乱一步一步实验
[*] 1、读取 PNG 图像信息

[*] 调用 png_read_info() 获取 PNG 图像信息并存入 png_info 对象
[*] png_read_info(png_ptr, info_ptr);

[*] 2、查询图像信息

[*] 使用 libpng 提供的 API 查询图像的宽度、高度、位深度和颜色类型
[*] unsigned int width = png_get_image_width(png_ptr, info_ptr); //获取 png 图像的宽度
unsigned int height = png_get_image_height(png_ptr, info_ptr); //获取 png 图像的高度
unsigned char depth = png_get_bit_depth(png_ptr, info_ptr); //获取 png 图像的位深度
unsigned char color_type = png_get_color_type(png_ptr, info_ptr); //获取 png 图像的颜色类型
[*] color type 在 png.h 头文件中界说,如上所示:

[*] 3、设置解码输出参数

[*] 根据需要调用 png_set_xxxxx 函数设置数据输出格式,比方:
[*] unsigned char depth = png_get_bit_depth(png_ptr, info_ptr);
unsigned char color_type = png_get_color_type(png_ptr, info_ptr);
if (16 == depth)
png_set_strip_16(png_ptr); //将 16 位深度转为 8 位深度
if (8 > depth)
png_set_expand(png_ptr); //假如位深小于 8,则扩展为 24-bit RGB
if (PNG_COLOR_TYPE_GRAY_ALPHA == color_type)
png_set_gray_to_rgb(png_ptr); //假如是灰度图,则转为 RGB
[*] 查看函数信息

[*] 在 libpng 的头文件 png.h 中可以查看每个函数的注释信息和参数列表
[*] 详细使用方法和更多转换函数请参考 libpng 的使用手册

[*] 自界说转换函数

[*] libpng 提供了多种转换函数,但不支持所有大概的输出格式(如 YUV565、RGB565、YUYV)
[*] 用户可以设置自界说转换函数来解决这些问题

[*] 注册自界说转换函数

[*] 使用 png_set_read_user_transform_fn() 注册自界说转换函数
[*] 使用 png_set_user_transform_info() 提供自界说转换函数所需的用户数据结构和输出数据详细信息(如颜色深度和颜色通道)
[*] 有关自界说转换函数和其他详细信息,可以查阅 libpng 的使用资助文档


[*] 4、更新 PNG 数据信息

[*] 调用 png_read_update_info() 更新 png_info 对象中的图像信息
[*] png_read_update_info(png_ptr, info_ptr);

[*] 5、读取并解码 PNG 数据

[*] 解码 PNG 数据

[*] 调用 png_read_image() 一次性解码整个 PNG 文件的数据并存入用户提供的内存区域

[*] png_read_image(png_ptr, row_pointers);
[*] 参数 png_ptr 指向 png_struct 对象
[*] 第二个参数 row_pointers 是一个 png_bytepp 类型的指针变量,也就是 unsigned char **(指针数组)

[*]png_bytep row_pointers;

[*] 无返回值

[*] 需要提供足够大的内存空间来保存解码后的数据,并通过 row_pointers 数组传入每一行的指针

[*] 内存分配

[*] 调用 png_read_image() 一次性解码整个 PNG 文件的数据并存入用户提供的内存区域

[*] png_bytep row_pointers = {0};
size_t rowbytes = png_get_rowbytes(png_ptr, info_ptr);//获取每一行数据的字节大小
int row;
/* 为每一行数据分配一个缓冲区 */
for (row = 0; row < height; row++)
row_pointers = png_malloc(png_ptr, rowbytes);
png_read_image(png_ptr, row_pointers);
[*] 使用 png_malloc() 为每一行数据分配缓冲区
[*] png_malloc() 是 libpng 提供的 API,等价于 malloc()

[*] 也可以调用 png_read_rows()一次解码 1 行或多行数据、并将解码
后的数据存放在用于提供的内存区域中

[*] ize_t rowbytes = png_get_rowbytes(png_ptr, info_ptr);//获取每一行数据的字节大小
png_bytep row_buf = png_malloc(png_ptr, rowbytes); //分配分缓冲、用于存储一行数据
int row;
for (row = 0; row < height; row++) {
png_read_rows(png_ptr, &row_buf, NULL, 1);//每次读取、解码一行数据(末了一个数字 1 表示每次 1 行)
/* 对这一行数据举行处理: 譬如刷入 LCD 显存举行表现 */
do_something();
}
[*] png_read_rows 会自动跳转处理下一行数据


[*] 内存管理差异

[*] 在 low-level 接口中,需要手动分配内存区域
[*] 在 high-level 接口中,调用 png_read_png() 时 libpng 会自动分配缓冲区


[*] 6、结束解码

[*] 调用 png_read_end() 结束读取息争码过程
[*] png_read_end(png_ptr, info_ptr);


读取解码后的数据



[*] 解码后处理

[*]解码完成后,可以获取解码后的数据举行进一步处理或直接表现到 LCD 上

[*] Low-Level 方式

[*]缓冲区由调用者分配,直接从缓冲区中获取数据即可

[*] High-Level 方式

[*] 缓冲区由 png_read_png() 函数内部门配,并与 png_struct 对象关联
[*] 使用 png_get_rows() 函数获取指向每一行数据缓冲区的指针数组
[*] png_bytepp row_pointers = NULL;
row_pointers = png_get_rows(png_ptr, info_ptr);//获取到指向每一行数据缓冲区的指针数组

[*] 内存管理

[*]在销毁 png_struct 对象时,由 png_read_png() 分配的缓冲区会被自动开释,归还给操作系统

结束销毁对象



[*] 调用 png_destroy_read_struct()销毁 png_struct 对象

[*]void png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr);

[*] 使用方法

[*]png_destroy_read_struct(png_ptr, info_ptr, NULL);

libpng 应用编程

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <string.h>
#include <linux/fb.h>
#include <sys/mman.h>
#include <png.h>

static int width;                     //LCD X分辨率
static int height;                      //LCD Y分辨率
static unsigned short *screen_base = NULL;      //映射后的显存基地址
static unsigned long line_length;       //LCD一行的长度(字节为单位)
static unsigned int bpp;    //像素深度bpp

static int show_png_image(const char *path)
{
    png_structp png_ptr = NULL;
    png_infop info_ptr = NULL;
    FILE *png_file = NULL;
    unsigned short *fb_line_buf = NULL; //行缓冲区:用于存储写入到LCD显存的一行数据
    unsigned int min_h, min_w;
    unsigned int valid_bytes;
    unsigned int image_h, image_w;
    png_bytepp row_pointers = NULL;
    int i, j, k;

    /* 打开png文件 */
    png_file = fopen(path, "r");    //以只读方式打开
    if (NULL == png_file) {
      perror("fopen error");
      return -1;
    }

    /* 分配和初始化png_ptr、info_ptr */
    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr) {
      fclose(png_file);
      return -1;
    }

    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
      png_destroy_read_struct(&png_ptr, NULL, NULL);
      fclose(png_file);
      return -1;
    }

    /* 设置错误返回点 */
    if (setjmp(png_jmpbuf(png_ptr))) {
      png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
      fclose(png_file);
      return -1;
    }

    /* 指定数据源 */
    png_init_io(png_ptr, png_file);

    /* 读取png文件 */
    png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_ALPHA, NULL);
    image_h = png_get_image_height(png_ptr, info_ptr);
    image_w = png_get_image_width(png_ptr, info_ptr);
    printf("分辨率: %d*%d\n", image_w, image_h);

    /* 判断是不是RGB888 */
    if ((8 != png_get_bit_depth(png_ptr, info_ptr)) &&
      (PNG_COLOR_TYPE_RGB != png_get_color_type(png_ptr, info_ptr))) {
      printf("Error: Not 8bit depth or not RGB color");
      png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
      fclose(png_file);
      return -1;
    }

    /* 判断图像和LCD屏那个的分辨率更低 */
    if (image_w > width)
      min_w = width;
    else
      min_w = image_w;

    if (image_h > height)
      min_h = height;
    else
      min_h = image_h;

    valid_bytes = min_w * bpp / 8;

    /* 读取解码后的数据 */
    fb_line_buf = malloc(valid_bytes);
    row_pointers = png_get_rows(png_ptr, info_ptr);//获取数据

    unsigned int temp = min_w * 3;//RGB888 一个像素3个bit位
    for(i = 0; i < min_h; i++) {

      // RGB888转为RGB565
      for(j = k = 0; j < temp; j += 3, k++)
            fb_line_buf = ((row_pointers & 0xF8) << 8) |
                ((row_pointers & 0xFC) << 3) |
                ((row_pointers & 0xF8) >> 3);

      memcpy(screen_base, fb_line_buf, valid_bytes);//将一行数据刷入显存
      screen_base += width;   //定位到显存下一行
    }

    /* 结束、销毁/释放内存 */
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
    free(fb_line_buf);
    fclose(png_file);
    return 0;
}

int main(int argc, char *argv[])
{
    struct fb_fix_screeninfo fb_fix;
    struct fb_var_screeninfo fb_var;
    unsigned int screen_size;
    int fd;

    /* 传参校验 */
    if (2 != argc) {
      fprintf(stderr, "usage: %s <png_file>\n", argv);
      exit(-1);
    }

    /* 打开framebuffer设备 */
    if (0 > (fd = open("/dev/fb0", O_RDWR))) {
      perror("open error");
      exit(EXIT_FAILURE);
    }

    /* 获取参数信息 */
    ioctl(fd, FBIOGET_VSCREENINFO, &fb_var);
    ioctl(fd, FBIOGET_FSCREENINFO, &fb_fix);

    line_length = fb_fix.line_length;
    bpp = fb_var.bits_per_pixel;
    screen_size = line_length * fb_var.yres;
    width = fb_var.xres;
    height = fb_var.yres;

    /* 将显示缓冲区映射到进程地址空间 */
    screen_base = mmap(NULL, screen_size, PROT_WRITE, MAP_SHARED, fd, 0);
    if (MAP_FAILED == (void *)screen_base) {
      perror("mmap error");
      close(fd);
      exit(EXIT_FAILURE);
    }

    /* 显示BMP图片 */
    memset(screen_base, 0xFF, screen_size);//屏幕刷白
    show_png_image(argv);

    /* 退出 */
    munmap(screen_base, screen_size);//取消映射
    close(fd);//关闭文件
    exit(EXIT_SUCCESS);    //退出进程
}

编写流程和上面先容的libpng 使用阐明一致



[*] 使用的是 high-level
接口处理方式
[*] 解码得到的数据是 RGB888 格式,需要转换为 RGB565 格式
[*] 转换后的数据刷入显存中举行表现
编译代码



[*]${CC} -o testApp testApp.c -I/home/alientek/tools/png/include -L/home/alientek/tools/png/lib -L/home/alientek/tools/zlib/lib -
lpng -lz
实验测试



[*] 看到打印出了一些告诫信息,缘故原由是新版本的 libpng 加强了检查,发出了告诫;不影响
我们的使用,可以忽略

[*]


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 在 LCD 上表现 png 图片-I.MX6U嵌入式Linux C应用编程学习笔记基于正点原子