我应该如何使用libpng库将RGBA位图转换为PNG和PNG返回RGBA位图

时间:2016-10-02 10:21:47

标签: c zlib libpng

我尝试使用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功能。为什么需要安装此库?我希望将来创建后我的应用程序可以轻松移植到其他计算机,而无需安装第三方库。

我的问题很热,很容易开始使用这个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

3 个答案:

答案 0 :(得分:3)

简短的回答,只需使用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;

    }

答案 1 :(得分:0)

错误是什么?

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

John Bowler

答案 2 :(得分:0)

请尝试通过放置&#34; U&#34;来使pngconf.h中的大整数无符号化。最后:

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

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