0

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.
esljkfgh
  • 25
  • 1
  • 5

1 Answers1

0

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.

john
  • 85,011
  • 4
  • 57
  • 81
  • Ah, I see. However, after using the read function, the data is still outputting as "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\340". Not sure why – esljkfgh Sep 16 '20 at 02:11
  • @esljkfgh How are you outputing it? – john Sep 16 '20 at 06:24
  • I ran into an error using raster.data() as the first parameter for img.read, so I created char* buffer. I am cout-ing buffer. – esljkfgh Sep 16 '20 at 16:45
  • The reason that you see `"\377\377\377..."` is because cout treats `char*` as a string which in your case it isn't. The contents are probably fine. But if you want to see them then write a loop that writes each element of the buffer one at a time, but cast each element to an integer first so you see the integer value, instead of seeing the character. – john Sep 16 '20 at 18:30
  • thank you so much! One small problem remaining: the first 15 or so values are all -1. After that, normal numbers are being outputted. Is there any way I can be certain these are the correct values? My image is just a black rectangle in the middle of a white background, but there's a lot of variation in the values, so I'd like to be sure. – esljkfgh Sep 17 '20 at 13:50
  • `char`'s are integers and can be negative. I imagine that you're expecting unsigned byte values in the range 0 to 255. So you should change your data to `unsigned char*` (or `vector` as I originally suggested). If you do that you should see the first 15 values print as 255 instead of -1. Note this is just about how the data is printing, that actual bytes read will be the same in either case. – john Sep 17 '20 at 14:42
  • Yes, I am using the vector. So just to be sure - because I will be analyzing the values of the pixels - as long as I keep the data in unsigned char form, I can say something like `if(pixel == 255)` to check if it is white, it will work right? – esljkfgh Sep 18 '20 at 00:14
  • @esljkfgh That will be fine. It's when you try and compare unsigned values with negative values that you can run into trouble. – john Sep 18 '20 at 05:55