【问题标题】:How should I use libpng library to convert RGBA bitmap into PNG and PNG back to RGBA bitmap我应该如何使用 libpng 库将 RGBA 位图转换为 PNG 并将 PNG 转换回 RGBA 位图
【发布时间】:2017-02-10 11:26:27
【问题描述】:

我尝试使用 libpng 库,但遇到了问题。

我现在正在使用 CLion,并尝试在我的项目中包含这个 libpng 库。 问题在于配置这个库以在我的项目中使用它,而不是使用这个库。我认为我可以将 libpng 中的所有 *.c、*.h 文件复制到我自己在 CLion 中的项目中,从中创建静态库 liblibpng.a 并链接它。我什至编译了 liblibpng.a 但是当我尝试使用它时,即简单的包括 ${path}/libpng-x.x.x/png.h 在 png.h 文件中存在错误和警告,例如缺少 png_uint_32 定义。好的,我可以像unsigned int 一样输入定义。

我正在尝试阅读 README.txt 和其他手册/文档 INSTALL.txt?但是有很多操作系统的可能性,我只想在我的项目中包含 png 功能。为什么需要安装这个库?我希望我的应用程序在将来创建后可以轻松移植到其他计算机,而根本不需要安装 3rd 方库。

我的问题是很容易开始使用这个 libpng,可能还有我自己的 CMake 项目中的 zlib 库,我更喜欢静态库链接,我不想要任何特定的安装等。

我认为我的这个声明有问题,因为这个而不是定义 png_uint_32 只是抛出错误!它来自 pngconf.h

#if UINT_MAX > 4294967294
   typedef unsigned int png_uint_32;
#elif ULONG_MAX > 4294967294
   typedef unsigned long int png_uint_32;
#else
#  error "libpng requires an unsigned 32-bit (or more) type"
#endif

【问题讨论】:

标签: c zlib libpng


【解决方案1】:

简短的回答,只需使用 lodepng。它使用起来比 libpng 简单得多,而且它采用单一来源,因此您不必为链接和设置包含路径而烦恼。

长答案

/*
   write an rgba image to a memory buffer in PNG format, without any fanciness.

   Params: rgba - the rgba values
       width - image width
       height - image height
       outsize - return for size of output buffer
   Returns: pointer to allocated buffer holding png data
*/
void *makePNGBuffer(unsigned char *rgba, int width, int height, size_t *outsize)
{
    int code = 0;
    // FILE *fp;
    png_structp png_ptr = 0;
    png_infop info_ptr =0;
    png_bytep row = 0;

    struct mem_encode state = {0, 0};

    *outsize = 0;

  // Initialize write structure
    png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (png_ptr == NULL) {
        fprintf(stderr, "Could not allocate write struct\n");
    code = 1;
    goto finalise;
    }

// Initialize info structure
    info_ptr = png_create_info_struct(png_ptr);
    if (info_ptr == NULL) {
       fprintf(stderr, "Could not allocate info struct\n");
       code = 1;
       goto finalise;
   }

   // Setup Exception handling
    if (setjmp(png_jmpbuf(png_ptr))) {
       fprintf(stderr, "Error during png creation\n");
        code = 1;
        goto finalise;
    }

    // png_init_io(png_ptr, fp);

    /* if my_png_flush() is not needed, change the arg to NULL */
    png_set_write_fn(png_ptr, &state, my_png_write_data, my_png_flush);

    // Write header (8 bit colour depth)
    png_set_IHDR(png_ptr, info_ptr, width, height,
             8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
             PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);

    // Set title
    /*
     if (title != NULL) {
     png_text title_text;
     title_text.compression = PNG_TEXT_COMPRESSION_NONE;
     title_text.key = "Title";
     title_text.text = title;
     png_set_text(png_ptr, info_ptr, &title_text, 1);
     }
     */

    png_write_info(png_ptr, info_ptr);

    // Allocate memory for one row (3 bytes per pixel - RGB)
    row = (png_bytep) malloc(4 * width * sizeof(png_byte));

    // Write image data
    int x, y;
    for (y=0 ; y<height ; y++) {
        for (x=0 ; x<width ; x++) {
            //  setRGB(&(row[x*3]), buffer[y*width + x]);
            row[x*4] = rgba[(y*width +x)*4];
            row[x*4+1] = rgba[(y*width +x)*4+1];
            row[x*4+2] = rgba[(y*width +x)*4+2];
            row[x*4+3] = rgba[(y*width +x)*4+3];
        }
        png_write_row(png_ptr, row);
    }

    // End write
    png_write_end(png_ptr, NULL);

finalise:
    // if (fp != NULL) fclose(fp);
    if (info_ptr != NULL) png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
    if (png_ptr != NULL) png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
    if (row != NULL) free(row);

    *outsize = state.size;
    return state.buffer;

    }

【讨论】:

  • 你能添加反向吗?要编译和使用 libpng,我必须更改 #if UINT_MAX > 4294967294 typedef unsigned int png_uint_32;进入 #if UINT_MAX > 0xffffffffe typedef unsigned int png_uint_32;
  • @MichałZiobro 在什么平台上你需要这样做?
  • 在 OS X El Capitan 上
【解决方案2】:

什么是错误?

ANSI-C(又名 ISO C90)要求 ULONG_MAX 的值大于或等于 4294967295,因此很明显,与 4294967294 的比较在 ANSI 编译器上总是成功的,而且显然由于标准完全使用该十进制字符串,因此编译器少一号有问题的不是 ANSI-C 编译器。

约翰·鲍勒

【讨论】:

    【解决方案3】:

    请尝试在 pngconf.h 中通过在末尾添加一个“U”来使那些大整数无符号:

    if UINT_MAX > 4294967294U
       typedef unsigned int png_uint_32;
    #elif ULONG_MAX > 4294967294U
       typedef unsigned long int png_uint_32;
    #else
    

    可能是在您的平台上 4294967294 不能表示为有符号整数,因此由于未定义数字,第一次比较失败。

    【讨论】:

      猜你喜欢
      • 2021-03-08
      • 1970-01-01
      • 1970-01-01
      • 2012-02-28
      • 2011-12-20
      • 1970-01-01
      • 1970-01-01
      • 2011-04-13
      • 1970-01-01
      相关资源
      最近更新 更多