Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading width and height of PNG header

I am experimenting with reading the width and height of a PNG file. This is my code:

struct TImageSize {
    int width;
    int height;
};

bool getPngSize(const char *fileName, TImageSize &is) {
    std::ifstream file(fileName, std::ios_base::binary | std::ios_base::in);

    if (!file.is_open() || !file) {
        file.close();
        return false;
    }

    // Skip PNG file signature
    file.seekg(9, std::ios_base::cur);

    // First chunk: IHDR image header
    // Skip Chunk Length
    file.seekg(4, std::ios_base::cur);
    // Skip Chunk Type
    file.seekg(4, std::ios_base::cur);

    __int32 width, height;

    file.read((char*)&width, 4);
    file.read((char*)&height, 4);

    std::cout << file.tellg();

    is.width = width;
    is.height = height;

    file.close();

    return true;
}

If I try to read for example from this image from Wikipedia, I'm getting these wrong values:

252097920 (should be 800)
139985408 (should be 600)

Note that the function is not returning false so the contents of the width and height variables must come from the file.

like image 898
ComFreek Avatar asked Dec 29 '12 16:12

ComFreek


Video Answer


1 Answers

It looks like you're off by a byte:

// Skip PNG file signature
file.seekg(9, std::ios_base::cur);

The PNG Specification says the header is 8 bytes long, so you want that "9" to be an "8" instead. Positions start at 0.

Also note that the spec says that integers are in network (big-endian) order, so you may want or need to use ntohl() or otherwise convert byte order if you're on a little-endian system.

It's probably worth using libpng or stb_image or something similar rather than attempting to parse the png yourself, though -- unless you're doing this to learn.

like image 90
leander Avatar answered Sep 29 '22 08:09

leander