libPng And Memory Access Violations

Member
Posts: 23
Joined: 2006.12
Post: #1
I'm having some problems using libpng to read png files. I can open the file, read the header and see that it's definitely a png file, but as soon as I call png_read_png ( which in turn calls fread and attempts to read memory I'm assuming it's not supposed to ) I get memory access errors causing my program to crash.

I've stepped through a million times and can't seem to find what I'm doing wrong. And do to the definite lack of simple libpng examples, I don' have much to compare this against. (Other then the libpng manual but that all seems to agree with what's here.)

I used this program as the basis for my read png function: http://zarb.org/~gc/html/libpng.html

Code:
void pngLoad::read_png_file(const char *file_name)
{
    png_byte header[8];

    FILE *fp = fopen(file_name, "rb");
    if (!fp)
        std::cout << "[read_png_file] File %s could not be opened for reading";
    
    fread(header, 1, 8, fp);
    bool is_png = !png_sig_cmp(header, 0, 8);
    if (!is_png)
        std::cout << "[read_png_file] File %s is not recognized as a PNG file";

    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    
    if (!png_ptr)
        std::cout << "[read_png_file] png_create_read_struct failed";

    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr)
        std::cout << "[read_png_file] png_create_info_struct failed";

    if (setjmp(png_jmpbuf(png_ptr)))
        std::cout << "[read_png_file] Error during init_io";

    png_init_io(png_ptr, fp);
    png_set_sig_bytes(png_ptr, 8);

    png_read_png(png_ptr, info_ptr, NULL, NULL);

    /* The rest of the function that is never reached
        ...
        */
}
Quote this message in a reply
Sage
Posts: 1,482
Joined: 2002.09
Post: #2
My PNG loading code looks like this:
Code:
#include <stdlib.h>
#include <assert.h>

#include "png.h"

#define PNG_SIG_BYTES 8

char *
load_png(char *name, int *width, int *height)
{
    FILE *png_file = fopen(name, "rb");
    assert(png_file);

    uint8_t header[PNG_SIG_BYTES];

    fread(header, 1, PNG_SIG_BYTES, png_file);
    assert(!png_sig_cmp(header, 0, PNG_SIG_BYTES));

    png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    assert(png_ptr);

    png_infop info_ptr = png_create_info_struct(png_ptr);
    assert(info_ptr);

    png_infop end_info = png_create_info_struct(png_ptr);
    assert(end_info);

    assert(!setjmp(png_jmpbuf(png_ptr)));
    png_init_io(png_ptr, png_file);
    png_set_sig_bytes(png_ptr, PNG_SIG_BYTES);
    png_read_info(png_ptr, info_ptr);

    *width = png_get_image_width(png_ptr, info_ptr);
    *height = png_get_image_height(png_ptr, info_ptr);

    png_uint_32 bit_depth, color_type;
    bit_depth = png_get_bit_depth(png_ptr, info_ptr);
    color_type = png_get_color_type(png_ptr, info_ptr);
            
    if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
        png_set_gray_1_2_4_to_8(png_ptr);

    if (bit_depth == 16)
            png_set_strip_16(png_ptr);
            
    if(color_type == PNG_COLOR_TYPE_PALETTE)
        png_set_palette_to_rgb(png_ptr);
    else if(color_type == PNG_COLOR_TYPE_GRAY ||
            color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
        {
            png_set_gray_to_rgb(png_ptr);
        }

    if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
        png_set_tRNS_to_alpha(png_ptr);
    else
        png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);

    png_read_update_info(png_ptr, info_ptr);

    png_uint_32 rowbytes = png_get_rowbytes(png_ptr, info_ptr);
    png_uint_32 numbytes = rowbytes*(*height);
    png_byte* pixels = malloc(numbytes);
    png_byte** row_ptrs = malloc((*height) * sizeof(png_byte*));

    int i;
    for (i=0; i<(*height); i++)
      row_ptrs[i] = pixels + ((*height) - 1 - i)*rowbytes;

    png_read_image(png_ptr, row_ptrs);

    free(row_ptrs);
    png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
    fclose(png_file);

    return (char *)pixels;
}

I do a lot of unnecessary steps in between, but I would expect that maybe you are needing the png_read_info() call. I'd bet that is required to initialize the structs properly. I could look it up in the docs, but I'm feeling lazy at the moment.

Scott Lembcke - Howling Moon Software
Author of Chipmunk Physics - A fast and simple rigid body physics library in C.
Quote this message in a reply
Member
Posts: 23
Joined: 2006.12
Post: #3
Well, originally I had it going the "low-level" way and started off with png_read_info(). png_read_png() is supposed to let you go around that.

Ironically though, png_read_info() gave me the same issue when I had it in there. With the memory violation and what not.

I'll go back to trying it with png_read_info. And thank you for the source, I'll look it over and see if I can find the difference.

P.S. Your post count of 666 is making me wonder if I should trust your advice Rasp
Quote this message in a reply
Member
Posts: 23
Joined: 2006.12
Post: #4
Hmm... my code is almost identical to yours up to the png_read_info(png_ptr, info_ptr);

But it crashes there.

Maybe the problem is outside my code? Something in the png file perhaps?
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #5
Mine is here:

http://onesadcookie.com/trac/browser/Rub...urce/png.c

And I don't have exactly 666 posts Rasp
Quote this message in a reply
Sage
Posts: 1,482
Joined: 2002.09
Post: #6
Hah! There.

Now I can be trusted. Wink

Scott Lembcke - Howling Moon Software
Author of Chipmunk Physics - A fast and simple rigid body physics library in C.
Quote this message in a reply
Member
Posts: 23
Joined: 2006.12
Post: #7
Well, it looks like I've finally pin down the error, and as I suspected, it wasn't in the source code itself.

Believe it or not, it's a windows specific issue...

...what, no one is surprised?

Quote:So you pass the FILE* from fopen to png_init_io which will cause libpng
itself to make fread() calls on that FILE*. If libpng then crashes in
png_read_info it means that the library you used to allocate the FILE* (i.e.
the one containing the implementation of fopen which was called in (1)) is
*not* the same as the library libpng expects to call to read from the FILE*
(i.e. the library libpng.so was compiled/linked against to get the
implementation of fread).

FIX:
If you can"t change your library to match libpng and you don"t want to
compile and build libpng (statically) to change it then you have no choice
but to implement your own file IO and hope that there are no other issues (I
believe that file IO with stdio is the *only* case where an object is
allocated in the application and subject to library calls within libpng.)

Now if only I better understood his fix...because I really don't feel like writing my own file IO.
Cry
Quote this message in a reply
Member
Posts: 23
Joined: 2006.12
Post: #8
Well, for those of you who absolutely could not sleep until you found out what came of this problem, it's fixed now. Turned out the libpng version I was using was from 2004...*sigh* So I downloaded the newest source and recompiled the libraries. Lo and behold, it works now. Thanks for all the help.
Quote this message in a reply
Moderator
Posts: 3,579
Joined: 2003.06
Post: #9
Skorche Wrote:Hah! There.

Now I can be trusted. Wink

Continuing the way OT: I did 666 last week too. Didn't see any black cats crossing my path or anything either. I guess 666 is the number right after 665 and just before 667 after all. Whew! Sneaky
Quote this message in a reply
Nibbie
Posts: 2
Joined: 2013.09
Post: #10
I have encountered the same problem as you.
And my version of libpng is 1.2.37, can you tell me which version should I
use? Or can you send your libpng to me. My e-mail is yejizhensdudsm@163.com
Many thanks.
Quote this message in a reply
Moderator
Posts: 3,579
Joined: 2003.06
Post: #11
This is a pretty old thread, so I don't know if the OP is still around to answer. Personally I haven't used libpng in ages. Lately I've been using stb_image for loading pngs. If you don't need any png features other than just loading pngs for a game, it works great and is easy to use.
Quote this message in a reply
Moderator
Posts: 1,562
Joined: 2003.10
Post: #12
I've encountered libpng crashes caused by linking to a mismatched version of zlib. Make sure you're linking against the exact zlib version that your libpng states it's compatible with; in my case, I had to downgrade from zlib 1.2.5 to 1.2.3 to get it to work without crashing with libpng 1.4.1.
Quote this message in a reply
Nibbie
Posts: 2
Joined: 2013.09
Post: #13
How to solve this problem? I have tried many different methods. However, I still can't find a solution, any one can help me 。
thanks。
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  libpng loading junk at bottom of my OpenGL textures...? BinarySpike 6 6,316 Apr 19, 2007 12:20 PM
Last Post: BinarySpike
  libpng transparency problem wyrmmage 3 5,495 Mar 1, 2007 05:53 PM
Last Post: OneSadCookie
  Trouble writing PNGs with 16 bits per channel using libpng flash 2 3,947 Aug 28, 2006 11:01 AM
Last Post: flash
  libpng with OpenGL : return what? Jones 3 4,264 May 28, 2006 07:32 AM
Last Post: Jones
  SDL_image + libpng + Panther = version mismatch BobbyWatson 2 4,275 Oct 23, 2005 03:55 AM
Last Post: BobbyWatson