The goal of this lab is to introduce you to basic concepts in the C++ program language. Concepts you will be familiar with after this lab include:
A skeleton version the program will appear in your cs35/labs/01 directory when you run update35. The program handin35 will only submit files in this directory. In later labs you may have the opportunity to work with a partner, but for this lab you should work on your own. Useful links:
This lab will have you write a program to load and output image files. In addition, you will provide a user the option to perform some basic image manipulation, including color alteration and horizontal flipping. To begin, we will first learn about the PPM Image format. Click here for information about the PPM format (and how to parse it) as well as tips for viewing and creating PPM image files.
Reading about the PPM format may seem overwhelming, but it's actually fairly simple to get started. At a high level, your program will ask the user to provide both the name of the input PPM image and the name of the file they would like to save the modified PPM to. You will then ask the user which of several image alteration techniques they would like to apply, perform the operations, and save the resulting image.
An aside: compiling your program in lab 1 is a little different from last lab. In this lab, your image manupulation function declarations/definitions will be split into separate helper files ppmEditorHelper.h and ppmEditorHelper.cpp. You must put your image manipulation functions in this file. To make sure C++ knows where to get the code for these functions, you need to include it in the compilation command, like this:
$ g++ -o ppmEditor ppmEditor.cpp ppmEditorHelper.cpp
Here is a sample run of the program where the only options are to convert an image to greyscale and flip it horizontally:
$ g++ -o ppmEditor ppmEditor.cpp ppmEditorHelper.cpp $ ./ppmEditor Welcome to the Portable Pixmap (PPM) Image Editor Enter name of image file: input/machupicchu.ppm Enter name of output file: machupicchu-grey.ppm Do you want to: convert to greyscale? (y/n): y flip horizontally? (y/n): n Session completeThe original and resulting image:
machupicchu.ppm | machupicchu-grey.ppm |
![]() |
![]() |
I recommend implementing your program in 3 phases:
Your program will need to handle opening, reading, closing, and writing to file.
string inputfilename = "image.ppm"; //Get this from the user ifstream inputFile(inputfilename.c_str());
hungry 356 blueYou can use the code:
string verb, color; int number; input >> verb; //"hungry" input >> number; //356 input >> color; //"blue"Notice that the strings do not contain whitespace, and that it automatically skipped the whitespace between 356 and blue. The provided code shows how to read the first two lines of the PPM file, you will need to complete the rest.
string outName = "output.txt"; ofstream outputFile(outName.c_str()); output << verb << endl; output << number << " " << color << endl;
To help read a line of pixels write a function readLine with the following signature:
bool readLine(ifstream& input, int pixels[], int columns)that takes in the input file, your buffer array, and the number of columns for one line of the image. Your function should read one line of the image (NOT necessarily one line of the file) and load the values into the pixels buffer. Note that arrays in C++ are passed-by-pointer, so any modifications to pixels will modify the array designed in the call to readLine (just like in Python!). Your method should return whether the input stream is still valid (HINT: inputFile.good() returns true if everything is in the clear). Your main program should stop if a read fails, output an error message, and quit.
Create a corresponding function for writing one line of data:
void writeLine(ofstream& output, int pixels[], int columns)
Your output file can actually be formatted as you like. Whitespace includes newline characters, so you can put them in where you wish. The format allows for it. Test this with small files and large files. You can check to see if they are identical by loading them both into a text editor like gvim and comparing number by number. Load them into image viewers, as discussed in the PPM Image Format help page listed above. Example ppm files are available in the input folder in your labs directory for this week.
Once you can exactly replicate a PPM image, you can begin writing functions to manipulate the image. At a minimum, you must implement a function to convert an image to greyscale, another to flip the image horizontally, a method to negate all red values, and at least 2 more of your choosing. Let us begin with negating red values.
void negateRed(int pixels [], int columns, int maxColorValue)It will change just the red color numbers into their "negative". That is, if the red number is low, it should become high and vice versa. This depends on the maximum color value. For example, if maximum value is 255 and a pixel had a red value of 0, it would become 255; if it were 255 it would become 0. If the red were 100, it would become 155. It should make changes to the buffer array as described above.
void flipHorizontally(int pixels[], int columns);This function will flip the picture horizontally. That is, the pixel that is on the far right end of the row ends up on the far left of the row and vice versa (remember to preserve RGB order!). This is probably the trickiest of all of image alteration functions, so be sure to think about this carefully and test often.
void greyScale(int pixels[], int columns);which will change the picture into a grey scale image. This is done by averaging the values of all three color numbers for a pixel, the red, green and blue, and then replacing them all by that average. So if the three colors were 25, 75 and 250, the average would be 116, and all three numbers would become 116.
Pick whatever sounds interesting for your other methods. Some ideas include:
Note that you are responsible for determining what parameters are needed for each of these functions (aside from negateRed, flipHorizontally, greyScale which have been provided for you. A more difficult but fun function would be to add random noise to the image. There is plenty of information on how to generate random values in C++ online, or you can come see me or one of the ninjas.
Greet user Ask user for input file (check if valid) Ask user for output file Read header (check if valid) Output header Ask user what filters (image alterations) to apply For each line of the image: Load image into buffer (check if still in valid state) Apply chosen filters Write image to output file Close files, output messageThe menu simply asks the user if they would like to apply each filter you developed. Using a series of yes or no questions. If the user enters an invalid value (you must define this) you should restate the question until a valid response is provided. At all points in your program, you should be defensive against potential user error
See the example at the top of the writeup for an example menu. Your program should apply each filter specified, in succession, one at a time. The filters must be cumulative (even if doesn't make sense in some cases); that is, if the user chooses to flatten all reds and flatten all blues, you should have a resulting picture of only green values.
Once you are satisfied with your code, hand it in by typing handin35. This will copy the code from your cs35/labs/01 to my grading directory. You may run handin35 as many times as you like, and only the most recent submission will be recorded.
This lab write up is based off of Joshua Guerin and Debby Keen's NIFTY 2012 submission titled PPM Image Editor.