
This week you will explore another useful feature of the Zelle Graphics module: creating and manipulating images. You will create Instagram-style filters. This will give you a hands-on introduction to the subfield of computer science called image processing.
The goals this week are to:
Image objects.Create a Lab06 folder on your computer where you store CS151 projects and labs, hopefully somewhere that is backed up (e.g. in Dropbox, Google Drive, Microsoft OneDrive, etc.)
Open VS Code. Create a new Python source code file called show.py.
Open up a Terminal (e.g. Control+` in VS Code) and change the directory (cd) to the Lab06 folder.
Copy each other following files to your Lab06 folder.
| Description | Links |
|---|---|
| Zelle Graphics Module | Zelle Graphics module Documentation (PDF) |
| Helpful function for viewing an image | display.py |
Important: The Zelle Graphics documentation PDF contains a listing of all Zelle Graphics object types, their methods, and how they work. It is helpful to have this open as you work.
Download at least two of the following PPM images to use in the lab exercises. You should right-click on the Image and do "Save Link As..."
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
show.pyLet's practice loading in PPM images as Zelle Image objects and viewing them.
This section is intentionally similar to what we did in class. Try to only consult the code from class if you get stuck so that you can practice, but do use it to check your work.
Create a main function in your show.py file. In it, make an Zelle Image object that represents the PPM image file that you downloaded. Making an Image object is much like making Zelle shape objects:
myImage = gr.Image(gr.Point(x, y), filename)
where (x, y) is where the image appears in the canvas (can be 0, 0) and filename is the name of the PPM file.
Call the displayImage function in the display module (download above) to create a window and display your image. The displayImage function takes two arguments:
Image object to displayThe displayImage function returns a GraphWin object, which you need to assign to a variable (e.g. screen). Add code to keep the window up until the user clicks.
Add main code (in the usual conditional statement) that calls the main function.
Try out your show function. You should see your image displayed in a window until the user clicks.
This will be a useful function throughout this week's lab and project for quickly viewing images that you create.
Our goal is to pass in the PPM image filename to show.py through the Terminal (command line) and have it display that image (rather than showing a hard-coded image, like we did in class). For example, to show geraniums.ppm, you would run the following in the Terminal:
python3 show.py geraniums.ppm
To show the winter scene, you would simply enter the following in the Terminal:
python3 show.py winter.ppm
You do not need to write down the answers to the following questions anywhere. They are intended to guide you toward developing an understanding of how command-line arguments work. Do take them seriously...the topic of command-line arguments is fair game for quizzes.
sys.argv listCreate a new file called lab06args.py. Import the module sys at the top.
Arguments passed in through the command-line are available in the list named argv in the sys module (i.e. sys.argv). In top-level (unindented) main code, copy-and-paste the code:
print('Item 0 in sys.argv:', sys.argv[0]) print('Item 1 in sys.argv:', sys.argv[1]) print('Item 2 in sys.argv:', sys.argv[2]) print('Item 3 in sys.argv:', sys.argv[3]) print('Item 4 in sys.argv:', sys.argv[4])
Save your file and run it as follows:
python3 lab06args.py a b c d
Make sure you understand which items passed in by command-line arguments appear as which items in the list.
Run your file again with these command-line arguments:
python3 lab06args.py i love CS and CS151
Add a print statement to have your program print the CS151 passed in by command-line arguments.
sys.argv list?Add the line of code to lab06args.py:
print(5*sys.argv[2])
Run your file again with these command-line arguments:
python3 lab06args.py 1 2 3 4 5
What is the data type of items in the sys.argv list?
How would you need to change the line to get the multiplication to give you 10?
Run the file as follows:
python3 lab06args.py 1 2 3 4
What happens and why?
This is a common problem with using command-line arguments — it is not clear what values you need to pass in to get the program to run and how many!
For practice, let's require the user to pass in 5 command-line arguments. Check to see if the user passes in any fewer, and if so print the message:
Usage: python3 lab06args.py <int 1> <int 2> <int 3> <int 4> <int 5>
then on the next line call the exit function (this is a built-in Python function like print).
Running the file in the following way should be fine and print out all the command-line arguments:
python3 lab06args.py 1 2 3 4 5
Running the file in the following way should print out the usage statement and close the program cleanly without crashing:
python3 lab06args.py 1 2 3 4
show.pyRecall that you want to pass the image name by command-line arguments:
python3 show.py winter.ppm
The best practice is to only have sys.argv in the code within if __name__ == '__main__'. Determine the image filename from sys.argv there and pass it as a string parameter to main — i.e. your main function should now have a signature that looks like def main(filename):. From now on, I should not see any sys.argv outside of if __name__ == '__main__'!
Test out show.py with at least two different PPM files, for example, as shown above. You should see the appropriate image in the window.
Why this best practice? Your code becomes much less readable and it can be a debugging nightmare tracking down which aspects of your program depend on command-line arguments that may or may not be present. Please ask me to elaborate if you are not convinced!
Now you're going to play with the pixels in an image to create different effects.
Recall that each pixel in a color image has three values (r, g, b). Each pixel is addressed by its row ("y") and column ("x"). The height of the image tells us the number of rows and the width of the image tells us the number of columns.
The Zelle Graphics module contains two functions that make it easy to get and set pixel values if you have an Image object. The three lines below demo how you would:
Image from a file (which you did above)img = graphics.Image(graphics.Point(0,0), 'myImage.ppm') (r, g, b) = img.getPixel(42, 35) img.setPixel(42, 35, graphics.color_rgb(2*r, 2*g, 2*b))
swapBlueGreen that swaps green and blue colors in an imageCreate a new file called filters.py, import graphics, sys, and display.
Copy-and-paste and fill in the below function signature and docstring for the function named swapGreenBlue that takes in one parameter, which is an Image object that you will be modifying.
def swapGreenBlue(img): '''Swaps the green and blue values of every pixel of a Zelle image `img`'''
Hint: You will need to write a nested loop. Also, take a look at lecture notes and/or the Zelle documentation PDF for Image methods.
Create a test function that should take one parameter, the filename (a string) of the image (will be passed in by command-line argument). Except for applying the filter and saving the resulting image, the code should be very similar to what you did in show.py:
swapGreenBlue image filter to the image.Lab06 folder (the filename should not be the same as the original image!). Look at the Zelle documentation to figure out how to save an Image object as a image file on your computer.Add main code that calls your test function and pass in the filename from command-line arguments.
Running filters.py should show you the filtered image (green parts of the original image are blue-ish and vice-versa).
You should also see a new PPM file in your Lab06 folder that is the filtered image. Double check that the saved image file looks right (e.g. pass the filename as a command-line argument to show.py).
Once you are done with each of the lab tasks, you may start on the project.
© 2021 Oliver Layton