Michał Ziobro Michał Ziobro - 2 months ago 12
C Question

How should I use libpng library to convert RGBA bitmap into PNG and PNG back to RGBA bitmap

I try to use libpng library, and I encounter problem with it.

I am using CLion now, and try to include this libpng library in my project.
The problem is rather with configuration of this library to use it in my project than using this library. I think that I can make copy all *.c, *.h files from libpng into my own project in CLion, make from it static library liblibpng.a and just link against it. I even compiled liblibpng.a but when I try to use it, i.e. simple including ${path}/libpng-x.x.x/png.h there are errors and warnings in the png.h file like lack of

png_uint_32
definition. Ok I can typedefine this somehow like
unsigned int
.

I am trying to read README.txt, and other manuals/documantations, INSTALL.txt? But there is a lot os possibilities, and I just want to include png functionalities in my project. Why there is need to install this library? I want that my app after creation in the future will be easly portable to other computers without 3rd party libraries installation needed at all.

My question is hot to easily start using this libpng, and porbably also zlib libraries in my own project in CMake, I prefer static library linking, I don't want any specific installation, etc.

I think I have a problem with this declaration as this instead of defining
png_uint_32
just throw error! It is from 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

Answer

Short answer, just use lodepng. It's a lot simpler to use than libpng and it comes in a single source, so you don't have to mess about with linking and setting up include paths.

Long answer

/*
   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;

    }
Comments