0

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.

Calamaryi
  • 3
  • 4
  • The width and height are stored in the png width first then height, but you are reading height followed by width. So looking quickly at your code, just remove the line `it += 4` that is probably putting you too far ahead in the header, then you should be able to read the width then height without issue. – user20716902 Jan 23 '23 at 22:34
  • Hmm...seems at least really close to a duplicate. https://stackoverflow.com/q/5354459/179910 – Jerry Coffin Jan 23 '23 at 22:41
  • @user20716902 I deleted that line and it changes my output to something different but still incorrect. – Calamaryi Jan 23 '23 at 22:41
  • Ah ok, in that case change `it += 4` to `it+=8` instead. – user20716902 Jan 23 '23 at 22:44
  • Great glad that solved the issue, I've added the details as an answer for you. – user20716902 Jan 23 '23 at 22:58

1 Answers1

1

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
user20716902
  • 861
  • 1
  • 14