Trouble writing PNGs with 16 bits per channel using libpng

Member
Posts: 22
Joined: 2006.04
Post: #1
I've been working on a more sophisticated height map implementation (hopefully on the way to proper bump mapping) and I've been using PNGs with the red channel as the height data and the green, blue and alpha channels as the x,y and z components of the normals for each vertex.

I wrote a program to read in an image, calculate the normals and write out such a PNG. I got it all working using 8bit precision and it looks ok, but not as good as calculating the normals in the rendering program at higher precision. So I converted my program to use a 16bit colour depth and it works up til writing out the PNG at which point gdb says:

mi_cmd_stack_list_frames: Not enough frames in stack.

This is in png_malloc when in png_create_write_struct2 it seems.

I'm using a test image of 16x16 (the 8bit program works with 512x512 ) so I find it hard to believe there really isn't enough space on the stack, butI'd freely admit I don't really understand what's going on.

My write function is here:

Code:
bool PNGLoader::writePNG16File(const string file_name, short* image_data, int width, int height, int bits_per_channel)
{
    if(bits_per_channel!=16)
    {
#ifdef IVORDEBUG_PNG
        printf("PNGLoader:writePNGFile: bits per channel must be 8 or 16!\n", file_name.c_str());
#endif
        return false;
    }
    
    // open file
    FILE *fp = fopen(file_name.c_str(), "wb");
    if (!fp)
    {
#ifdef IVORDEBUG_PNG
        printf("PNGLoader:writePNGFile: File %s could not be opened for writing.\n", file_name.c_str());
#endif
        fclose(fp);
        return false;
    }
    
    write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!write_ptr)
    {
#ifdef IVORDEBUG_PNG
        cout <<"PNGLoader:writePNGFile: write_ptr not created.\n";
#endif
        fclose(fp);
        return false;
    }
    info_ptr = png_create_info_struct(write_ptr);
    if (!info_ptr)
    {
        png_destroy_write_struct(&write_ptr, (png_infopp)NULL);
#ifdef IVORDEBUG_PNG
        printf("PNGLoader:writePNGFile: could not create info_ptr.\n", file_name.c_str());
#endif
        fclose(fp);
        return false;
    }
    
    if (setjmp(png_jmpbuf(write_ptr)))
    {     // on an error libpng needs to know where to jump back to
#ifdef IVORDEBUG_PNG
        printf("PNGLoader:writePNGFile: Error during init_io");
#endif
        fclose(fp);
        return false;
    }
    
    png_init_io(write_ptr, fp);
    
       /* turn on or off filtering, and/or choose
        specific filters.  You can use either a single
        PNG_FILTER_VALUE_NAME or the logical OR of one
        or more PNG_FILTER_NAME masks. */
    png_set_filter(write_ptr, 0, PNG_FILTER_NONE);
    
    // set the zlib compression level
    png_set_compression_level(write_ptr, Z_BEST_COMPRESSION);
    
    png_set_IHDR(write_ptr, info_ptr, width, height,
                 bits_per_channel, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
                 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
    
    row_pointers = (png_byte**) png_malloc(write_ptr, height*sizeof(png_bytep));
    for (int i=0; i<height; i++)
        row_pointers[i]= (png_byte*) png_malloc(write_ptr, width*4*sizeof(short));
    
    // flips image vertically - back from how opengl likes it
    for(int i=0;i<height;i++)
        for(int j=0;j<width*4;j++)
        {
            row_pointers[height-i-1][j] = image_data[(i*width*4+j)*sizeof(short)];
        }
            png_set_rows(write_ptr, info_ptr, row_pointers);
    
    png_write_png(write_ptr, info_ptr, PNG_TRANSFORM_SWAP_ENDIAN, NULL);    // PNG_TRANSFORM_SWAP_ENDIAN
    
    
#ifdef IVORDEBUG_PNG
    cout << "PNG Written\n";
#endif
    return true; // success    
}

Any help most appreciated - sorry for the rather long post.

Flash!
Quote this message in a reply
Member
Posts: 87
Joined: 2006.08
Post: #2
Post the code that calls this function. Specifically, how do you allocate the buffer pointed to by image_data?
Quote this message in a reply
Member
Posts: 22
Joined: 2006.04
Post: #3
I actually got it working - I was overrunning an array way back in the code. Now it seems I'm not getting all 16 bits when I read a PNG. I'll just have to keep hacking I suppose...

Flash!
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  libPng And Memory Access Violations Jaden 12 12,734 Sep 4, 2013 04:50 AM
Last Post: miye
  OpenGL Alpha Channel Problem Moganza 1 3,297 Jan 19, 2013 08:25 AM
Last Post: sealfin
  writing a rasterizer NelsonMandella 4 3,606 Jun 2, 2009 07:02 PM
Last Post: NelsonMandella
  libpng loading junk at bottom of my OpenGL textures...? BinarySpike 6 6,306 Apr 19, 2007 12:20 PM
Last Post: BinarySpike
  libpng transparency problem wyrmmage 3 5,494 Mar 1, 2007 05:53 PM
Last Post: OneSadCookie