Lab Exercise 4: Images
The main purpose of this lab is to give you the tools you need to complete an image-manipulation project. You will be using John Zelle's graphics package. Here is the reference guide.
- In your personal file space, make a folder called Project4. Then download the following files to it.
- Open a text editor (e.g TextWrangler). Create a new file called show.py. Put a comment at the top of the file with your name and the date. Save it in your Project4 folder.
After the comment line, write the command to tell Python to import the
graphics package, the display package, and the sys package:
- Download one of the following images to use in the lab exercises. You should right-click on the Image and do "Save Link As..."
The first thing we're going to do is create a simple program that will
read image data from a file and display it in a window. We'll use the
command line to specify the filename of the image to view.
Create a main function in your show.py file. Give it one argument, while will be the list of strings from the command line. One of these strings should be the filename of the image to open and view. The main function should do the following.
- Test if there are at least two strings in the main function parameter: the name of the python program and the filename of the image to open. If there are not at least two strings, print a usage message and exit using the exit() function. Use the len() function to test how many strings there are in the list.
- Load image data from the file specified in the
second string of the main function parameter into an Image. You can do
this by calling the function graphics.Image() with a Zell
Point object as the first argument and the filename as the second
argument. The filename will be the second element in the list argv that
is the parameter of your main function. You want to assign the return
value of the graphics.Image function to a variable.
Any time we need to store, retain, or assign information, we need to use an assignment statement. In this case, we want to store the Image object created by the graphics.Image() function call. Therefore, you need a variable on the left side of an assignment and the graphics.Image() function call on the right.
- Use the displayImage function in the display package to create a window and display the Image. It takes two arguments, which are the Image to display and the title to be displayed in the window. You could use the filename as the title of the window. The displayImage function returns a window reference, which you need to assign to a variable. That means the variable to hold the window reference must be on the left side of an assignment and the function call must be on the right.
- Finally, call the getMouse method of the window. That means you type the name of the variable holding the window reference, then .getMouse() to call the method. This will wait for a mouse click in the window and then go on to the next instruction. If there is no next instruction, the program will terminate.
Below the main function, put a conditional call to it, using the method we learned last week. Pass the main function the list sys.argv.
if __name__ == "__main__": main(sys.argv)
Once complete, try out your show function. On the terminal, make sure you are in the correct working directory and then run your program with an image filename as a command line argument.
python3 show.py geraniums.ppm
The second thing we're going to do in lab is figure out how to
manipulate pixels in an image. Each pixel in a color image has three
values (r, g, b). Each pixel is addressed by its row and column.
There are rows x columns pixels in an image. The Zelle graphics
library (graphics.py) contains two functions that make it easy to get
and set pixels if you have an Image object. The three lines below
demonstrate how you would read in a Image from a file (which we did
above) and then swap the red and blue channels of pixel 42 (x), 35
img = graphics.Image(graphics.Point(0,0), 'myImage.ppm' ) (r, g, b) = img.getPixel( 42, 35 ) img.setPixel( 42, 35, graphics.color_rgb(b, g, r ) )
- Create a new file called filter.py. Do the usual stuff of putting your name and a date at the top. Then import graphics and sys. Save it in your Project4 directory.
Create a function named something like swapRedBlue that takes
in one argument, which will be a Image object. The algorithm is
written below as comments, properly indented. Read through them and
make sure you understand the process. Then fill in the python
code. After the Python code has been written, please remove these
comments. They do not make the code any more readable, as they are
just the English version of the code.
def swapRedBlue( src ): # loop over each row row_idx # loop over each column col_idx # get the r, g, b values of the pixel indexed by (col_idx, row_idx) # set the pixel indexed by (col_idx, row_idx) to the value (b, g, r) # return
Create a new test function in filter.py (this is a different function than swapRedBlue) that takes in an
argument which is the list of strings from the command line. You can use show.py as an example for your test function. As in that example,
first test if there are enough arguments and print out a usage
statement and exit if there are not. If there are enough arguments,
then open the image and store the result in a variable. Pass the
Image to the swapRedBlue function, then save the result to a
file. If your Image variable were img, then you could save
it by using
You can pass whatever filename name you want to the save function. I'd recommend not having spaces in the name.
At the end of your filter.py file, put a call to your test function behind a conditional that tests the value of the __name__ variable, as we did last week.
if __name__ == "__main__": test( sys.argv )
Note that this is the only place in your filter.py file where you should use the sys.argv variable. if you are using it in any of your functions, then you are not making proper use of the function parameters.
When you are done, run your filter.py program, giving it an image filename as the argument. Then look at the result with your show program. Now, perhaps, you see why command line parameters are useful.
If you would like to use any additional photos, then you may want to make the images smaller for testing. You can use the convert program to change the size of any image.
convert myImage.jpg -scale 25% mySmallImage.jpg
You can also change an image of one format to a different format. The Zelle graphics library can open only PPM format images, not JPGs. You can change a JPG to a PPM using one of the following examples.
convert myImage.jpg myImage.ppm
PNG and JPG images are the formats for you will need to use for your reports or for web pages. Note that you can change the format and change the scale at the same time.
convert myImage.jpg -scale 25% myImage.ppm
The convert program is a very powerful application for manipulating images. If you want to find out more about it, check out the ImageMagick web site.
When you are done with the lab exercises, you may begin the project.