Make sense of PGM data and load PGM data into vector/array

480 Views Asked by At

Let me preface this by saying this is my first time working with the PGM file format in C++, so I have multiple questions.

  1. I'm currently using P2 PGM files, but I read that P5 is much simpler to work with. How can I convert a P2 to a P5?

  2. With the P2, I am trying to take the image and transfer the pixel values to a 2D vector or array or anything remotely index-able. I'm using a very basic image (white background with a black rectangle in the foreground). Here's my code so far:

    fstream img;
    img.open(PATH_NAME, ios::in | ios::binary | ios::out);
    
    string line;
    getline(img, line); //header part that says "P2"

    //stores column and row values
    getline(img, line);
    istringstream iss(line);
    string row_string, col_string;
    iss >> row_string;
    iss >> col_string;
    int original_rows = stoi(row_string);
    int original_cols = stoi(col_string);
    
    getline(img, line);//collects maxval

    //now I am collecting actual image/pixel data
    getline(img, line);
    cout << line;

The problem with that last part is that when I cout << line; , this is the output:

\377\377\377\377\377\377\377\377\377\377\377\377\

and on and on and on for much longer than a single line should be (there are 162 columns in my sample photo and this code outputs much more than 162 377s). The maxval is 255, so I'm not really sure what the problem is.

  1. As for actually transferring these values into something indexable, how do I go about that? So far, my idea is to take each string line, detect for '\' and collect the individual values that way and store it in an array; convert each string to int and then store it in a vector. Might be easier said than done, so I am open to more efficient options.
1

There are 1 best solutions below

8
On

The problem is that you are confusing text I/O with binary I/O. As I understand the image data in a P5 file is held as binary byte values. Therefore you should be reading it into a byte vector (or similar) using read, instead of reading it using getline which is for text I/O.

Like this

vector<unsigned char> raster(original_rows*original_cols);
img.read(raster.data(), original_rows*original_cols);

raster is your something indexable.