Zayum
Zayum

Reputation: 119

Write a function ImageLoader to read the contents of a PPM file in P3 format using C++

I am completely lost and frustrated trying to read from a PPM file. I understand how to open the file, and how to access the magic number, the width and the height, and the max color value. I am struggling to understand the process behind reading the pixel data from the PPM file, and assigning it to a previously defined private variable/matrix image[MAX_WIDTH[MAX_HEIGHT][3]. The goal of this function is to load the PPM file data into the image array so that I can later draw on the existing file in a later function. I'm used to writing in python so my c++ is really rusty.

P3
720 540
255
123 125 124 
124 126 125 127 129 128 129 131 130 128 130 129 126 128 127 
132 134 133 132 135 134 135 140 139 137 143 141 136 142 140 135 143 140 
134 144 140 135 147 142 138 145 143 139 143 142 138 142 141 137 141 140 
139 144 143 139 143 142 139 143 142 140 143 141 143 142 140 140 140 137 
enum COLOR { RED, GREEN, BLUE }; // this is in a header file

// everything below is in a cpp file
void Image::ImageLoader(string filename) {
    int max_color;
    ifstream infile; // image variable used to read from a file
    infile.open(filename); // open the file, and associate image with it
    if(infile.fail()){ // true if filename doesn't exist
        throw "File failed to open";
    }
    string magic_num;
    infile >> magic_num >> width >> height >> max_color;


    if (max_color != MAX_COLOR){
        throw "Max color range not 255";
    }
    if (magic_num != "P3"){
        throw "Bad magic number";
    }
    if (width > MAX_WIDTH || width < 0)
        throw "Width out of bounds";
    if (height > MAX_HEIGHT || height < 0)
        throw "Height out of bounds";


// This is where i'm stuck. I think I'm lacking some fundamental knowledge in c++ that's making this part harder. 

// my goal with these loops is to parse through the file infile value by value, and assign these values to my image matrix. 
// I don't really get what's happening with the array image[MAX_WIDTH][MAX_HEIGHT][3]. I know it's a 3d array, but how does the use of enum play into iterating through the array?
// Am I supposed to increment the third index while iterating, or do I iterate all three colors at once? 
    for(int x = 0; x < width; x++){
        for(int y = 0; y < height; y++){
            if (0 > x || x > 255 || 0 > y || y > 255){
                throw "Color value invalid";
            }
            infile >> image[x][y][RED];
            infile >> image[x][y][GREEN];
            infile >> image[x][y][BLUE];


        }
    }

    }

Upvotes: 1

Views: 1873

Answers (1)

Botje
Botje

Reputation: 30832

From the specification:

Each PPM image consists of the following:
...
A raster of Height rows, in order from top to bottom.
Each row consists of Width pixels, in order from left to right.
Each pixel is a triplet of red, green, and blue samples, in that order.

This translates naturally to a nested loop:

for (int y = 0; y < height; y++) {
  for (int x = 0; x < width; x++) {
    unsigned int red, green, blue;
    infile >> red >> green >> blue;
    if (!infile) {
      std::cerr << "Error reading from file around (" << y << "," << x << ")" << std::endl;
      return;
    }
    // TODO: Check the values of red, green, blue against the interval [0,255] 
    image[y][x][0] = red;
    image[y][x][1] = green;
    image[y][x][2] = blue;
  }
}

Finally, you defined an enum COLOR { RED, GREEN, BLUE }. C++ will assign values to the three enum values as follows: RED=0, GREEN=1, BLUE=2.

So it is fine to use these enum values in place of 0,1,2 in the code above.

Upvotes: 1

Related Questions