c++binary-datapgm

What is wrong with my code to write netbpm images?


I am currently working on a project that needs to output generated images. I have decided to the use greyscale netbpm format due to its simplicity. One of these images is a heightmap. My code to export it is as follows:

#include <array>
#include <fstream>
#include <iostream>

int main(){
    constexpr unsigned LENGTH = 4;
    std::array<double, LENGTH*LENGTH> m_data = {
        0, 0, 0, 0,  
        0, 1, 1, 0,
        0, 1, 1, 0,
        0, 0, 0, 0
    };

    std::ofstream fout;
    fout.exceptions(std::ios::badbit | std::ios::failbit);
    fout.open("test.pgm", std::ios::binary);
    fout << "P5 " << LENGTH << " " << LENGTH << "\n256\n";

    for(unsigned i=0;i<LENGTH*LENGTH;++i){
        unsigned char brightness = m_data[i]*255;
        std::cout << m_data[i] << std::endl;
        fout.write(reinterpret_cast<char*>(&brightness), sizeof(unsigned char));
    }

    return 0;
}

This code looks correct to me, after reading the specification for the netbpm format on Wikipedia. Yet, when I attempt to open this image in either Gimp or Clion there are various errors:

Non-specific error from Clion "Premature end of file" error from Gimp.

The file is saved with a pgm extension. What is wrong with my code?


Solution

  • Try writing the NetPBM header like this:

    fout << "P5\n" << LENGTH << " " << LENGTH << "\n255\n";
    

    The reason is that most image readers check the MAXVAL and if it is 255 or less, they assume 8-bits per pixel. If MAXVAL exceeds 255, they assume 16-bits per pixel, so they will complain that your file is too short (as it doesn't provide 2 bytes per pixel).