如何使用 ligpng 库进行图片解码应用开发openwrt linux sdd20x平台

本文介绍了libpng库的基本概念,它是用于处理PNG图像格式的跨平台开源库。详细讲解了如何在项目中引入库和头文件,以及解码PNG文件的过程,包括文件操作、初始化结构体、获取图像信息和转换数据格式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

如何使用 libpng 库进行图片解码应用开发。


一、libpng是什么?

libpng是一个开源的、跨平台的图像处理库,用于处理和支持PNG(Portable Network Graphics)图像格式。PNG是一种无损压缩的图像格式,广泛用于互联网上的图像传输和存储。libpng提供了一系列的API和函数,使开发者可以在自己的应用程序中读取、写入和操作PNG图像文件。libpng还支持处理其他常见图像格式,如BMP和JPEG。它是一个功能强大且使用广泛的图像处理库,被许多软件和应用程序所使用。png相对其他格式可以保存设透明度信息。

二、使用步骤

1.引入库及头文件

make 文件添加对应的库文件:

#png-lib
LIBS+= $(DIR_PRJ)/miniPrinter/lib/png/lib/libpng16.a
LIBS+= $(DIR_PRJ)/miniPrinter/lib/png/lib/libz.a

引入头文件

#include "png.h"            //解码库文件
#include "pngconf.h"        //解码库文件
#include "pnglibconf.h"     //解码库文件

2.解码过程

代码如下:

int decode_png(char* name)
{
    static struct timeval start_time, stop_time;
    int i, j;
    int m_width, m_height;
    png_infop info_ptr;             //图片信息的结构体
    png_structp png_ptr;         //初始化结构体,初始生成,调用api时注意传入

    FILE* file = fopen(name, "rb");    //打开的文件名
    printf("%s, %d\n", __FUNCTION__, __LINE__);
    if(file==0) 
    {
        printf("%s, %d,%s open faile \n", __FUNCTION__, __LINE__, name);
        return -1;
    }

    gettimeofday(&start_time, NULL); //获取时间

    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);   //创建初始化libpng库结构体
    info_ptr = png_create_info_struct(png_ptr);                                                 //创建图片信息结构体
    setjmp(png_jmpbuf(png_ptr));                              //设置错误的返回点
    // 这句很重要
    png_init_io(png_ptr, file);         //把文件加载到libpng库结构体中
    // 读文件了
    png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, 0);        //读文件内容到info_ptr中

    gettimeofday(&stop_time, NULL); //获取时间
    printf("decode_png time:%d ms\n", stop_time.tv_usec/1000 - start_time.tv_usec/1000);
    

    // 得到文件的宽高色深
    if ((png_ptr != NULL) && (info_ptr != NULL))
    {
        m_width = png_get_image_width(png_ptr, info_ptr);
        m_height = png_get_image_height(png_ptr, info_ptr);                          //通过png库中的api获取图片的宽度和高度
        printf("%s, %d, m_width =%d, m_height = %d\n", __FUNCTION__, __LINE__, m_width, m_height);
        
    }
    int color_type = png_get_color_type(png_ptr, info_ptr);                          //通过api获取color_type
    printf("%s, %d, color_type = %d\n", __FUNCTION__, __LINE__, color_type);
    int bit_depth = png_get_bit_depth(png_ptr,info_ptr);
    printf("%s, %d, bit_depth = %d\n", __FUNCTION__, __LINE__, bit_depth);

    int bitNum = bit_depth;
    if( color_type )bitNum *= ((color_type & PNG_COLOR_MASK_COLOR)?3:0) + ((color_type & PNG_COLOR_MASK_ALPHA)?1:0);
    bitNum = bitNum / 8;
    printf("%s, %d, bitNum = %d\n", __FUNCTION__, __LINE__, bitNum);



    int size = m_height * m_width * bitNum;
     unsigned char* bgra = NULL;
    bgra = (unsigned char*)malloc(size);
    if (NULL == bgra)
    {
         printf("%s, %d, bgra == NULL\n", __FUNCTION__, __LINE__);
         return NULL;
    }
    int pos = 0;
    // row_pointers里边就是传说中的rgb数据了
    png_bytep* row_pointers = png_get_rows(png_ptr, info_ptr);
    // 拷贝!!注意,如果你读取的png没有A通道,就要3位3位的读。还有就是注意字节对其的问题,最简单的就是别用不能被4整除的宽度就行了。读过你实在想用,就要在这里加上相关的对齐处理。
    int byteNum;
    char bytes;
    for (i = 0; i < m_height; i++)
    {
        
        for (j = 0; j < (bitNum * m_width); j += bitNum)
        {
#if 1            
            bgra[pos++] = row_pointers[i][j + 2]; // blue
            bgra[pos++] = row_pointers[i][j + 1]; // green
            bgra[pos++] = row_pointers[i][j];   // red
            bgra[pos++] = row_pointers[i][j + 3]; // alpha
            // printf("%s, b:%d, g:%d, r:%d, a:%d\n", __FUNCTION__, 
            // row_pointers[i][j + 2],  row_pointers[i][j + 1],row_pointers[i][j],row_pointers[i][j + 3]);
#endif             

        }
    }

 #if 1  
    char tmp[10] = { 0 };
    //保存rgb裸流文件咯,省时省力
    FILE* f = fopen("save-png.bin", "wb");
#if 1
    for (i = 0; i < size; i++)
    {
        // printf("%s, %d, bgra[%d] = %d\n", __FUNCTION__, __LINE__,  i, bgra[i]);
        sprintf(tmp, "0x%x,", bgra[i]);
        fwrite(tmp, strlen(tmp), 1, f);

    }
#endif 
    fwrite(bgra, size, 1, f);
    fclose(f);
#endif 

    png_destroy_read_struct(&png_ptr, &info_ptr, 0);
    fclose(file);
    return 0;
}

解码生成的格式是rgb格式并不能直接读取。如果要看效果可以通过以下在线工具进行查看
https://imagetostl.com/cn/view-rgba-online


总结

要注意这里使用libz.a,否则编译不过的。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ruihuan_2000

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值