At the conclusion of this programming assignment, participants should be able to:
Before starting this programming assignment, participants should be able to:
Content used in this assignment is based upon information in the following sources:
The PPM image format is encoded in human-readable plain text. A PPM image has two main parts:
The header is always the top three uncommented lines in the file:
P3
4 4
255
The first line specifies the image encoding that is contained within the file. We will always use the "P3" specification. The second line specifies the number of pixel columns and rows present in the image. In this example, we have a 4 pixel by 4 pixel image. The final number indicates the maximum value for each red, green, and blue (RGB) element in the picture. We will always use a max value of 255.
Below the header is the body of the PPM file. Each pixel has a red, green, and blue value. For example, the body content of our 4x4 image might be:
255 0 0 0 255 0 0 0 255 255 255 255
0 0 0 255 0 0 0 255 0 0 0 255
255 0 255 0 0 0 255 0 0 0 255 0
0 255 255 255 0 255 0 0 0 255 0 0
With these values, the pixel in the first column and first row has a RGB value of (255, 0, 0), which equates to red. The pixel in the last column and the first row has a RGB value of (255, 255, 255), which equates to white. A blown-up image containing these values would look like:
Note: You can explore RGB color values at [this website](http://www.colorpicker.com/).Download this PPM image of the NY sky line: ny.ppm. You can open the image with software such as Ifranview to view it as an image. You can also open it as a text file (in Spyder IDE or a text editor) to view it as plain text (useful for debugging your code!).
(Image from [https://pixabay.com/en/new-york-skyline-manhattan-hudson-540807/](https://pixabay.com/en/new-york-skyline-manhattan-hudson-540807/))Write a program to prompt the user for the name of an input PPM image. Produce an output PPM image file for each of the following modifications to the input PPM image:
Provide status updates to the console regarding your program's progress applying the above modifications.
In your program, the PPM image data must be stored in a 2-dimensional list (pixel rows and columns) of tuples. Each tuple represents an RGB triple, e.g. (red value, green value, blue value).
At a minimum, your solution must contain the functions below. These functions will help you get started!
Required file I/O functions:
process_header(infile, outfile)
: Accepts input and output file objects. Writes the first three lines of the input image to the output image (no need to modify these lines)process_body(infile, outfile, modification)
: Accepts an input file object, output file object, and a string representing the modification to apply. Calls load_image_data()
and calls the appropriate function to apply the specified modification according to modification
.load_image_data(infile)
: Accepts an input file object. Reads the data in from the input PPM image into a 2-dimensional list of RGB tuples. Returns the 2-dimensional list.Note: with the above functional decomposition we are going to open/process/close the input file for every modification. Is this necessary? If you state in a comment block at the top of the code that you are going to implement this more efficient approach, you are free to change the above function headers.
Required image modification functions:
apply_vertical_flip(image_2dlist, outfile)
: Accepts a 2-dimensional list of tuples and an output file object. Flips the image data in image_2dlist
vertically.apply_horizontal_flip(image_2dlist, outfile)
: Accepts a 2-dimensional list of tuples and an output file object. Flips the image data in image_2dlist
horizontally.apply_horizontal_blur(image_2dlist, outfile)
: Accepts a 2-dimensional list of tuples and an output file object. Horizontally blurs the image data in image_2dlist
.Required RGB tuple/value modification functions:
negative(num)
: Accepts a single integer RGB value. Subtracts 255 and takes the absolute value of the result. Returns the modified value.high_contrast(num)
: Accepts a single integer RGB value. If the value is greater than 127, sets it to 255, otherwise sets it to 0. Returns the modified value.random_noise(num)
: Accepts a single integer RGB value. Generates a random number in the range [-50, 50] and adds it to the value. Returns the modified value.gray_scale(rgb)
: Accepts a RGB tuple. Computes the average of the RGB values in the tuple. Returns a new tuple with each RGB value is the average.remove_color(rbg, color_to_remove)
: Accepts a RGB tuple and a string representing the color to remove (e.g. "r", "g", or "b"). Returns a new tuple with the appropriate red, green, or blue value set to 0.A main()
function that drives your program.
Negative line example: 1 2 3 200 100 150
negated is 254 253 252 55 155 105
High contrast line example: 1 2 3 200 100 150
in high contrast is 0 0 0 255 0 255
Gray scale line example: 1 2 3 200 100 150
as gray scale is 2 2 2 150 150 150
.
Remove green line example: 1 2 3 200 100 150
without green is 1 0 3 200 0 150
Here is an example run of the program (including the bonus):
Please enter the name of the input PPM image file: ny.ppm
Opening ny.ppm for reading and ny_negative.ppm for writing...
Image modification "negative" complete. Closing files...
Opening ny.ppm for reading and ny_high_contrast.ppm for writing...
Image modification "high contrast" complete. Closing files...
Opening ny.ppm for reading and ny_remove_red.ppm for writing...
Image modification "remove red" complete. Closing files...
Opening ny.ppm for reading and ny_remove_green.ppm for writing...
Image modification "remove green" complete. Closing files...
Opening ny.ppm for reading and ny_remove_blue.ppm for writing...
Image modification "remove blue" complete. Closing files...
Opening ny.ppm for reading and ny_gray_scale.ppm for writing...
Image modification "gray scale" complete. Closing files...
Opening ny.ppm for reading and ny_vertical_flip.ppm for writing...
Image modification "vertical flip" complete. Closing files...
Opening ny.ppm for reading and ny_horizontal_flip.ppm for writing...
Image modification "horizontal flip" complete. Closing files...
Opening ny.ppm for reading and ny_random_50.ppm for writing...
Image modification "random 50" complete. Closing files...
(Bonus) Opening ny.ppm for reading and ny_horizontal_blur.ppm for writing...
(Bonus) Image modification "horizontal blur" complete. Closing files...
Exiting program...
Here are the image files to compare with:
Implement a "horizontal blur" which will replace every 5 RGB triples with the average of those 5 RGB triples. More specifically, a red value will be replaced with the average of itself and its four adjacent red values. Your program will do this for the green and blue values as well. Note that pixels on the edges will have to be handled specially.
os
Module (5 pts)¶Validate the input file specified by the user is valid, i.e. the input file adheres to the following requirements:
If the user specifies an invalid input file, tell the user why the file is invalid, and re-prompt until a valid file is specified by the user.
Hint: To check if a file exists, import the os
module and call the predicate function os.path.isfile(<string file name>)
:
import os.path
print(os.path.isfile("ny.ppm"))
print(os.path.isfile("file_that_doesnt_exist.ppm"))
True False
<your last name>_pa6.zip
by the due date and time.Note: By submitting your code to be graded, you are stating that your submission does not violate the CptS 111 Academic Integrity Policy outlined in the Syllabus.
This assignment is worth 125 points + 10 points bonus. Your assignment will be evaluated based on a successful compilation and adherence to the program requirements. We will grade according to the following criteria:
A main()
function that drives your program.
process_header()
load_image_data()
and storage of PPM image data in a 2-dimensional list of RGB tuplesprocess_body()
(and other helper functions you define)apply_vertical_flip()
apply_horizontal_flip()
negative()
high_contrast()
random_noise()
gray_scale()
remove_color()
main()