Due Date:

Fauxtoshop is due Monday, October 9th at 6:00pm.

This problem is about C++ grids, images and pixels, functions, using libraries, and decomposing a large problem.


Starter Code

We provide a ZIP archive with a starter project that you should download and open with Qt Creator. You will edit and turn in only the following files. The ZIP contains other files/libraries; do not modify these. Your code must work with the other files unmodified.

  • fauxtoshop.cpp, the C++ code for your solution
  • art.png (and art2.png, art3.png, ...): your own unique Fauxtoshop output image(s).


When you are finished, submit your assignment using our Paperless web system.

Program Description:

In this assignment, you'll write your own photo editor with advanced features like green screen, "scatter" blur effect, and edge detection. You'll be making extensive use of our week-1 topics: console interaction and the Grid collection (look for our other collections to show up on assignment 2). For extra spice, there is one easy mouse click interaction. This document is long, but don't let that overwhelm you! (Much of it is just screenshots anyway.) There are plenty of opportunities for artistic expression and creative extensions. I look forward to seeing what you do!

The assignment has several purposes:

  1. To stress the notion of problem decomposition and taking a thoughtful, organized approach to program function and style.
  2. To become more familiar with C++ strings and console I/O.
  3. To gain practice with the Grid data structure.
  4. To evaluate use cases for pass-by-reference parameters vs pass-by-value parameters, and when to use const.

Console Window and Graphical Window

Your program should use the console to support basic menu selections, file name input, and other interactions with the user. Below is a screenshot of the initial welcome screens:

Welcome screen

You'll notice there are two windows: a Console window and a Fauxtoshop window. In the screenshots throughout this document, you will see that what you should print in the window labeled "Console" is in black font, and what the user types is in blue font. The "Fauxtoshop" window is created using the Stanford library graphics class GWindow (refer to Stanford library documentation).

Important note: your program should only ever declare and use one GWindow, and its lifespan should span the entire duration of the program, or else your program may crash. We have declared one in main for you in the starter code, thereby making its lifespan the duration of the program. You should not make other GWindow objects. If you need to use this window in other functions of your code, pass it by reference to avoid making a copy of the window.

Main Menu Sequence

This section outlines the sequence of interactions that take place in the main menu in the console window. Later sections will explain other important components of the program, and detail the behavior of each of the four menu options.

First, greet the user with the welcome message shown, then ask the user to specify an image file name. The image files should be located in the res directory (sibling directory of your src and lib directories in the project directory). When images are located there, Qt Creator will handle making them available to your code without additional path (directory location) information.

To open the image file, declare a GBufferedImage object, and then call the openImageFromFilename function (provided in the starter code in the file fauxtoshop-provided.cpp) to open the file with the image file name the user specified. This function returns a Boolean value, where true indicates success. You should re-prompt the user for a filename if this function returns false. (Tip: If you type "?" as the file name, openImageFromFilename will pop up a graphical file chooser window, which will let you avoid typing out long file names.)

After the image is opened, you'll want to resize the GWindow to be the exact same size as the image, and then add the image to the GWindow by calling add (the code shown below assumes your GBufferedImage object is called img and your GWindow object is called gw, but you could use different names):

// adding a BufferedImage to GWindow
gw.setCanvasSize(img.getWidth(), img.getHeight());
gw.add(&img, 0, 0);

It is important that the GBufferedImage object you add to the GWindow not cease to exist (go out of scope) after you add it to the GWindow. For example, if you make a helper function that declares a GBufferedImage object and adds it to the GWindow, then returns (causing the local variable of the GBufferedImage to go out of scope and cease to exist), this could cause your program to crash! The starter code declares one GBufferedImage in main, and if you use that object throughout the program (by changing the contents, not declaring a new one to add to the GWindow--though you may declare temporary ones that you don't add to the GWindow), you'll avoid any trouble. If you call gw.clear(); , the GWindow will remove and forget about any images it was containing, so it is okay for them to fall out of scope after that.

Below is a screenshot showing the next steps of the interaction after the image is opened and added to the window. It shows a menu of filter effect options and asks the user to select one (if the user enters something other than a valid menu choice, re-prompt with the entire menu text starting with "Which image filter..."). Each menu option has additional input(s) required of the user, which are explained in each menu option section below.

Main menu

Aside: Some of the examples shown in this document may take a very long time to render, depending on the speed of your computer. When opening larger image files than your debugger can handle well, it may appear that the program has frozen. If this happens to you, try working with smaller images.

After the filter effect is complete and displayed in the window, you should ask the user if they want to save the image, as shown in the screenshot below. To save the image file, call the saveImageToFilename function (provided in the starter code in the file fauxtoshop-provided.cpp) with the image file name the user specified. This function returns a Boolean value, where true indicates success. You should re-prompt the user for a file name if this function returns false. (Tip: If you type "?" as the file name, saveImageToFilename will pop up a graphical file chooser window, which will let you avoid typing out long file names.)

Aside: The saved image file will not save in the input images' res directory, where you might expect! Instead, it will save in the build directory created by the compiler to hold its intermediate work and the final compiled executable. The build directory will be found as a sibling directory of the "Fauxtoshop" project directory, and it will have a name something like build-Fauxtoshop-Desktop_Qt_5_2_0_MinGW_32bit-Debug. Usually you should ignore the build directory and not mess with it, but it's fine to look in there for your saved image files.

After offering to save the image, clear the GWindow object so it is blank again (call its clear member function). Print one blank line. Then repeat the entire main menu sequence again (as shown in the screenshot below), until the user enters an empty filename to quit the program.

Repeating the main menu

Working with Images

For each of the filter effects in the menu options, you'll want to iterate over the pixels of the image and inspect or change them. Before doing any such inspection or change of pixels, convert your GBufferedImage object into a Grid<int> collection. The conversion step is as follows (where img is the name of the GBufferedImage object; yours could have a different name):

// converting a BufferedImage to a Grid of ints
Grid<int> original = img.toGrid();

The individual pixels (row/col entries) of the Grid are integers representing RGB values. You can read about the RGB color scheme in detail on Wikipedia or RGBWorld, but the basic idea is that there are three separate values packed into one int: a value between 0 and 255 representing how much Red, a value between 0 and 255 representing how much Green, and a value between 0 and 255 representing how much Blue. The red, green, and blue combine together to make one particular pixel's color. By varying the red, green, and blue values, we can make all the colors of the rainbow. It's a slightly different version of the Primary Colors concept you learned as a kid. In the starter code, three color values are defined for you as constants:

// pre-defined color constants
const int WHITE = 0xFFFFFF;
const int BLACK = 0x000000;
const int GREEN = 0x00FF00;

Aside: These numbers are written in base 16 (called "hexadecimal"), which you don't need to worry too much about. They still behave as any other literal value of type int. For the curious: The first two digits represent red, the second two digits represent green, and the third two digits represent blue. So in the case of white, the red, green, and blue components all have the maximum value of 255 (base 10) or "FF" (base 16). On the other hand, green has the maximum value of green (the middle two digits are "FF") and 0 of red and blue.

We have a nice helper function provided for you in the Stanford libraries that separates the pixel ints into their individual RGB components for you (it's a nice example of "returning" three values using pass-by-reference). Here is an example for one pixel (where original is the name of a Grid<int> object, and row and col are integers; as usual, you may choose different names):

// getting the red/green/blue components of a pixel
int pixel = original[row][col];
int red, green, blue;
GBufferedImage::getRedGreenBlue(pixel, red, green, blue);

Aside: The GBufferedImage::getRedGreenBlue syntax might look new or strange to you. The :: is called the scope resolution operator, and it indicates that the getRedGreenBlue function can be found in the GBufferedImage class, but that you do not need an instance of the class to use the function (that is, it is a static function in the same sense of the word static that you may have seen in Java). You don't really need to worry about exactly what this means until we talk about it later in the course. Just use the function as if its "full name" is GBufferedImage::getRedGreenBlue.

You should not use the GBufferedImage member functions such as setColor or setRGB that set individual pixels in the image. Instead, make all the changes you want in a Grid<int> object, and then change the image all at once by calling the img.fromGrid (where img is the name of your GBufferedImage instance), which takes a Grid<int> as its argument. There are two reasons for this requirement: one is efficiency, and the other is to get you to practice using the Grid collection by doing looping and operations there rather than in the image object directly.

RGB Color "Difference" Calculation

For both the edge detection and green screen effects, your program will need to have a way of calculating the "difference" between two colors. There are a number of ways to do this, and in fact exploring alternate calculations could be one of the extensions you do for this assignment.

To earn points for the basic assignment you'll need to precisely implement our algorithm (and not some other algorithm, however reasonable).

  1. Use the GBufferedImage::getRedGreenBlue member function described above to separate the pixels into their RGB components.
  2. Take the difference between each pair of RGB values (difference between the two reds, difference between the two blues, and difference between the two greens).
  3. Take the absolute values of each difference so you have the magnitude of each difference. Note the <math> standard library has an integer abs function.
  4. Then take the max of those three differences (there is also a max function that takes two values at a time).

That is going to be our definition of difference between pixels. Note, all calculations should be done using type int, not double/float.

Menu Option 1: Scatter

For this filter, your program will take the original image and "scatter" its pixels, making something that looks like a sand drawing that was shaken.

First, ask the user to provide a "radius" (it's not quite a radius, mathematically) of how far we should scatter pixels. The value should be an integer between 1 and 100, inclusive (otherwise re-prompt).

Then create a new image Grid that has the same dimensions as the original image Grid. Next, for each pixel in the new image, randomly select a pixel from nearby that row and column in the original image that will provide the color for this pixel in the new image. You will randomly select the pixel by randomly selecting a row that is within radius of the current row, and randomly selecting a column that is within radius of the current column. If the randomly selected row or column is out of bounds of the Grid of the original image, you should randomly select again until you get an in-bounds pixel.

Here is a screenshot of the Scatter filter effect complete, waiting for the user to respond to the prompt about saving the file (notice we haven't cleared the window yet):

Scatter filter

Note: Since the Scatter operation uses randomness, it produces a different output each time, even if you run it on the same image with the same radius. If you want to try to match our expected outputs exactly, you can call the provided function fakeRandomNumberGenerator(); at the start of your program's main function, which will cause the random number generator to always return the same sequence of integers every time you call it. To match our output, you would also have to use these fake random numbers in row-major order to generate "dr" and "dc" values, offsets from the image's original row and column for each pixel. You are not required to do this to get full credit; it's optional and is only useful to verify that your implementation exactly matches ours.

Menu Option 2: Edge Detection

For this filter, your program will create a new black and white image of the same size as the original, where a given pixel is black if it was an edge in the original image, and white if it was not an edge in the original image.

First, ask the user for a threshold that controls how different two adjacent pixels must be from each other to be considered an "edge." This should be a positive (nonzero) integer value (otherwise re-prompt). Then, loop over each pixel and determine if it is an edge or not.

A pixel is defined as an edge if at least one of its neighbors has a difference of greater than threshold from it. The neighbors are the 9 pixels (including self) immediately adjacent or diagonal from the current "self" row/column of the Grid. So if my distances to my neighbors are: 9, 8, 5, 3, 3, 0 (self), 4, 7, 8, 7, then I would only be considered an edge if the threshold were less than 9 (the greatest difference between me and one of my neighbors). Remember that pixels near edges and corners may not have all 9 neighbors, so take care not to go out of bounds. The Grid class has an inBounds member function that will be helpful.

Here is a screenshot of the Edge Detection filter effect complete, waiting for the user to respond to the prompt about saving the file (notice we haven't cleared the window yet):

Edge Detection filter

Menu Option 3: Green Screen

For this filter, your program will paste a "sticker" image on top of a "background" image, but ignore any part of the sticker that is close to pure green in color. This technique is used widely in filmmaking--actors are filmed acting on a stage that is painted bright green and then their forms are later digitally placed on top of some other scenery.

The image that the user specifies in the main menu will be the background image, so the first thing you should do for this filter effect is ask the user to specify a new image file name to be the sticker image. The prompt will work in a similar fashion (re-prompt if open fails), but you will not offer the option to enter a blank filename to indicate ending the program. Open the image file and convert it to a Grid in the same way you did with the original background image.

Next, we need to know how much tolerance we should have for green that isn't pure green (0x00FF00). That way if there are slight shadows or other variations on the green part of the image, the green screen effect will still work as we want it to. Prompt the user to enter a value, and then you'll use that as a threshold in conjunction with the same pixel color difference calculation that we used in edge detection (described above). Your code should re-prompt until the tolerance is between 0 and 100 inclusive.

Next, we need to know where to place the sticker image. Ask the user to specify a location as (row,col) in exactly that format, with row and col being non-negative integers (otherwise re-prompt). The row and column specified will be the background location where you will place the upper left corner of the sticker. The only variation from that exact (row,col) format that you should allow is for the user to enter nothing (just hits Enter), in which case you should allow the user to specify the location use a mouse click. The starter code includes a function that receives mouse clicks and reports the location to you as row and column. You should report back to the user the detected click location.

Now we are ready to place the image in the location specified. Any pixel on the sticker image that is difference greater than threshold from pure green will be copied onto the background, otherwise that pixel will be ignored and the background pixel there will remain untouched. You should allow the sticker image to be cut off on the bottom or right edge(s) if it cannot completely fit on the background.

Here is a screenshot of the Green Screen filter effect complete, waiting for the user to respond to the prompt about saving the file (notice we haven't cleared the window yet):

Green Screen filter

Here is a screenshot of the Green Screen filter effect complete in the case where the user clicked to give the sticker location:

Green Screen filter with click

Menu Option 4: Compare Images

This is the least exciting of the menu options, and it does not produce any visual effect. However, it will help you debug your code by comparing your output to the sample outputs provided on the course website. For this menu option, ask the user to name another image file (open it as a GBufferedImage in the same way described in the Green Screen section), and you will count how many pixels differ between the two.

This would be easy to do by iterating over the pixels yourself, but it's actually even easier than that; there is a countDiffPixels member function in the GBufferedImage class that does all the work for you. Use it, then report the result to the user. Print a nonzero count as "These images differ in _ pixel locations!" or print "These images are the same!" as applicable. You will continue to display the original image. Your main menu should not ask the user if they want to save the resulting image in this case, since no new image is generated. Here is a screenshot showing this menu option in action:

Compare Images option

In addition to printing the number of differing pixels, if the images are not the same, you should also pop up a graphical window to display the differences. To do this, call the instructor-provided function showDiffWindow, passing it your GWindow and the second image's file name as parameters. You can ask a BufferedImage for its filename by calling getFilename() on it as shown below. (The code shown below assumes your GWindow object is called gw and your GBufferedImage object is called otherImg, but you could use different names):

// pop up a window to display differences between the two images
showDiffWindow(gw, otherImg);

The following screenshot shows an example output from showDiffWindow when the GWindow is displaying rainbow.png and the other image to compare against is rainbow-love-you.png:

showDiffWindow output (for rainbow.png and rainbow-love-you.png)

Example Logs of Execution:

Here is an example log of interaction from your program (with user input bolded). Your output must match this format exactly to earn full credit. (We are very picky.)

Welcome to Fauxtoshop!
Enter name of image file to open (or blank to quit): kitten.jpg
Opening image file, may take a minute...
Which image filter would you like to apply?
    1 - Scatter
    2 - Edge detection
    3 - "Green screen" with another image
    4 - Compare image with another image
Your choice: 1
Enter degree of scatter [1-100]: 999
Enter degree of scatter [1-100]: -5
Enter degree of scatter [1-100]: 10
Enter filename to save image (or blank to skip saving): kitten-scatter-10.png

Enter name of image file to open (or blank to quit): oops-not-found.png
Opening image file, may take a minute...
Enter name of image file to open (or blank to quit): kitten-scatter-10.png
Opening image file, may take a minute...
Which image filter would you like to apply?
    1 - Scatter
    2 - Edge detection
    3 - "Green screen" with another image
    4 - Compare image with another image
Your choice: what?
Illegal integer format. Try again.
Your choice: 0
Which image filter would you like to apply?
    1 - Scatter
    2 - Edge detection
    3 - "Green screen" with another image
    4 - Compare image with another image
Your choice: 4
Now choose another image file to compare to.
Enter name of image file to open: bad-image-file-wont-be-found.png
Opening image file, may take a minute...
Enter name of image file to open: expected-output-kitten-scatter-10.png
Opening image file, may take a minute...
These images are the same!

Enter name of image file to open (or blank to quit): 
Example log of execution

Here are some additional expected output files to compare:

  • test #1 (kitten scatter 10)
  • test #2 (pusheen edge detect 30)
  • test #3 (stanford-oval greenscreen godzilla)
  • test #4 (compare rainbow to rainbow-love-you)

Tired of typing? Your program's Console window has a File → Compare Output feature for checking your output, as well as a Load Input Script feature that can auto-type the user console input for you. Use them!

The "Load Input Script" feature of the console window

Creative Aspect, art.png:

Along with your code, submit an image named art.png that you created using your code (use the Save resulting image option to save the file). You should use several of the filter effects in combination (e.g., multiple green screen stickers, one of them edges only or scattered), by saving interim files and reading them in as input to the next step. Although you may use one of the images provided in the starter code to generate your piece of artwork, it should include an image of your own that was not part of the starter code (e.g., your own photo, or something you sourced from the internet). You may use some of your extensions (if any) in making this artwork file if you like. This is worth a small part of your grade.

If you enjoy this part of the assignment and want to submit multiple art files, feel free to do so. Name them art.png, art2.png, art3.png and so on.

Style Details:

To achieve a high style score, submit a program with high code quality that conforms to the guidelines presented in our course. There are many general C++ coding styles that you should follow, such as naming, indentation, commenting, avoiding redundancy, etc. While there are many valid programming styles in various contexts, the most important overall stylistic trait a programmer can have is the ability to be given a set of style guidelines and follow them rigorously and consistently. In the context of this course, our style guides and constraints are the laws of the land and are not open for debate.

Before getting started, you should read our Style Guide for information about expected coding style. You are expected to follow the Style Guide on all homework code. The following are some points of emphasis and style contraints specific to this problem:

C++ idioms: For full credit, you must use C++ facilities (cout, ifstream, string) instead of C equivalents (printf, fopen, char*).

Procedural decomposition: Your main function should represent a concise summary of the overall program. It is okay for main to contain some code, such as calls to other functions or brief console output statements to cout. But main should not perform too large a share of the overall work itself directly, such as reading the lines of the input file or prompting the user to replace placeholders. Instead, it should make calls to other functions to help it achieve the overall goal. You should declare function prototypes (each function's header followed by a semicolon) near the top of your file for all functions besides main, regardless of whether this is necessary for the program to compile.

Each function should perform a single clear and coherent task. No one function should do too large a share of the overall work. As a rough estimate, a function whose body (excluding the header and closing brace) has more than 30 lines is likely too large. You should avoid "chaining" long sequences of function calls together without coming back to main, as described in the Procedural Design Heuristics handout on the course web site. Your functions should also be used to help you avoid redundant code. If you are performing identical or very similar commands repeatedly, factor out the common code and logic into a helper function, or otherwise remove the redundancy.

Parameters, Returns, Values, References: Since your program will have several functions and those functions will want to share information, you will need to appropriately pass parameters and/or return values between the functions. Each function's parameters and return values should be well chosen. Do not declare unnecessary parameters that are not needed by your function. A particular point of emphasis on this assignment is that you should demonstrate that you understand when it is proper to pass by reference, and when it is proper for a parameter to be declared const. As much as possible, pass collections and objects by reference, and const reference when applicable, because passing them by value makes an expensive copy. You should also demonstrate that you understand when it is better to return a result and when it is better to store a result into an 'output' reference parameter.

Variables and types: Use descriptive variable and function names. Use appropriate data types for each variable and parameter; for example, do not use a double if the variable is intended to hold an integer, and do not use an int if the variable is storing a true/false state that would be better suited to a bool. When manipulating strings, favor talking to string objects over individual char values when possible, and use the string object's built-in member functions as opposed to rewriting similar behavior yourself. Do not declare any global variables or static variables; every variable in your program must be declared inside one of your functions and must exist in only that scope. No single variable's scope should extend beyond a single invocation of a single function.

Commenting: Your code should have adequate commenting. The top of your file should have a descriptive comment header with your name, a description of the assignment, and a citation of all sources you used to help you write your program. Each function should have a comment header describing that function's behavior, any parameters it accepts and any values it returns, and any assumptions the function makes about how it will be used. For larger functions, you should also place a brief inline comment on any complex sections of code to explain what the code is doing. See the programs written in lecture or the Course Style Guide for examples of proper commenting.

Collections: Use the Grid and other Stanford library tools. Do not use pointers, arrays, or STL containers on this program. You should not be explicitly allocating or freeing any memory for this assignment (goes along with no pointers).

If you refer to any non-class resource (person, website, your own previous coding projects that are substantially similar), you need to make a clear citation of that fact in the code. Please refer to the Honor Code for CS106A+B+X for more detail.

Project size: While high quality solutions can vary widely in length, some students find it helpful to know, as a general point of reference, how many lines of code our solution is. Our solution is about 300 lines of code, including #include, comments, etc.

Frequently Asked Questions (FAQ):

For each assignment problem, we receive various frequent student questions. The answers to some of those questions can be found below.

NOTE: On this first assignment, many students have issues with setting up their Qt Creator software. If your problem or issue is more about that software than it is about HW1 specifically, you should also check out our Qt Creator troubleshooting page for possible solutions.

Q: Can I work with a partner on this assignment?
A: No. This assignment is an individual assignment, so you should work individually and submit your own solution. Do not show your code to any other student and do not develop your solution with a partner.
Q: You said I need to use Qt Creator to write my homework, but I prefer a different editor (Visual Studio, Xcode, Eclipse, Netbeans, vim, emacs, etc.). Can I use my favorite editor instead of Qt Creator?
A: Probably not. We don't support this. We are giving out a starter project in Qt Creator's format, so if you were trying to use a different editor, you'd have to disassemble that starter project and put it back together in your editor's format, which might be difficult. Also, if you have any problems getting things to work in your editor, we will not be willing to help you fix them.
Q: I'm having trouble getting Qt Creator to work! Help!
A: Please make sure you followed the instructions in our Qt Creator page. If you are still having trouble, please see our Tricky C++ Issues page for some possible solutions.
Q: When I try to compile my program I see an error message, "cannot open output file ...\Fauxtoshop.exe: Permission denied". What does it mean? How do I fix it?
A: It means that your Fauxtoshop executable is still running from the last time you ran/tested the program a moment ago. Make sure to shut down any previously running instances of your program. Click Qt Creator's "3 Application Output" tab and click any of the red square "stop" sign buttons you see. You might also need to open your operating system's Task Manager to stop them all.
Q: Will my solution get full credit? Is it written in the style you want? Will I get marked off for this code?
A: In general we cannot answer these kinds of questions. We call this "pre-grading." The section leader/TA/instructor can't look over your entire program for mistakes or tell you exactly what things you will get marked off for; we don't have the resources to provide such a service, and even if we did, we want you to learn how to gain these intuitions on your own. We'll grade you on the guidelines in the homework document, and we can help you with specific issues and questions about your code, but we cannot pre-evaluate your entire program for you or give you advance warning about every possible mistake or violation.
Q: Is my art.png file okay? Will it get full credit?
A: Our grading is pretty lenient on a creative part aspect like this. If it meets the criteria in the assignment spec, it should get full credit, even if it is not particularly creative or exciting.

(Optional) Extra Feature Suggestions:

This assignment offers lots of opportunity to create fun and interesting extra features ("extensions"). For any extensions you write, make their use go through a new top level menu item, so autograders can still test your program using menu items 1-4 and expect them to perform exactly according to specification. So, for example, if you change the behavior of green screen, make a new top level menu item 5 titled something like "Improved green screen."

Edge detection extension suggestions:

  • As mentioned in the section on difference calculation, you may want to experiment with alternate formulas for calculating the difference in color between two pixels. The edges will be sharper if you select a difference calculation where difference(a, b) does not equal difference(b, a) (for nonzero differences; i.e., produce a signed output), because then only one of the two pixels will decide it meets threshold to be an edge. One reasonable idea for a distance calculation would be Euclidean distance between RGB values treated as vectors of dimension 3.
  • There are more advanced edge detection algorithms that you could use, especially if you are experienced in linear algebra. Wikipedia page for edge detection is a good place to start. Hough Transform is a really cool one that specializes in finding straight lines or circles (google it).

Green screen extension suggestions:

  • Let the user specify an RGB value to use instead of green (e.g., sometimes you'll see blue screen instead of green screen in filmmaking). This could be done by typing the RGB value, or, if you initially show the entire sticker in the window, allowing the user to click a pixel to select the color.
  • Ask the user specify a resizing factor to scale the sticker image up or down for a better fit to the scene.
  • Allow the user to rotate the sticker image or flip horizontal/vertical.

Scatter extension suggestions:

  • There are many more interesting blur/smudge type algorithms, such as incorporating an average of neighboring pixels (for some radius of neighbor), or Gaussian blur. Research and implement one of these algorithms. To help you implement Gaussian blur, the starter code includes a function that calculates a Gaussian kernel for you (that's the trickiest part).
  • Let the user specify one specific area to scatter, rather than the whole image. This could be useful for anonymizing images by blurring a faces or private data.

General extension suggestions:

  • Create composite filters that automate multi-step operations (e.g., first do edge detection on an image that you will then use as a sticker in a particular place, etc.). You could even insert pauses between the executions of each step, so it looks like a simple animation. To add a pause, use the function pause(milliseconds);.
  • Add various color effects filters: grayscale, black and white, sepia tone, negative. All of these are very simple manipulations of the RGB values for each pixel.
  • Allow users to flip horizontal/vertical and rotate the image. Resize is another option, but unlike the others it does not preserve each pixel exactly, so you'll need to think through the algorithm for that (there are lots of nice and easy options - search Google).
  • A really neat trick that is surprisingly easy is steganography combination of two images. You'll want to include an option to both encode a message/image, and recover the secretly encoded message/image.
  • Add a GUI menu interface (must be in addition to our console-based menu interface).
  • Add brush/pen/pencil drawing on the photo using the mouse.
  • Add bucket fill, or bucket fill with a tolerance for non-exact colors (using your color difference calculation again). The algorithm to fill an area is something we'll cover later in the quarter, but you could read ahead if you are interested in trying this.

If you do any extensions that require any additional image files for the grader to operate your extension options, please make sure to turn in those additional files. Be sure your code includes comments and/or cout statements that make it clear to the grader how to operate your extensions.

Honor Code Reminder:

You are expected to follow the Stanford Honor Code.

  • In your file's comment header, list your name; also cite all sources of help, including books, web pages, friends, section leaders, etc.
  • Do not consult any assignment solutions that are not your (pair's) own.
  • Do not attempt to disguise any code that is not your (pair's) own.
  • Do not give out your assignment solution to another student.
  • Do not post your homework solution code online. (e.g. PasteBin, DropBox, web forums).
  • Please take steps to ensure that your work is not easily copied by others.

Remember that we run similarity-detection software over all solutions, including this quarter and past quarters, as well as any solutions we find on the web.

If you need help solving an assignment, we are happy to help you. You can go to the LaIR, or the course message forum, or email your section leader, or visit the instructor/Head TA during their office hours. You can do it!