CS140 -- Lab 3


Back to PGM files.

To do this lab, you are to copy the program pgm_editor.cpp from /home/plank/cs140/Labs/Lab3. You'll note that there is a comment that says "DO NOT CHANGE ANYTHING BELOW THIS LINE". I feel that this comment is pretty self-explanatory. The gradescript will check to see if you have changed anything below the line, and if you do, it will flag it as an error. What you do is write code where it says "Write your code here". You compile this program and run it, and that is what you submit for grading.

Here is pgm_editor.cpp:

#include <cstdio>
#include <cstdlib>
#include <string>
#include <sstream>
#include <vector>
#include <iostream>
using namespace std;

typedef vector <int> IVec;

// Write your code here:

// DO NOT CHANGE ANYTHING BELOW THIS LINE

void bad_pgm(string s)
{
  cerr << "Bad PGM file: " << s << endl;
  exit(1);

}

....

Your job is to write seven procedures. You can figure out their parameter types from how they are called within pgm_editor.cpp. They all revolve around PGM files, which are held in a vector of vectors of ints. Suppose that we have a PGM file p, declared as:

vector <IVec> p;

Then p.size() is the number of rows of the PGM file. Each element p[i] will be a vector of the same size. p[i].size() is the number of columns in the PGM file. And p[i][j] contains the pixel value in row i column j. In the procedures that you write, you may assume that you get a valid PGM file as input. You do not have to error check.

The seven procedures are:

  1. pgm_write(p): This writes a PGM file p to standard output. I want the output to be in a very specific format:

  2. pgm_create(r, c, pv). This creates and returns a PGM file which has r rows, c columns, and all pixels have the value pv. You actually return a 2D vector, not a file from this function.

  3. pgm_cw(p). This rotates p 90 degrees clockwise. Obviously, p must be a reference parameter. You will need to declare a 2D vector to hold the rotated pgm and then copy the rotated pgm back into the original pgm vector.

  4. pgm_ccw(p). This rotates p 90 degrees counterclockwise. Obviously, p must be a reference parameter. You will need to declare a 2D vector to hold the rotated pgm and then copy the rotated pgm back into the original pgm vector.

  5. pgm_pad(p, w, pv). This adds w pixels around the border of p. All the pixels will have the value pv. You may not declare another 2D vector to hold the padded pgm file. You can accomplish the padding using only the original pgm vector.

  6. pgm_panel(p, r, c). This changes p so that it has r*c copies of the PGM file, laid out in a r * c grid. See the examples. You may not declare another 2D vector to hold the padded pgm file. You can accomplish the paneling using only the original pgm vector.

  7. pgm_crop(p, r, c, rows, cols). This changes p so that it has a subset of the original picture -- the rectangle starting at row r and column c, with rows rows and cols cols. You may not declare another 2D vector to hold the padded pgm file. You can accomplish the cropping using only the original pgm vector.
When pgm_editor is compiled and running correctly, you can use it either to create a PGM file, or to edit the PGM file on standard input and print the result on standard output. For example:
UNIX> pgm_editor
usage: pgm_editor command....

        CREATE rows cols pixvalue
        CW
        CCW
        PAD pixels pixvalue
        PANEL r c
        CROP r c rows cols
UNIX> 

UNIX> pgm_editor CREATE 50 200 0 | convert - example_create.jpg

UNIX> pgm_editor CW < Red.pgm | convert - example_cw.jpg

UNIX> pgm_editor CCW < Red.pgm | convert - example_ccw.jpg

UNIX> pgm_editor PAD 30 0 < Rodney.pgm | convert - example_pad_1.jpg

UNIX> pgm_editor PAD 30 0 < Rodney.pgm | pgm_editor PAD 30 255 | pgm_editor PAD 1 0 | convert - example_pad_2.jpg

UNIX> pgm_editor PANEL 2 4 < Red.pgm | convert - example_panel_1.jpg

UNIX> pgm_editor PAD 6 0 < Rodney.pgm | pgm_editor PAD 3 255 | pgm_editor PANEL 3 5 | convert - example_panel_2.jpg

UNIX> pgm_editor CROP 45 60 50 100 < Red.pgm | convert - example_crop.jpg

UNIX> pgm_editor CROP 45 60 50 100 < Red.pgm | pgm_editor PAD 2 0 | pgm_editor PAD 1 255 | pgm_editor PANEL 4 9 | convert - example_crop_panel.jpg 


BVZ Notes

  1. Dr. Plank's main is not declared to return an int, which could cause your program not to compile on a Mac. You can fix this problem by having your main return an int when compiling and testing it on a Mac. However, when you transfer the file to a hydra machine to test it, you will need to change main back to not returning an int. If you do not, then Dr. Plank's gradeall script will flag your program as incorrect, since you will have changed something below the "Do Not Change Anything" line.

  2. In pgm_write, you need to ensure that your pgm file ends with exactly one newline character. Hence if the number of pixels in your pgm file is not a multiple of 20, then you will need to output a newline character at the end of your pgm_write procedure. If the number of pixels in your pgm file is a multiple of 20, then your pgm_write procedure will already have written a newline character and you should not print a second one.

Grading and Starting

Once again, you cannot modify the part of the program that says "DO NOT CHANGE ANYTHING BELOW THIS LINE.". If so, the gradescript will yell at you and won't get it correct.

To start this lab -- and do this during lab, write dummy versions of these procedures that don't work, but that compile. That way you at least have the procedure declarations correct. Then work on pgm_create() and pgm_write(). Then the others. Think about when you should be using reference parameters.