1

I am attempting to read a PPM image from standard input with this code:

cin >> format;
cin >> ppm->width >> ppm->height >> ppm->colourMax;

for (int r = 0; r < ppm->height; r++) {
  ppm->pixels[r] = new Pixel[ppm->width];
  for (int c = 0; c < ppm->width; c++) {
    Pixel p = Pixel();
    cin.read(reinterpret_cast<char *>(&p.r), sizeof(unsigned char));
    cin.read(reinterpret_cast<char *>(&p.g), sizeof(unsigned char));
    cin.read(reinterpret_cast<char *>(&p.b), sizeof(unsigned char));
    ppm->pixels[r][c] = p;
  }
}

However, when I output the PPM image unchanged, I am missing the very last pixel. Everything else seems to work perfectly. Any ideas?

DBoyer
  • 3,062
  • 4
  • 22
  • 32
  • Did not check yet, but maybe you are missing the *first* pixel? – Antonio Feb 17 '16 at 16:59
  • Which pixel coordinates are missing? Does this vary depending on the size of the input image? Have you tried more than one source image file? – tadman Feb 17 '16 at 17:00
  • When I compare the original file to my output, the original has 1 extra byte at the end. – DBoyer Feb 17 '16 at 17:00
  • 1
    It's also worth noting that you can declare `Pixel& p = ppm->pixels[r][c]` and avoid creating a useless intermediate variable. Less copying that way. – tadman Feb 17 '16 at 17:01
  • 1
    A single byte is not enough for a pixel, as your code reads 3 per pixel. What is that extra byte and what is your system? – Serge Ballesta Feb 17 '16 at 17:02
  • I have tried it with 2 different images, and same problem, there is 1 extra byte at the end, the byte is different for each image. – DBoyer Feb 17 '16 at 17:08
  • For 1 image the extra byte is 255 and the other is a 0 – DBoyer Feb 17 '16 at 17:11
  • Hard to confirm without a real file, but it looks that your original files do have an extra byte. – Serge Ballesta Feb 17 '16 at 17:27

1 Answers1

1

The PPM file format has for all its variant a single space character following the colourMax parameter:

Each PPM image consists of the following:

...
5. A height, again in ASCII decimal.
6. Whitespace.
7. The maximum color value (Maxval), again in ASCII decimal. Must be less than 65536 and more than zero.
8. A single whitespace character (usually a newline).
...

In your code, this extra whitespace is not extractacted from the stream because read() starts reading at the current position. And as you read an fixed number of chars, this extras space, causes your code to ignore the last char.

Solution: just cin.ignore(); before starting your reading loops.

Christophe
  • 68,716
  • 7
  • 72
  • 138