Trouble writing PNGs with 16 bits per channel using libpng
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:
Any help most appreciated - sorry for the rather long post.
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!
Post the code that calls this function. Specifically, how do you allocate the buffer pointed to by image_data?
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!
Possibly Related Threads...
| Thread: | Author | Replies: | Views: | Last Post | |
| OpenGL Alpha Channel Problem | Moganza | 1 | 1,419 |
Jan 19, 2013 08:25 AM Last Post: sealfin |
|
| libpng loading junk at bottom of my OpenGL textures...? | BinarySpike | 6 | 5,043 |
Apr 19, 2007 12:20 PM Last Post: BinarySpike |
|
| libpng transparency problem | wyrmmage | 3 | 4,240 |
Mar 1, 2007 05:53 PM Last Post: OneSadCookie |
|
| libPng And Memory Access Violations | Jaden | 8 | 7,258 |
Feb 23, 2007 11:01 PM Last Post: AnotherJake |
|
| libpng with OpenGL : return what? | Jones | 3 | 3,469 |
May 28, 2006 07:32 AM Last Post: Jones |
|

