Search code examples
c++imagebinarypngpixel

How can I extract the height and width of this image in C++?


I am having an issue with extracting the proper height and width of a png file. The width prints properly, but the height does not. I am currently inputting an image of height 2264 pixels * width 2382 pixels yet my output is this: Image width: 2382, Image height: 1229472850. Below is my code, any suggestions would be helpful.

int loadImage(std::string fileName, void(*inputConversionType)()) {
    // extract the file extension from the file name
    size_t dotPos = fileName.rfind(".");
    if (dotPos == std::string::npos) {
        std::cout << "Error: invalid file name, no extension found" << std::endl;
        return 1;
    }
    std::string extension = fileName.substr(dotPos + 1);

    // open the file in binary mode
    std::ifstream file(fileName, std::ios::binary);
    if (!file.is_open()) {
        std::cout << "Error: unable to open file " << fileName << std::endl;
        return 1;
    }
    // get the size of the file and read the contents into a buffer
    file.seekg(0, std::ios::end);
    int fileSize = file.tellg();
    file.seekg(0, std::ios::beg);
    std::vector<unsigned char> buffer(fileSize);
    file.read(reinterpret_cast<char*>(&buffer[0]), buffer.size());
    file.close();
    if (extension == "png") {
        if (buffer.size() < 24) {
            std::cout << "Not a valid PNG file" << std::endl;
            return 1;
        }
        std::vector<unsigned char>::iterator it = buffer.begin();
        if (*it != 137 || *(it + 1) != 80 || *(it + 2) != 78 || *(it + 3) != 71 || *(it + 4) != 13 || *(it + 5) != 10 || *(it + 6) != 26 || *(it + 7) != 10) {
            std::cout << "Not a valid PNG file" << std::endl;
            return 1;
        }

        // increment iterator by 8
        it += 8;
        std::string type(it, it + 4);
        it += 4;

        unsigned int height = (*it++ << 24) | (*it++ << 16) | (*it++ << 8) | (*it++);
        unsigned int width = (*it++ << 24) | (*it++ << 16) | (*it++ << 8) | (*it++);

        std::cout << "Image width: " << width << ", Image height: " << height << std::endl;

    }
}

I was expecting this to output the correct height and width of pixels and print it to the screen.


Solution

  • The width and height are stored in the png header with width first then height, but you are reading height followed by width. Also it += 4 should be it += 8 this ensures you are in the correct position to read both values correctly.

    This means that the last four lines of the corrected code are now:

        it += 8;
    
        unsigned int width = (*it++ << 24) | (*it++ << 16) | (*it++ << 8) | (*it++);
        unsigned int height = (*it++ << 24) | (*it++ << 16) | (*it++ << 8) | (*it++);
    
        std::cout << "Image width: " << width << ", Image height: " << height << std::endl;
    

    This gives the expected output of:

    Image width: 2382, Image height: 2264