Sign in to follow this  
BraXi

libpng crash

Recommended Posts

Hello, it's my first post hereand im not sure if i've choosen correct forum but i decided to post it here anyway.
I've replaced TGA loader in my game with [b]libpng 1.2.37[/b] as i think PNG is much better format and soon i've found problem with code. I have copied code from here [url="http://en.wikibooks.org/wiki/OpenGL_Programming/Intermediate/Textures"]http://en.wikibooks....ediate/Textures[/url] , included all libs and headers in project and succesfully compiled the code without any errors and warnings but now my game seems to crash at:
[source lang="cpp"] // read all the info up to the image data
png_read_info(png_ptr, info_ptr);[/source]

I though that invalid PNG file was causing the problem so i tried to load pngs included with libpng but it didnt work either.
Does anybody know how to fix that issue? Any help appericated [img]http://public.gamedev.net//public/style_emoticons/default/smile.png[/img]


I'm attaching code here:

[source lang="cpp"] MaterialDef mtl = createMaterial( fileName, fileName, 0, 0, 0, 0, 0 );
mtl.num = loadImage( fileName, mtl.width, mtl.height );
[...........]

#define TEXTURE_LOAD_ERROR 0 //default texture ID
GLuint MaterialManager::loadImage( char fileName[128], int &width, int &height )
{
//http://en.wikibooks.org/wiki/OpenGL_Programming/Intermediate/Textures
//header for testing if it is a png
png_byte header[8];

//open file as binary
FILE *fp = fopen( fileName, "rb" );
if (!fp)
{
Com.warning( "loadImage: failed to open %s", fileName );
return TEXTURE_LOAD_ERROR;
}

//read the header
fread(header, 1, 8, fp);

//test if png
int is_png = !png_sig_cmp(header, 0, 8);
if (!is_png)
{
Com.warning( "loadImage: %s is not an PNG", fileName );
fclose(fp);
return TEXTURE_LOAD_ERROR;
}

//create png struct
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr)
{
Com.warning( "loadImage: png_create_read_struct failed for %", fileName );
fclose(fp);
return TEXTURE_LOAD_ERROR;
}

//create png info struct
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr)
{
Com.warning( "loadImage: png_create_info_struct(info_ptr) failed for %", fileName );
png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
fclose(fp);
return TEXTURE_LOAD_ERROR;
}

//create png info struct
png_infop end_info = png_create_info_struct(png_ptr);
if (!end_info)
{
Com.warning( "loadImage: png_create_info_struct(end_info) failed for %", fileName );
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
fclose(fp);
return TEXTURE_LOAD_ERROR;
}

//png error stuff, not sure libpng man suggests this.
if( setjmp(png_jmpbuf(png_ptr)) )
{
Com.warning( "loadImage: setjmp(png_jmpbuf(png_ptr)) caused by %", fileName );
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
fclose(fp);
return TEXTURE_LOAD_ERROR;
}

//init png reading
png_init_io(png_ptr, fp);

//let libpng know you already read the first 8 bytes
png_set_sig_bytes(png_ptr, 8);


// read all the info up to the image data
png_read_info(png_ptr, info_ptr); // THIS CAUSES APP TO CRASH

//variables to pass to get info
int bit_depth, color_type;
png_uint_32 twidth, theight;


// get info about png
png_get_IHDR(png_ptr, info_ptr, &twidth, &theight, &bit_depth, &color_type,
NULL, NULL, NULL);


//update width and height based on png info
width = twidth;
height = theight;

// Update the png info struct.
png_read_update_info(png_ptr, info_ptr);

// Row size in bytes.
int rowbytes = png_get_rowbytes(png_ptr, info_ptr);

// Allocate the image_data as a big block, to be given to opengl
png_byte *image_data = new png_byte[rowbytes * height];
if (!image_data)
{
//clean up memory and close stuff
Com.warning( "loadImage: failed to allocate memory for %", fileName );
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
fclose(fp);
return TEXTURE_LOAD_ERROR;
}

//row_pointers is for pointing to image_data for reading the png with libpng
png_bytep *row_pointers = new png_bytep[height];
if (!row_pointers)
{
Com.warning( "loadImage: failed to allocate memory for %", fileName );
//clean up memory and close stuff
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
delete[] image_data;
fclose(fp);
return TEXTURE_LOAD_ERROR;
}

// set the individual row_pointers to point at the correct offsets of image_data
for (int i = 0; i < height; ++i)
row_pointers[height - 1 - i] = image_data + i * rowbytes;

//read the png into image_data through row_pointers
png_read_image(png_ptr, row_pointers);

//Now generate the OpenGL texture object
GLuint texture;
glGenTextures(1, &texture);
glBindTexture( GL_TEXTURE_2D, texture );
glTexImage2D(GL_TEXTURE_2D,0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) image_data);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );

//clean up memory and close stuff
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
delete[] image_data;
delete[] row_pointers;
fclose(fp);

return texture;
}[/source]

Edit: I'm using Visual C++ 2005 Express, GLFW, GLEW and Windows XP SP3. Edited by BraXi

Share this post


Link to post
Share on other sites
I can't help you directly with your problem, but I remember having trouble compiling the libpng library (to use with SDL) under different Linux versions because of the "setjmp" call that got deprecated. They fixed it in a future revision and just updating fixed it. Maybe you could try the same thing since you mentioned using 1.2.37 and they are currently at 1.5.10 which is a big difference.

Share this post


Link to post
Share on other sites
[quote name='Dunge' timestamp='1339523390' post='4948575']
I can't help you directly with your problem, but I remember having trouble compiling the libpng library (to use with SDL) under different Linux versions because of the "setjmp" call that got deprecated. They fixed it in a future revision and just updating fixed it. Maybe you could try the same thing since you mentioned using 1.2.37 and they are currently at 1.5.10 which is a big difference.
[/quote]

Thanks for pointing me into good direction. I will try latest version of libpng.

Share this post


Link to post
Share on other sites
Sorry for double posting but it seems that libpng 1.5.10 and zlib 1.2.7 don't solve the problem. Now im a bit worried.
The problem must be in loading code but im not sure what causes png_read_info(png_ptr, info_ptr); to crash.

Share this post


Link to post
Share on other sites
Try this instead:
[source lang="cpp"]png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);[/source]
It's what I use in my texture loading code, which is almost identical up to the point of crash.

Share this post


Link to post
Share on other sites
[quote name='Firestryke31' timestamp='1339531104' post='4948616']
Try this instead:
[source lang="cpp"]png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);[/source]
It's what I use in my texture loading code, which is almost identical up to the point of crash.
[/quote]
Thanks, this fixed crash but now i get this:
[img]http://s6.ifotos.pl/img/pngerrJPG_rsheqqa.JPG[/img]


setjmp is called at this moment:
[source lang="cpp"]png_read_image(png_ptr, row_pointers);[/source]

This is source code, again..:
[source lang="cpp"]#define TEXTURE_LOAD_ERROR 1
GLuint MaterialManager::loadImage( char fileName[128], int &width, int &height )
{
//http://en.wikibooks.org/wiki/OpenGL_Programming/Intermediate/Textures
//header for testing if it is a png
png_byte header[8];

//open file as binary
FILE *fp = fopen( fileName, "rb" );
if (!fp)
{
Com.warning( "loadImage: failed to open %s", fileName );
return TEXTURE_LOAD_ERROR;
}

//read the header
fread(header, 1, 8, fp);

//test if png
int is_png = !png_sig_cmp(header, 0, 8);
if (!is_png)
{
Com.warning( "loadImage: %s is not an PNG", fileName );
fclose(fp);
return TEXTURE_LOAD_ERROR;
}

//create png struct
png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr)
{
Com.warning( "loadImage: png_create_read_struct failed for %", fileName );
fclose(fp);
return TEXTURE_LOAD_ERROR;
}

//create png info struct
png_infop info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr)
{
Com.warning( "loadImage: png_create_info_struct(info_ptr) failed for %", fileName );
png_destroy_read_struct(&png_ptr, (png_infopp) NULL, (png_infopp) NULL);
fclose(fp);
return TEXTURE_LOAD_ERROR;
}

//create png info struct
png_infop end_info = png_create_info_struct(png_ptr);
if (!end_info)
{
Com.warning( "loadImage: png_create_info_struct(end_info) failed for %", fileName );
png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
fclose(fp);
return TEXTURE_LOAD_ERROR;
}

//png error stuff, not sure libpng man suggests this.
if( setjmp(png_jmpbuf(png_ptr)) )
{
Com.warning( "loadImage: setjmp(png_jmpbuf(png_ptr)) for %s", fileName );
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
fclose(fp);
return TEXTURE_LOAD_ERROR;
}

//init png reading
png_init_io(png_ptr, fp);

//let libpng know you already read the first 8 bytes
png_set_sig_bytes(png_ptr, 8);

//png_read_info(png_ptr, info_ptr);
png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);

//variables to pass to get info
int bit_depth, color_type;
png_uint_32 twidth, theight;


// get info about png
png_get_IHDR(png_ptr, info_ptr, &twidth, &theight, &bit_depth, &color_type, NULL, NULL, NULL);


//update width and height based on png info
width = twidth;
height = theight;

// Update the png info struct.
png_read_update_info(png_ptr, info_ptr);

// Row size in bytes.
int rowbytes = png_get_rowbytes(png_ptr, info_ptr);

// Allocate the image_data as a big block, to be given to opengl
png_byte *image_data = new png_byte[rowbytes * height];
if (!image_data)
{
//clean up memory and close stuff
Com.warning( "loadImage: failed to allocate memory for %", fileName );
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
fclose(fp);
return TEXTURE_LOAD_ERROR;
}

//row_pointers is for pointing to image_data for reading the png with libpng
png_bytep *row_pointers = new png_bytep[height];
if (!row_pointers)
{
Com.warning( "loadImage: failed to allocate memory for %", fileName );
//clean up memory and close stuff
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
delete[] image_data;
fclose(fp);
return TEXTURE_LOAD_ERROR;
}

// set the individual row_pointers to point at the correct offsets of image_data
for (int i = 0; i < height; ++i)
row_pointers[height - 1 - i] = image_data + i * rowbytes;

//read the png into image_data through row_pointers
png_read_image(png_ptr, row_pointers); // !CODE STOPS HERE!

//Now generate the OpenGL texture object
GLuint texture;
glGenTextures(1, &texture);
glBindTexture( GL_TEXTURE_2D, texture );
glTexImage2D(GL_TEXTURE_2D,0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) image_data);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );

//clean up memory and close stuff
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
delete[] image_data;
delete[] row_pointers;
fclose(fp);


return texture;
}[/source] Edited by BraXi

Share this post


Link to post
Share on other sites
Can you create a minimal program that still shows the problem? By "minimal" I mean a program such that if you remove anything you won't reproduce the error. Post that complete program here so we can try to reproduce the error ourselves. You may have to include the .PNG file you are trying to read.

Share this post


Link to post
Share on other sites
Alvaro, your idea was brillant.
The bug wasn't exactly in png functions as everything worked well in "minimal" program. I was trying to fill width and height incorrectly which additionaly caused LibPNG to crash. I think i've solved the problem now.

Thank you all for help and i'm posting complete source code with libs for minimal png loader program (VC++2005 project, includes, libs, source code and 2 png images).
Download: http://www.sendspace.com/file/mzo1e1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this