The goal of this lab assignment to allow you to practice processing and manipulating image files in Python by using the PIL library.

For this assignment, record your work in a Jupyter Notebook and upload it to the form below by 11:59 PM Friday, March 8.

Activity 0: Starter Notebook

To help you get started, we have provided you with a starter notebook, which you can download and then use to record your answers. To utilize the starter notebook, download it to wherever you are running Jupyter Notebook and then use the Jupyter Notebook interface to open the downloaded file.

Download Starter Notebook

The starter notebook is already formatted for all the various sections you need to fill out. Just look for the red instructions that indicates were you need to write text or the cyan comments that indicate where you need to write code.

Activity 1: Gradient

For the first activity, you are to produce an image consisting of a gradient of two colors such as shown below:

Function

To complete this activity, you will need to implement the make_gradient_image function described below:

def make_gradient_image(width, height, source, target):
    ''' Given the width and height of the target image, this function
    produces a gradient image that goes from source color to target color.
    '''
  return None

In order to implement this function, you will need to do the following:

  1. Create a new Image with the specified width and height.

  2. Iterate through all the pixels in the new Image.

  3. For each pixel, determine the pixel color value using the following formula:

    weight    = 1.0 - (x / width)
    new_color = source*weight + target*(1 - weight)
    

    What this does is compute a weight based on how far long we are in the width of the image. Based on this weight, we will take a portion of the pixel value from the source image and take the remaining portion from the target image.

    For instance, if we are 20% of the way across the image, we want to use 80% of the source color's value and 20% of the target color's value.

  4. Store the computed color for each pixel.

  5. Return the newly created Image.

Testing

To test and demonstrate that your make_gradient_image function is working, create and display two different images using two different pairs of colors.

ND_BLUE = (12, 35, 64)
ND_GOLD = (211, 159, 16)
display(make_gradient_image(480, 320, ND_BLUE, ND_GOLD))

Reflection

After you have implemented the make_gradient_image function and demonstrated it with two different images, answer the following questions:

  1. Describe how you implemented the make_gradient_image. In particular, describe the overall control flow in the function and the computation you performed to determine the color at each pixel.

  2. Currently, the make_gradient_image function produces a horizontal gradient. How would you instead produce a vertical gradient?

Activity 2: Blend

For the second activity, you are to produce an image by blending two images based on a provided weight:

Functions

To complete this activity, you will need to implement the blend_images function described below:

def blend_images(image1, image2, weight):
    ''' Blend the two given images using the specified weight:

    new_pixel = pixel1*weight + pixel2*(1 - weight)
    '''
    return None

In order to implement this function, you will need to do the following:

  1. Query the width and height of one of the images.

  2. Create a new Image with the queried width and height.

  3. Iterate through all the pixels in the new Image.

  4. For each pixel, determine the pixel color value using the following formula:

    new_pixel = pixel1*weight + pixel2*(1 - weight)
    

    This computation should be similar to the one in make_gradient_image.

  5. Store the computed color for each pixel.

  6. Return the newly created Image.

Testing

To test and demonstrate that your blend_images function is working, create and display two different blended images using two different pairs of images from the Internet.

Remember that you can load an image from the Internet, by doing the following:

url1 = 'https://upload.wikimedia.org/wikipedia/en/e/e8/Taylor_Swift_-_Red.png'
url2 = 'https://upload.wikimedia.org/wikipedia/en/f/f6/Taylor_Swift_-_1989.png'
image1 = Image.open(BytesIO(requests.get(url1).content))
image2 = Image.open(BytesIO(requests.get(url2).content))
display(blend_images(image1, image2, 0.5))

Reflection

After you have implemented the blend_images function and demonstrated it with two different pairs of images, answer the following questions:

  1. Describe how you implemented the blend_images. In particular, describe the overall control flow in the function and the computation you performed to determine the color at each pixel.

  2. What happens if the two images don't have the same dimensions? What could you do to ensure that the blend operation always works even if the images are different sizes?

Submission

Once you have completed your lab, submit your Jupyter Notebook using the form:

Submit Lab Notebook