21MAKING GRAPHS AND MANIPULATING IMAGES

A picture is worth a thousand words, and your code can handle high-resolution image files just as it can any other form of data. The third-party Pillow package has several functions for editing images and drawing lines and text with the precision and speed of automated scripts. To generate line graphs, bar graphs, scatter plots, and pie charts, you can use Matplotlib, a popular library for making professional-looking graphs.

A simple drawing of a light bulb. LEARNING OBJECTIVES

  • Understand how computers store images, pixels, and colors.
  • Perform basic image editing by resizing, cropping, and rotating images with Pillow.
  • Draw shapes and text onto images, or overlay images on top of each other.
  • Copy and paste images to the clipboard.
  • Generate graphs using Matplotlib.

A grey circle with a white question mark at the center Practice Questions

These questions test your knowledge of the Pillow library, image file concepts in general, and graphing with Matplotlib.

Computer Image Fundamentals

Computer programs often represent a color in an image as an RGBA value, a group of numbers that specify the amount of red, green, blue, and alpha (transparency) to include. Image pixels are addressed with x- and y-coordinates, which, respectively, specify a pixel’s horizontal and vertical locations.

  1. 1. What color is (0, 255, 0, 0)?

  2. 2. What does the A in RGBA represent?

  3. 3. What function can you call to get the RGBA value of the color “chocolate”?

  4. 4. What code returns a list of all the color names in the Pillow library?

  5. 5. What are the x- and y-coordinates of the origin?

  6. 6. In which corner of an image is the origin?

  7. 7. What is the RGBA tuple for the color purple?

  8. 8. (255, 255, 255, 255) is the RGBA tuple for what color?

  9. 9. (0, 0, 0, 255) is the RGBA tuple for what color?

  10. 10. In a 100-pixel-wide and 100-pixel-tall image, what is the coordinate of the pixel in the bottom-right corner?

  11. 11. What is a box tuple in the context of the Pillow library?

  12. 12. How can you calculate the width of the box from the data in a box tuple?

  13. 13. What are the width and height of a (5, 20, 10, 30) box tuple?

Manipulating Images with Pillow

An Image object has several useful attributes that give you basic information about the image file from which it was loaded: its width and height, the filename, and the graphics format. The object’s methods allow you to crop, rotate, resize, extract, and duplicate portions of the image.

  1. 14. You do not run import pillow to import Pillow. What instruction do you run?

  2. 15. Can Pillow read images in the .png, .jpg, and .gif formats?

  3. 16. What does the Image.open() function return?

  4. 17. What does the show() method do?

  5. 18. What does the following code do: Image.new('RGBA', (100,100), 'purple').show()?

  6. 19. Say you have an image named zophie.png. How can you find the width and height of this image?

  7. 20. Which is correct: im.crop(335, 345, 565, 560) or im.crop((335, 345, 565, 560))?

  8. 21. Does the method call im.crop((335, 345, 565, 560)) change the size of the Image object in im?

  9. 22. What does the copy() method do?

  10. 23. Does copy() take a box tuple argument to specify which portion of the image it should copy?

  11. 24. What does the code cat_im.paste(face_im, (0, 0)) do?

  12. 25. Will the function call cat_im.paste(face_im, (0, 0)) correctly paste pixels with transparency, or will these pixels show up as opaque white pixels?

  13. 26. If the Image object in im contains a 100×100 image, the method call im.resize((2.0, 2.0)) doesn’t resize the image to double the width and height. What method call will do this?

  14. 27. Does the method call im.resize((100, 100)) change the size of the Image object in im?

  15. 28. What method call returns a new Image object that is a horizontally flipped version of an Image object in an im variable?

  16. 29. What method call returns a new Image object that is a vertically flipped version of an Image object in an im variable?

  17. 30. Is horizontally flipping an image the same thing as rotating the image 180 degrees?

  18. 31. If you rotate a 200×100 image by 90 degrees (and pass expand=True to the rotate() method call), how big is the rotated image?

  19. 32. If you rotate a 200×100 image by 180 degrees (and pass expand=True to the rotate() method call), how big is the rotated image?

  20. 33. If the Image object in im is 200×100 in size, how big is the Image object returned by im.rotate(45)?

  21. 34. Is the Image object returned by im.rotate(45, expand=True) bigger, smaller, or the same size as the Image object in im?

  22. 35. What method returns the color of a single pixel of an Image object?

  23. 36. Does im.putpixel((50, 100), (255, 0, 0)) return a new Image object with the changed pixel?

  24. 37. What does the following code draw?

    from PIL import Image
    im = Image.new('RGBA', (100, 100), 'red')
    for x in range(10, 90):
        for y in range(10, 90):
            im.putpixel((x, y), (0, 0, 255, 255))
    im.show()
  25. 38. Write the code to draw a 100×100 image that is green on the top half and yellow on the bottom half. Hint: The RGBA tuple for green is (0, 255, 0, 255), and the RGBA tuple for yellow is (255, 255, 0, 255). Your program should call the show() method to display the image.

Drawing on Images

Pillow’s ImageDraw module lets you treat image files as canvases to draw on with code. You can change individual pixels as well as draw shapes such as rectangles, circles, and lines.

  1. 39. What import statement must you run before drawing shapes on Image objects?

  2. 40. What code returns an ImageDraw object for an Image object stored in a variable named im?

  3. 41. What method draws a circle?

  4. 42. What method draws a square?

  5. 43. How many lines does this method call draw: draw.line([10, 10, 20, 20, 40, 60])?

  6. 44. You cannot draw a diamond shape that looks like a square rotated 45 degrees with the rectangle() method. Which method can draw this diamond shape?

  7. 45. What do each of the three arguments mean in draw.text((20, 150), 'Hello', fill='purple')?

  8. 46. What font does the method call draw.text((20, 150), 'Hello', fill='purple') use to draw the text?

  9. 47. Say you call the ImageFont.truetype() function on a nonexistent font, as in ImageFont.truetype('no_such_font.ttf', 32). What error does this raise?

  10. 48. Write code that creates a 100×100 image of black text on a white background. The text should read “Hello”; then, resize the image to 1,000×1,000.

Copying and Pasting Images to the Clipboard

Just as the third-party pyperclip module allows you to copy-and-paste text strings to the clipboard, the pyperclipimg module can copy-and-paste Pillow Image objects. By putting images on and getting images from the clipboard, you can enable users to quickly input and output image data without first saving it to an image file.

  1. 49. Does pyperclipimg require you to also install Pillow?

  2. 50. What does the code pyperclipimg.paste().show() do?

  3. 51. What data type does the pyperclipimg.paste() function return if there is an image on the clipboard?

  4. 52. What value does the pyperclipimg.paste() function return if there is text on the clipboard?

  5. 53. What does the code pyperclipimg.copy(pyperclipimg.paste().resize((100, 100))) do?

  6. 54. What does the code pyperclipimg.paste().save('contents.png') do?

Creating Graphs with Matplotlib

Drawing your own graphs using Pillow’s ImageDraw module is possible but would require a lot of work. The Matplotlib library can create a wide variety of graphs for use in professional publications.

  1. 55. What is the usual convention for importing Matplotlib? (Hint: It uses the as keyword in the import statement.)

  2. 56. How many points are on the plot created by plt.plot([10, 20, 30], [10, 5, 40])?

  3. 57. Does the plot created by plt.plot([10, 20, 30], [10, 5, 40]) include points connected by lines, or just individual points?

  4. 58. What is the name of the kind of plot that has individual points but no lines connecting them?

  5. 59. What method call saves the plot as an image file named plot.png?

  6. 60. What are the two arguments to the plt.bar() function?

  7. 61. What functions add an x-axis label and a y-axis label?

  8. 62. What does plt.grid(True) do?

  9. 63. What code displays an interactive preview window of a plot?

  10. 64. What does the following code do?

    import matplotlib.pyplot as plt
    slices = [80, 20]
    labels = ['Part that looks like Pacman', 'Part that does not
    look like Pacman']
    plt.pie(slices, labels=labels)
    plt.show()
  11. 65. What code adds the text “The plot thickens” to the top of your plot?

A simple drawing of a sharpened pencil. Practice Projects

In the following projects, you’ll create an image of a snowpal, generate rainbow flags, and build a clipboard logger.

Snowpal Image

Use Pillow to create an image of a wintery snowpal according to the following specifications:

  • The image size should be 1,000×1,000.
  • The top of the background should be a blue sky, and the bottom should be a white, snow-covered ground.
  • The snowpal’s body should consist of three black circles or ellipses with a white fill.
  • The snowpal should have a top hat made from two black rectangles.
  • The snowpal should have left and right arms made from two lines.

Aside from these requirements, you may make your image look however you want. You can add a face or buttons, use any shade of blue for the sky, add falling snowflakes to the background, create ears and whiskers to make a snowcat, or put the code in a loop to draw multiple snowpals.

At the end of the program, call the show() method to display your snowpal. If you write this method call code first at the bottom of your program, you can create your program in pieces and run it to see how the image is coming together.

Save this program in a file named snowpalImage.py.

Rainbow Flag Image Generator

The rainbow flag is a simple image consisting of six horizontal stripes in a rectangle. Let’s create a function, create_rainbow_flag(width, height), that takes a width and height parameter and generates a custom-sized rainbow flag. The colors to use, from top to bottom, are red, orange, yellow, green, blue, and purple.

The horizontal stripes should have x-coordinates that always range from 0 to width - 1, while the y-coordinates will vary but should always be int(height / 6) tall. The exception is the purple stripe at the bottom, which always goes down to height - 1 to cover the entire image. Make sure your flag doesn’t have gaps in between the stripes.

For example, if you call create_rainbow_flag(640, 480), your code should produce an Image object that is 640 pixels wide and 480 pixels tall. You can call the show() or save() method on this Image object to view the rainbow flag. Test your function by calling it with various arguments, and make sure the resulting image is the correct size.

Clipboard Image Recorder

In Chapter 12 of Automate the Boring Stuff with Python, we created a clipboard recording program that logged all text that appeared on the clipboard. Let’s do the same thing here, but instead of logging text, your program will record any images copied to the clipboard. Such a program can speed up your workflow if you’re, say, trying to download multiple images on a website but don’t want to fill out Save As dialogs for each one.

You can use the cliprec.py program’s source code as a starting point. You can find this program in the downloadable resources at https://nostarch.com/automate-boring-stuff-python-3rd-edition. To return a Pillow Image object of the clipboard contents, use the pyperclipimg module’s paste() function.

Your program should run in the background. As the user copies images to the clipboard, it should save them to a file with the current timestamp, such as clipboard-2028-12-16 21_58_21.753433.png. A call to str(datetime.datetime.now()) returns this timestamp format, but you must replace the colons with underscores.

The program should also display Recording clipboard images... (Ctrl-C to stop) when it starts and Saved clipboard-2028-12-16 21:58:21.753433.png when it saves a file.

Save this program in a file named clipboardImgRec.py.