0

I'm trying to get the values of IHDR of a png image using c++, I am limited to only use standard c++11-c++17 no 3rd party library is allowed.

I have successfully got the png signature right, but it seems that my way of reading the IHDR is incorrect, because the sample png that I'm working on only have 500 width and 500 height (dim500x500) but I'm getting very large values.

I have also tried to skip 16 bytes after the png signature just in case my png is a CgBI but I think it is not the case.

code

#include <iostream>
#include <fstream>

int main()
{
    std::ifstream read_bin("yeji.png", std::ios::out | std::ios::binary);
    if (!read_bin)
    {
        std::cout << "ERROR: reading binary file!\n";
        exit(1);
    }

    unsigned char pngsign[8];
    read_bin.read(reinterpret_cast<char*>(&pngsign[0]),sizeof(unsigned char)*8);

    unsigned int IHDR_LENGTH;
    char CHUNK_TYPE[4];
    read_bin.read(reinterpret_cast<char*>(&IHDR_LENGTH),sizeof(unsigned int));
    read_bin.read(reinterpret_cast<char*>(&CHUNK_TYPE[0]),sizeof(char)*4);

    unsigned int h, w;
    read_bin.read(reinterpret_cast<char*>(&w),sizeof(unsigned int));
    read_bin.read(reinterpret_cast<char*>(&h),sizeof(unsigned int));

    unsigned char bitdepth;
    read_bin.read(reinterpret_cast<char*>(&bitdepth),sizeof(unsigned char));

    unsigned char colordepth;
    read_bin.read(reinterpret_cast<char*>(&colordepth),sizeof(unsigned char));

    unsigned char compression_method;
    read_bin.read(reinterpret_cast<char*>(&compression_method),sizeof(unsigned char));

    unsigned char filter_method;
    read_bin.read(reinterpret_cast<char*>(&filter_method),sizeof(unsigned char));

    unsigned char interlacce_method;
    read_bin.read(reinterpret_cast<char*>(&interlacce_method),sizeof(unsigned char));

    std::cout<<"PNG SIGN : ";
    for(size_t i=0; i<8; ++i) std::cout<<int(pngsign[i])<<' ';
    std::cout<<'\n';

    std::cout<<"IHDR LENGTH = "<<IHDR_LENGTH<<'\n';
    std::cout<<"CHUNK TYPE  = "<<CHUNK_TYPE<<'\n';

    std::cout<<"Width  = "<<w<<'\n';
    std::cout<<"height = "<<h<<'\n';

    std::cout<<"bitdepth   = "<<int(bitdepth)<<'\n';
    std::cout<<"colordepth = "<<int(colordepth)<<'\n';
    std::cout<<"compression_method = "<<int(compression_method)<<'\n';
    std::cout<<"filter_method      = "<<int(filter_method)<<'\n';
    std::cout<<"interlacce_method  = "<<int(interlacce_method)<<'\n';

    return 0;
}

output

PNG SIGN : 137 80 78 71 13 10 26 10 
IHDR LENGTH = 218103808
CHUNK TYPE  = IHDR�PNG
▒

Width  = 4093706240
height = 4093706240
bitdepth   = 8
colordepth = 2
compression_method = 0
filter_method      = 0
interlacce_method  = 0
  • 3
    Remember that all sizes are in *big endian*, while a typical x86(-64) system is *little endian*. – Some programmer dude Jul 19 '21 at 05:22
  • 1
    Also remember that when you pass an array of characters to the output operator `<<`, it will be treated as a null-terminated string. Since e.g. `CHUNK_TYPE` *isn't* a null-terminated string you can't do that without undefined behavior as the output continues past the end of the array in search for the non-existing null-terminator. – Some programmer dude Jul 19 '21 at 05:24
  • 2
    https://stackoverflow.com/questions/2384111/png-file-format-endianness – Retired Ninja Jul 19 '21 at 05:24
  • C++ does not standardize it ever and so byte order is not detectable compile time in standard manner.Instead the committee adds useless trash and garbage features into language. So you have to use non standard methods. There usually are POSIX ntohl() ntohs() functions in system and/or compiler intrinsic functions for changing byte order of numbers. – Öö Tiib Jul 19 '21 at 06:37
  • @ÖöTiib `c++20` has `std::endian` – Ian Cook Jul 19 '21 at 08:59

0 Answers0