测试libpng-1.6.37(静态库,对应的zlib-1.2.11)

博客指出libpng和zlib是静态库,在链接时若顺序不当会报错。原因是链接器处理静态库有特殊规则,仅在需要时包含.o文件且按链接行顺序处理。代码未直接调用zlib函数,若先处理-lz则不会引入zlib,修改链接顺序可解决问题。

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

libpng和zlib都是静态库的。

测试代码如下:

#define _CRT_SECURE_NO_WARNINGS

#include <stdio.h>
#include <stdlib.h>
//#include <string>
//#include <memory>
#include <string.h>

//#include <pngconf.h>


//#define PNG_feature_SUPPORTED
//#define PNGLCONF_H
//#include <zlib.h>
#include <png.h>

#define PNG_BYTES_TO_CHECK 4

/*
fun:    读取文件名为filepath的png文件
return: png_bytep类型的buff,即数据域
arg[0]: filepath,文件名
arg[1]: width,图像宽度
arg[2]: height,图像高度
*/
png_bytep load_png_image(const char *filepath, int *width, int *height)
{
    FILE *fp;
    png_structp png_ptr;
    png_infop info_ptr;
    png_bytep* row_pointers;
    char buf[PNG_BYTES_TO_CHECK];
    int w, h, x, y, temp, color_type;

    fp = fopen(filepath, "rb");
    if (fp == NULL) {
        printf("load_png_image err:fp == NULL");
        return 0;
    }

    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
    info_ptr = png_create_info_struct(png_ptr);

    setjmp(png_jmpbuf(png_ptr));
    /* 读取PNG_BYTES_TO_CHECK个字节的数据 */
    temp = fread(buf, 1, PNG_BYTES_TO_CHECK, fp);
    /* 若读到的数据并没有PNG_BYTES_TO_CHECK个字节 */
    if (temp < PNG_BYTES_TO_CHECK) {
        fclose(fp);
        png_destroy_read_struct(&png_ptr, &info_ptr, 0);
        printf("load_png_image err:读到的数据并没有PNG_BYTES_TO_CHECK个字节");
        return 0;
    }
    /* 检测数据是否为PNG的签名 */
    temp = png_sig_cmp((png_bytep)buf, (png_size_t)0, PNG_BYTES_TO_CHECK);
    /* 如果不是PNG的签名,则说明该文件不是PNG文件 */
    if (temp != 0) {
        fclose(fp);
        png_destroy_read_struct(&png_ptr, &info_ptr, 0);
        printf("load_png_image err:不是PNG的签名");
        return 0;
    }

    /* 复位文件指针 */
    rewind(fp);
    /* 开始读文件 */
    png_init_io(png_ptr, fp);
    /* 读取PNG图片信息和像素数据 */
    png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_EXPAND, 0);
    /* 获取图像的色彩类型 */
    color_type = png_get_color_type(png_ptr, info_ptr);

    /* 获取图像的宽高 */
    w = png_get_image_width(png_ptr, info_ptr);
    h = png_get_image_height(png_ptr, info_ptr);
    *width = w;
    *height = h;

    /* 分配空间buff,保存像素数据 */
    png_bytep buff = (png_bytep)malloc(h * w * 3 * sizeof(png_byte));
    memset(buff, 0, (h * w * 3 * sizeof(png_byte)));

    /* 获取图像的所有行像素数据,row_pointers里边就是rgba数据 */
    row_pointers = png_get_rows(png_ptr, info_ptr);

    /* 根据不同的色彩类型进行相应处理 */
    switch (color_type) {
    case PNG_COLOR_TYPE_RGB_ALPHA:
        for (y = 0; y<h; ++y)
        {
            for (x = 0; x<w * 4;)
            {
                ///* 以下是RGBA数据,需要自己补充代码,保存RGBA数据 */
                ///* 目标内存 */ = row_pointers[y][x++]; // red
                ///* 目标内存 */ = row_pointers[y][x++]; // green
                ///* 目标内存 */ = row_pointers[y][x++]; // blue
                ///* 目标内存 */ = row_pointers[y][x++]; // alpha
                ///
                ///
                ///
                //printf("处理RGBA\n");
            }
        }

        break;

    case PNG_COLOR_TYPE_RGB:
        for (y = 0; y<h; y++)
        {
            for (x = 0; x<w; x++)
            {
                buff[y*w + 3 * x + 0] = row_pointers[y][3 * x + 0];
                buff[y*w + 3 * x + 1] = row_pointers[y][3 * x + 1];
                buff[y*w + 3 * x + 2] = row_pointers[y][3 * x + 2];
                printf("%x,%x,%x  ", buff[y*w + 3 * x + 0], buff[y*w + 3 * x + 1], buff[y*w + 3 * x + 2]);
                //printf("%x,%x,%x  ", buff[y*w + 3 * x + 0], buff[y*w + 3 * x + 1], buff[y*w + 3 * x + 2]);
                /*printf("处理RGB\n");*/
            }
            //printf("\n");
        }
        //printf("\n");
        break;
        /* 其它色彩类型的图像就不读了 */
    default:
        fclose(fp);
        png_destroy_read_struct(&png_ptr, &info_ptr, 0);
        printf("default color_type:close\n");
        return 0;
    }
    png_destroy_read_struct(&png_ptr, &info_ptr, 0);
    return buff;
}



int main()
{
    char *path = "D:/pic/pic1.png";
    int width = 0;
    int height = 0;
    png_bytep buff = load_png_image(path, &width, &height);
    if (!buff)
    {
        printf("load_png_image(filepath) erro");
    }
    printf("width:%d, height:%d\n", width, height);

    /*int i = 0, j = 0;
    for (i = 0; i < height; i++)
    {
        for (j = 0; j < width; j++)
        {
            printf("%x,%x,%x  ", buff[i*width + 3 * j + 0], buff[i*width + 3 * j + 1], buff[i*width + 3 * j + 2]);
        }
        printf("\n");
    }*/

    system("pause");

    return 0;
}

 

但是,如果link是以下:

就会报错:

原因是libpng到libz的连接顺序不能变。具体解释

You need to rearrange the order of the libraries:

-lpng -ljpeg -lz

What is happening is that the linker has special rules on how it treats static libraries. What it does is that it only includes a .o from inside the .a if the .o is needed to satisfy a reference.

Furthermore, it handles static archives in the order in which they appear on the link line.

So, your code does not directly call any functions in zlib. So when the linker handles -lz first, there are not yet any calls to it so it doesn't pull in any of zlib.

Next, when the linker handles libpng, it sees that there are calls to it from your code. So it pulls the code from libpng and since it makes calls to zlib, now there are references to the zlib functions.

Now you come to the end of your libraries and there are unsatisfied calls which causes your error.

So, if libhigh.a makes use of liblow.a, you must have -lhigh before -llow in your link order.

https://stackoverflow.com/questions/2395355/linking-with-libpng-zlib

修改为

就可以了。

多谢,亲爱的美美。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值