How to read a pbm/pgm/ppm image from a file

I am trying implement a program that read a PBM/PGM/PPM image from a file, following the description from here: https://en.wikipedia.org/wiki/Netpbm , and display the image on screen using sdl and opengl, based on the example explained here: https://open.gl/context and here: https://open.gl/drawing .

Right now, trying display a PBM file, either ASCII or binary, I manage to show something on screen, but different from the original image. If I try open a PGM or PPM ASCII file, I got a segmentation error. Trying open a binary file for this two formats, I got an error: terminate called after throwing an instance of 'std::invalid_argument'. This happens when the program tries read the third line of file, which contains the value for max_value.

Taking in consideration that despite the errors when I try open PGM or PPM files, the code is being compiled with no errors or warnings, someone can point for the best way to read this type of data from the file, based on the description from the link above?

What I have right now:

base class Netpbm.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
struct Pixel {
  float r, g, b;
};
typedef struct Pixel pixel;

class Netpbm {
protected:
  std::string magicNumber;
  int width;
  int height;
  std::vector<std::vector<pixel>> pixels;
public:
  int getWidth();
  int getHeight();

  virtual void read_file(std::string file_name) = 0;
  virtual void write_file(std::string file_name) = 0;
  
  float * toArray();
};


subclass Bitmap.cpp (for handling the PBM file format - all the other subclass have the same structure)

1
2
3
4
5
6
class Bitmap : public Netpbm {
public:
  Bitmap(std::string file_name);
  void read_file(std::string file_name);
  void write_file(std::string file_name);
};


implementation for read_file (Bitmap class):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
void Bitmap::read_file(std::string file_name) {
  std::ifstream file(file_name);
  std::string line_one, line_two, line_pixels;
  
  while(getline(file, line_one)) {
    if(line_one.at(0) != '#') {
      magicNumber = line_one;
      break;
    }
  }

  while(getline(file, line_two)) {
    std::string width, height;
    std::stringstream ss(line_two);

    if(line_two.at(0) != '#') {
      if(getline(ss, width, ' '))
        this->width = stoi(width);

      if(getline(ss, height, ' '))
        this->height = stoi(height);

      break;
    }
  }

  std::cout << magicNumber << std::endl;
  std::cout << width << " " << height << std::endl;  

  if(magicNumber == "P1") {
    std::cout << "P1" << std::endl;
    while(getline(file, line_pixels)) {
      if(line_pixels.at(0) != '#') {
        std::string data;
        std::stringstream ss(line_pixels);

        std::vector<pixel> row;
        while(getline(ss, data, ' ')) {
          pixel p;
          p.r = p.g = p.b = stoi(data);
          row.push_back(p);
        }
        pixels.push_back(row);
      }
    }
  }

  if(magicNumber == "P4") {
    std::cout << "P4" << std::endl;
    pixels = std::vector<std::vector<pixel>>(height, std::vector<pixel>(width));
    unsigned char c;
    int row = 0, column = 0;
    while(file.read((char*)&c, sizeof(char))) {
      for(int k=0; k<8; k++) {
        bool bit = (c & (1 << k));

        pixel p;
        if(bit)
          p.r = p.g = p.b = 1;
        else
          p.r = p.g = p.b = 0;
        pixels[row][column] = p;

        if(column < width) column++;
        else {row++; column = 0;}
      }
    }
  }
}
Last edited on
FYI, klebermo, your wiki link is borked because you included a period at the end of the link. The CPlusPlus URL interpreter isn't smart enough to not add the period to the link.
Last edited on
Write the following:
https://en.wikipedia.org/wiki/Netpbm[b][/b].

To produce:
https://en.wikipedia.org/wiki/Netpbm.
Topic archived. No new replies allowed.