Lab Exercise 4:
Images

One of Python's strengths is that there are a large number of built-in and third-party packages available for working with different kinds of data. For the next three weeks we will be working with images using the Python Imaging Library (PIL).

PIL is is a third-party package—unlike Turtle Graphics, it is not part of the default Python packages. If you usually work on your personal computer, you will need to install PIL (see FAQ). The install can be difficult, so do not hesitate to work on the lab machines instead.

Tasks

  1. Get your picture taken.
  2. Create a directory for project 4 (e.g. project4) and download the following file to it: pilutil.py
  3. Download your picture from the photos page when it is available. Until then, use one of the other images on that page.

    When you download your picture, you will want to make a smaller copy of it. You can do this using the convert command from the terminal. Use one of the following commands; the second version rotates the image to the left, which might be useful for your portrait.

    $ convert myImage.jpg -scale 25% mySmallImage.jpg
    
    $ convert myImage.jpg -rotate -90 -scale 25% mySmallImage.jpg
    

    The convert program is a very powerful application for manipulating images, with many command line parameters to control the manipulations. If you want to find out more about it, check out the ImageMagick web site.

  4. The first thing we are going to do is create a simple program that will read in an image and display it in a window. We will use a command line parameter to specify which image to view so we can display any image without editing our program. In other words, when we type the line below at the terminal, our program will display the image in a window.
    $ python show.py myimage.jpg

    Create a file named show.py in the project4 directory; write a comment at the top of the file with your name and the date.

    Import the Image, pilutil, and sys packages:

    import Image
    import pilutil
    import sys
    

    Create a function named main(args) in your show.py file. The args parameter will be the list of strings the user typed on the command line. The function should do the following:

    1. Test if there are fewer than two strings in the args parameter. If so, print a usage message and exit the program using the exit() function.
    2. Assign to a variable named filename the value of the element with index 1 in the args list.
    3. Load the file specified by the filename variable as a PIL Image. (Where Image is capitalized, this refers to a PIL Image object, which is the type used to store image data and functions.) Do this by assigning to a variable image the result of calling the function Image.open() with the filename as the only argument.
    4. Use the display() function in the pilutil package to create a window and display the Image. This function expects two arguments: the Image to display and a title for the window. Use the filename as the title of the window.
    5. Finally, call the wait() function in the pilutil package. This will wait for the image window to be closed or for a q or esc key press before continuing to the next statement in the program. If there is no next statement, the program will terminate.

    Below the main function, put a conditional call to it, using the approach we learned last week. Pass the main function the list of command line arguments, sys.argv.

    if __name__ == "__main__":
        main(sys.argv)
    

    Once complete, try out your show program on the image you downloaded and converted.

    $ python show.py mypicture.jpg
    
  5. The second thing we are going to do in lab is figure out how to manipulate the contents of an image. An image is a regular 2D array of picture elements (pixels). Each pixel is addressed by its column (x) and row (y) position in the array. There are (columns x rows) total pixels in an image. Each pixel in a color image is a triplet of three values (r, g, b).

    The value returned from the Image.open() function is actually an Image object. An object is a data type that contains both data and functions. In other words, given an Image variable, e.g. image, one can access information about the image or modify the image using functions on the Image object itself, e.g. image.getpixel( (42, 35) )

    To further illustrate, the following lines demonstrate how to load an image, then determine the size of the image (width x height), access the color value stored at an individual pixel, and modify the color value of that pixel. In this case, we are swapping the red and blue color values of the pixel.

    image = Image.open( "myimage.jpg" )
    (width, height) = image.size
    (r, g, b) = image.getpixel( (42, 35) )
    image.putpixel( (42, 35), (b, g, r ) )
    

    Note that the functions in PIL expect positions and colors to be provided as tuples, a set of values enclosed in parentheses. Tuples are like lists except elements in a tuple cannot be modified. You create a tuple by enclosing a set of values or variables in parentheses, as in the example above.

    You can find the number of columns in an image using image.size (note that this is not a function) which returns the size of an image as a tuple (width, height).

  6. Create a new file named effects.py in your project4 directory. As usual, put your name and a date at the top. Import the Image and sys packages.

    Create a function named swapRedBlue() that expects an Image as its only parameter. The algorithm is written in comments below, properly indented. Read through this and make sure you understand the process. Then fill in the Python code.

    def swapRedBlue( image ):
        # find the width and height of the image
        # loop over each row in the image height
            # loop over each column in the image width
                # get the (r, g, b) values of the pixel indexed by (column, row)
                # set the pixel indexed by (column, row)  to the value (b, g, r)
    
  7. Create a main function that takes as a parameter a list of strings (as we did above). As before, first test if there are enough strings in this list and print out a usage statement and exit if there are not. If there are enough strings, open the image file specified by the 2nd string and store the result in an Image variable. Pass the Image as an argument to the swapRedBlue() function, then save the result to a file. If your Image variable is called myimg, then you save it by using:
    myimg.save('myfilename.jpg')

    You can use whatever filename you want in the save function, but I recommend not having spaces in the name.

    When you are done, run your effects program. Then look at the result with your show program. Now, perhaps, you see why command line parameters are useful beasts.

When you are done with the lab exercises, get started on the project.