Now we're going to add alpha blending to the placeImage() function in
your filter.py file. This is a modification of your existing
function. The new algorithm is given below. Each comment is a line of
python code. Note the added function parameter alpha.

If you have two colors, (r1, g1, b1) and (r2, g2, b2), then the alpha
blend of the red color band is given by the expression below. You will
need to write a similar expression for the green and blue values.
Note that the graphics color_rgb function expects integers, hence the
cast.

r = int(r1 * alpha + r2 * (1.0 - alpha))

Remember to remove our comments once you have written the code (they contribute to clutter).

When you are finished, download the
file testimage.py, read through the test
file, and run it. As the usage statement indicates, it wants the
names of two ppm images. When the program is finished, look at the
image blend.ppm using your show.py file from last week.

The goal of the project this week is to enable you to easily blend
together multiple images, with various effects, into a collage.
Rather than hard code all the collage positions, however, we want to
put the essential information defining a collage into a list. Then we
can write a general function that takes in all of that information and
generates the correct collage image. To change the collage, we then
just change the information defining the collage, not the code.

What is the essential information that defines a collage?

First, we should identify the essential information for a single
image, since a collage is just a collection of single images.

Filename of the image

X offset in the collage

Y offset in the collage

Effect for the image

Alpha blend value

The Image object (after being read from a file)

To store the information for a single image, we can use a list. To
store the information for all of the images, we can use a list of
lists. Consider the assignment below, which creates a list that
defines a collage with two images.

The one problem with using a list is that when we need to access a
parameter for a given image, we have to remember that parameter's
index in the list. Consider looping over collageList and printing out
the filename.

for pictureParams in collageList:
print( pictureParams[0])

We have to remember that the filename will be pictureParams[0],
since we set up the parameter list with that value in the first
position.

Using a design where you have to use actual numbers means it is
easy to make mistakes when you have to remember whether a given value
is in position 4 or position 5. It also makes it hard to modify your
code. For example, if you feel you need to add a new parameter to the
list of parameters for a picture, what happens if you put it first in
the list? That would mean you would have to go through all of your
code and change the indexes everywhere you were accessing a parameter
value. That's a lot of code and a lot of opportunities to make
mistakes.

Instead, how could we use software engineering principles to avoid
having to remember the index? What about using a module-level
(top-level) variable whose value remains constant throughout the
simulation? We can use it to index into the list. For example, we
could create a variable IDXFilename that is set to 0,
the index of the filename in the list of parameters for an
image. Then, when we need to access the filename, we use code like

for pictureParams in collageList:
print(pictureParams[IDXFilename])

instead of the code above. It's a lot easier to remember
IDXFilename, and if you decide to change the position of the filename
parameter in your list, you have to change only one place in your
code: the assignment of a value to IDXFilename.

Create a new file called collage.py. You will
want to import filter so you can use your filters to modify the
images.

After the import statements, create the module-level variables
you will use to access the individual picture lists. Create one
variable for each of the picture parameters: filename, X offset, Y
offset, filter, alpha, and Image. When naming
your variables, please begin each name with IDX to indicate the value
is an index, then use a name that indicates the field. Using IDX
is not a Python rule, but a convention the differentiates these
variables as having a special purpose. Each of the assignments
will be something like the following.

IDXFilename = 0

Since we will be using mnemonic variables as indexes, it
doesn't really matter what order you put the values into the
list. However, if you want to be able to use the provided test
code then the ordering needs to be: filename, x-offset,
y-offset, filter, alpha, Image.

Copy the following test function into your collage.py and then
add more print statements to test each of the parameter entries.
Run it and make sure it prints out the right information for each
of the pictures.

Next, write a function readImages. Given the collage list structure we designed above, write a function that reads in each of the images in the collage and for each image stores the corresponding Image in the picture list. The template is below.

# reads in the files in the collage and stores the Image objects in the list
def readImages( clist ):
# for each pictureParams in clist
# assign to the variable filename the IDXFilename element of pictureParams
# assign to the variable src, the Image returned by reading filename (graphics.Image)
# assign to the IDXImage element of pictureParams the value in src

Test the readImages function by creating a test
function in collage.py that makes the above collageList variable,
calls readImages, and then prints out the names and
sizes of each image. Since in the readImages function you stored a
Image in the last location of each picture list, you can use the
Image to getWidth() and getHeight(). You can use the template
below in your test function.

# for each picParams in collageList:
# print the IDXFilename element of picParams
# print the result of using the IDXImage element of picParams to call the method getWidth()
# print the result of using the IDXImage element of picParams to call the method getHeight()

Given the collage list structure we developed, write a function that calculates
how big the program needs to make the background Image to hold the collage.

def getImageSize( clist ):
# assign to the variable rows, 0
# assign to the variable cols, 0
# for each item in clist
# assign to x0 the x offset information in item
# assign to y0 the y offset information in item
# assign to src the Image reference (last element in item)
# assign to dx the offset x0 plus the width of src
# if dx is greater than cols
# assign to cols, dx
# assign to dy the offset y0 plus the height of src
# if dy is greater than rows
# assign to rows, dy
# return a tuple with cols and rows in it

Test out your getImageSize function using the simple collage list
above, after reading in the images using your readImages function.
The answer should be 600 wide (cols) and 450 high (rows) if you use
maine1.ppm and main2.ppm as test images.

Now that you have practice working with the collage information lists,
you should be able to write a generic buildCollage program that
creates a collage from the information in the list. And this is
precisely what you will do in the project.

When you are done with the lab exercises, you may start on the rest of the project.