libpng playing up...

Started by
14 comments, last by Cornstalks 10 years, 7 months ago
I'm writing a PNG loader using libpng, and I've run up against a strange problem. I've written the code correctly, so far as I can see from the example file and the tutorial provided, and it compiles fine, but it crashes when I call png_read_info(png_ptr, info_ptr); The error occurs in the file _file.c, and has something to do with locking the file, as far as I can see. The exact message is:
Unhandled exception at 0x7c918fea in ImageTest.exe: 0xC0000005: Access violation writing location 0x00000010.
My code:

FILE *fpPNG = NULL;
png_structp png_ptr = NULL;
png_infop info_ptr = NULL;
png_byte sig[8];
png_uint_32 width, height;
int bit_depth, color_type, interlace_type;

fpPNG = fopen(sFilename.c_str(), "rb");

if(!fpPNG) throw Exception("The Portable Network Graphics file \"" + sFilename + "\" could not be opened.", __FUNCTION__, __FILE__, __LINE__);

try
{
	
	// Read 8 bytes of the file, and check them...
	fread(sig, 1, sizeof(png_byte [8]), fpPNG);
	if(!png_check_sig(sig, 8)) throw Exception("The Portable Network Graphics file \"" + sFilename + "\" is not valid.", __FUNCTION__, __FILE__, __LINE_);
	
	png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, (png_error_ptr)NULL, (png_error_ptr)NULL);
	if(png_ptr == NULL) throw Exception("An error has occurred reading the Portable Network Graphics file \"" + sFilename + "\".", __FUNCTION__, __FILE__, __LINE__);
	
	info_ptr = png_create_info_struct(png_ptr);	
	if(info_ptr == NULL) throw Exception("An error has occurred reading the Portable Network Graphics file \"" + sFilename + "\".", __FUNCTION__, __FILE__, __LINE__);
	
	png_init_io(png_ptr, fpPNG);
	png_set_sig_bytes(png_ptr, 8);
	
	png_read_info(png_ptr, info_ptr); // <- This is the problem...
	
	png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, int_p_NULL, int_p_NULL);
	
	png_bytep *row_pointers = new png_bytep[height];
	
	for(png_uint_32 row = 0; row < height; row++)
	{
		
		row_pointers[row] = (png_bytep)png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
		
	}
	
	png_read_image(png_ptr, row_pointers);
	
	png_read_end(png_ptr, info_ptr);
	
	png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
	
}
catch(Exception e)
{
	
	png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
	
	fclose(fpPNG);
	fpPNG = NULL;
	
	throw e;
	
}

fclose(fpPNG);
fpPNG = NULL;


Anyone got any suggestions? I've tried both the debug and release builds of the libpng/zlib DLL, and tested them with the pngtest program. They both work, apparently.
My opinion is a recombination and regurgitation of the opinions of those around me. I bring nothing new to the table, and as such, can be safely ignored.[ Useful things - Firefox | GLee | Boost | DevIL ]
Advertisement
Hi Insanty,

I'm having exactly the same problem. My work around has been to use tiffs since libtif seems to have no problem, but that is *far* from ideal.

I have tried compiling different versions of libpng with different options, but this problem persists. Hope someone has a suggestion!

Onnel
Are you passing the correct arguments?
From what it looks like it crashes because of something that (however, could be an internal problem too).


Yeah, the arguments are correct. There are two ways of reading a file using libpng, a high-level way, and a low-level way. The code above uses the low-level method, but I've tried both, and neither work. They both fail at exactly the same place. Now I know someone else is having problems, I think I'll email the libpng guys and see if there's a problem with this build of the library...
My opinion is a recombination and regurgitation of the opinions of those around me. I bring nothing new to the table, and as such, can be safely ignored.[ Useful things - Firefox | GLee | Boost | DevIL ]
According to the docs:
Quote:If you are intending to keep the file pointer open for use in libpng,
you must ensure you don't read more than 8 bytes from the beginning
of the file, and you also have to make a call to png_set_sig_bytes_read()
with the number of bytes you read from the beginning. Libpng will
then only check the bytes (if any) that your program didn't read.


I don't see a call to png_set_sig_bytes_read() in your posted code. Perhaps that is causing the problem? Not sure it matters, but it might be worth a try.
I think png_set_sig_bytes needs to be called before png_create_info_struct. Other than that, it looks alright, but I use custom IO in my code and png_get_image_width/png_get_image_height rather than png_get_IHDR.
Quote:Original post by Dave Hunt
According to the docs:
Quote:If you are intending to keep the file pointer open for use in libpng,
you must ensure you don't read more than 8 bytes from the beginning
of the file, and you also have to make a call to png_set_sig_bytes_read()
with the number of bytes you read from the beginning. Libpng will
then only check the bytes (if any) that your program didn't read.

I don't see a call to png_set_sig_bytes_read() in your posted code. Perhaps that is causing the problem? Not sure it matters, but it might be worth a try.

The function is called png_set_sig_bytes, and it is called in my code, just after png_init_io. png_set_sig_bytes_read might be from an earlier version of libpng, but it definitely isn't in the one I'm using (which is the most recent).

Quote:Original post by abdulla
I think png_set_sig_bytes needs to be called before png_create_info_struct. Other than that, it looks alright, but I use custom IO in my code and png_get_image_width/png_get_image_height rather than png_get_IHDR.

I gave it a try, but got the same error.
My opinion is a recombination and regurgitation of the opinions of those around me. I bring nothing new to the table, and as such, can be safely ignored.[ Useful things - Firefox | GLee | Boost | DevIL ]
Looks like it might be a specific problem with libpng. Here's the relevant code I use (libpng 1.2.8), and it works fine:

    // [...]    // Check the validity of the file    unsigned char header[8];    fread(header, 1, 8, file);    if(!png_check_sig(header, 8))        // Not a valid PNG        return PNGREADNOTAPNG;    // Prepare PNG structs    if(!CreatePNGStructs(true)) // Note: Does the same as your code, creating m_png and m_pngInfo        return PNGREADFAIL;    // Set error handling    if(setjmp(png_jmpbuf(m_png)))    {        // An error occurred        png_destroy_read_struct(&m_png, &m_pngInfo, 0);        return PNGREADFAIL;    }    // Set file for reading    png_init_io(m_png, file);    png_set_sig_bytes(m_png, 8);    // Read image info    png_read_info(m_png, m_pngInfo);    // [...]
Quote:Original post by mattd
Looks like it might be a specific problem with libpng. Here's the relevant code I use (libpng 1.2.8), and it works fine:

*** Source Snippet Removed ***

Ah, you're running the latest version, and it seems to be working OK? Which compiler are you using? I'm on Visual Studio.NET 2003.
My opinion is a recombination and regurgitation of the opinions of those around me. I bring nothing new to the table, and as such, can be safely ignored.[ Useful things - Firefox | GLee | Boost | DevIL ]
Quote:Original post by iNsAn1tY
The function is called png_set_sig_bytes, and it is called in my code, just after png_init_io. png_set_sig_bytes_read might be from an earlier version of libpng, but it definitely isn't in the one I'm using (which is the most recent).


Interesting. The quote I provided was from the 1.2.8 version of the docs. I guess they forgot to update it.

This topic is closed to new replies.

Advertisement