功能描述

  • 使用libpng库,在lcd屏上显示png图像。

实践要点

libpng移植

  • PNG是一种采用无损压缩算法的位图格式。
  • zlib是一套包含了数据压缩算法的函数库,libpng依赖于zlib库。移植libpng要先移植zlib库。

移植过程

  1. 下载源码,地址:https://github.com/glennrp/libpng/releases

  2. 编译源码,以libpng-1.6.35

    tar -xvf libpng-1.6.35.tar.gz
    cd libpng-1.6.35
    mkdir build
    source /opt/fsl-imx-x11/4.1.15-2.1.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi 
    export LDFLAGS="${LDFLAGS} -Lyourpath/zlib-1.2.10/build/lib"
    export CFLAGS="${CFLAGS} -Iyourpath/zlib-1.2.10/build/include"
    export CPPFLAGS="${CPPFLAGS} -Iyourpath/zlib-1.2.10/build/include"
    ./configure --prefix=yourpath/libpng-1.6.35/build --host=arm-poky-linux-gnueabi
    make
    make install
  3. 移植libpng,将生成的lib拷贝到开发板的/usr/lib目录下。

zlib移植

移植过程

  1. 下载源码,地址:https://www.zlib.net/fossils

  2. 编译源码,以zlib-1.2.10为例

    tar -xvf zlib-1.2.10.tar.gz
    cd zlib-1.2.10
    mkdir build
    source /opt/fsl-imx-x11/4.1.15-2.1.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi 
    ./configure --prefix=yourpath/zlib-1.2.10/build
    make
    make install

    这里提供上述使用的交叉编译器的下载链接:

    链接:https://pan.baidu.com/s/1K5mT3AzXKGUar2cZZfwnFA 
    提取码:ta2a 
  3. zlib移植,把生成的lib拷贝到开发板对应的目录下,即/usr/lib中。

PNG解码流程&关键代码

  1. 创建和初始化png_struct对象

    png_struct png_ptr = NULL;       //定义在中
    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if(!png_ptr)
       return -1;
  2. 创建和初始化png_info对象

    png_infop info_ptr = NULL;       //png_info数据结构体描述了png图像的信息
    info_ptr = png_create_info_struct(png_const_structrp png_ptr);
    if(info_ptr == NULL) {
       png_destroy_read_struct(&png_ptr, NULL, NULL);
       return -1;
    }
  3. 设置错误返回点

    • libpng库默认使用setjmp/longjmp这两个库函数组合来处理发生错误时的跳转,当libpng遇到错误时,执行默认错误处理函数,默认错误处理函数会调用longjpm来进行跳转。
    if(setjmp(png_jmpbuf(png_ptr))) {
       png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
       return -1;
    }
    • setjmp/longjmp

      在C语言中,在一个函数中执行跳转,可以使用goto语句。如果想实现跨越函数的跳转,在linux下,可以使用库函数setjmp和longjmp。

      • setjmp用来设置跳转点,setjmp初始调用时返回值为0,可以用此来区分是初始调用还是跳转返回。
      • longjmp用来执行跳转,会跳转到setjmp所设置的跳转点。
  4. 指定数据源

    png_init_io(png_structrp png_ptr, png_FILE_p fp);    //png_FILE_p为png图像文件的文件指针
  5. 读取png图像数据并解码

    png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_ALPHA, NULL);
    imageH = png_get_image_height(png_ptr, info_ptr);
    imageW = png_get_image_width(png_ptr, info_ptr);
    printf("分辨率:%d * %d\n", imageW, imageH);
  6. 读取解码后的数据

    png_bytepp row_pointers = NULL;
    row_pointers = png_get_rows(png_ptr, info_ptr);  //数据保存在row_pointers中,然后就可以把数据写入LCD屏幕缓冲了
  7. 结束销毁对象

    png_destroy_read_struct(png_ptr, info_ptr, NULL);

附录

说点什么
请文明发言!
支持Markdown语法
好耶,沙发还空着ヾ(≧▽≦*)o
Loading...