Image Reference


Install Pillow

The SimpleImage module we are covering in class uses the "Pillow" library. A library is a body of already written code which you import and use, and in this case the Pillow library contains code to manipulate images. In order for SimpleImage to work properly, you need to install Pillow on your machine.

To install Pillow, you should first open a "terminal" window: the easiest way to do this is to use the "Terminal" tab at the bottom of PyCharm. Type the following command into the Terminal. (Note that "Pillow" starts with an uppercase P.) On Windows, type py or python instead of python3):

python3 -m pip install Pillow
...prints stuff...
Successfully installed Pillow-9.5.0

If that doesn't work, try pip3 instead of pip.

Note: You only have to install Pillow once. After you have successfully installed it, the library will be available for use in all future assignments and lecture examples.

To test that Pillow is working, type the following command into the PyCharm terminal while you've opened any assignment or lecture example folder that contains the file simpleimage.py. On Windows, type py or python instead of python3):

python3 simpleimage.py
# yellow rectangle with green stripe appears

This runs the simpleimage.py code included in the project folder. When run like this, you should see a big yellow rectangle with a small green stripe on the right pop up. If you cannot get Pillow installed successfully, please check out our forum or go to the course staff office hours for help.

While any graphics projects we create for you will have the necessary graphics files included, you can also download this simpleimage file, unzip it, and add simpleimage.py to your project folder if you're starting from scratch. Then, all you need to do is add from simpleimage import SimpleImage to the top of your code.

Basic SimpleImage Functionality

The SimpleImage code used in CS106A provides you with some basic digital image processing tools:

Reading an image from a filename

This function reads the image from the specified file and returns a SimpleImage object that can be stored in a variable to refer to the image.

image = SimpleImage(filename)

The filename is something like 'my_image.jpg', a string that contains the name of an image file. This file should be within the project folder you're working on. You can add any photo you like to your project folder in order to open it with SimpleImage.

"For-each" loop over all pixels in the image

This gives you access to each of the pixels in the image one-by-one so that you can apply the same code to all of them.

for pixel in image:
  # use pixel in here

Accessing data inside a pixel

Each pixel has properties that can be accessed with the "dot" syntax. These properties include its RGB (red, blue, and green) components, which are integers between 0 and 255, as well as the location of the pixel in its corresponding image. The pixel's color properties can be accessed and modified, but the pixel's location properties cannot be directly modified.

# color properties
pixel.red
pixel.green
pixel.blue
# location properties
pixel.x
pixel.y

Displaying the image

Each image can be displayed on your computer using the show function. After you've finished manipulating the image in whatever way you like, you should call this function to make the image display.

image.show()

Accessing image size

Each image has two attributes - height and width - that can be directly accessed from the image. This is useful for algorithms that rely on the size of the image.

# size attributes
image.width
image.height

Advanced SimpleImage Functionality

As you progress into creating your own images or working on more complicated image algorithms, there are some more advanced features of SimpleImage that you can take advantage of:

Creating a blank image with a specified height and width

This is useful for starting off with a "blank canvas" that you can color in an interesting way. Both of the lines of code below are valid ways of making a blank image with a width of 200 pixels and a height of 100 pixels.

# can use either
image = SimpleImage.blank(200, 100)
image = SimpleImage.blank(width=200, height=100)

Accessing a pixel by its x, y coordinates

The top left of the image corresponds to x=0, y=0. x-coordinates get larger as you move to the right, and y-coordinates get larger as you move down.

# gets the pixel from image at (x, y)
pixel = image.get_pixel(x, y)

Note: x and y should be integers and x must be in the range 0 to width-1 (inclusive) and y must be in the range 0 to height-1 (inclusive).

Setting the value of a certain pixel in an image by its x, y coordinates

If you have a pixel and you want to place it directly into an image, you can do so with the following function.

# puts the pixel into image at (x, y)
image.set_pixel(x, y, pixel)

Resizing an image to be the same size as another image

This function takes in a target_image whose size you want to match and modifies image so that it has identical dimensions to the target image. This function is especially helpful when working on problems that involve taking pixels from one image and copying them onto another image). This function helps ensure that the sizes of the two images match up.

image.make_as_big_as(target_image)

Range Loops with SimpleImage

The "for each" loop described above is the easiest way to loop over all of the pixels in an image. However, sometimes you want to write loops that access pixels by their x, y coordinates. The code below demonstrates the standard nested for loop pattern to access all of the pixels in an image. The outer for loop iterates over the rows (starting with the top row (y = 0) and moving on to the next row (y = 1)), and the inner for loop iterates over the columns.

def example(filename):
  image = SimpleImage(filename)
  for y in range(image.height):     # loop over all the rows
    fox x in range(image.width):    # loop over all the columns
      pixel = image.get_pixel(x, y)
      # do something with pixel
        
  return image