The objective of this lab is to learn how to perform more complicated image manipulations by copying a picture into another picture, and scaling a picture.
copyInto, takes as its input a picture to be copied, a blank canvas (an empty picture) in which to copy it, and the upper left x and y coordinates of the location on the canvas where you want to copy the picture.
def copyInto(picture, canvas, upperLeftX, upperLeftY): # Assign values to the variables widthToCopy and heightToCopy # based on whether or not there is room on the canvas to fit the # entire picture. If there isn't enough room, we should copy less # than the full width and height of the picture. #canvas argument will not be modified... newCanvas = duplicatePicture(canvas) pictureWidth = getWidth(picture) pictureHeight = getHeight(picture) canvasWidth = getWidth(newCanvas) canvasHeight = getHeight(newCanvas) #These two lines only work if the picture doesn't spill off the canvas... widthToCopy = pictureWidth heightToCopy = pictureHeight #You need something like the following two lines instead. #(You'll need to replace the question marks.) #widthToCopy = min(pictureWidth, ???????????) #heightToCopy = min(pictureHeight, ??????????) # Copy however much of the picture as will fit over to the canvas edge targetX = upperLeftX for sourceX in range(widthToCopy): targetY = upperLeftY for sourceY in range(heightToCopy): # Copy the color of the pixel at the source location to the # destination location. sourcePix = getPixel(picture, sourceX, sourceY) color = getColor(sourcePix) destPix = getPixel(newCanvas, targetX, targetY) setColor(destPix, color) targetY = targetY + 1 targetX = targetX +1 return newCanvasThe function as written so far only works if there is enough room on the canvas to copy the entire picture starting at the location you specify, as in the first illustration below. This is not always a safe assumption. The picture might be bigger than the canvas in at least one dimension, as in the second illustration, or it might be small enough to fit in the canvas but not when the copying starts at the specified upper-left corner, as in the third illustration. (In the illustrations, the black area represents the canvas in which we wish to copy the picture; any part of the picture covered with grid lines cannot be copied into the canvas.)
Design Questions: How can you determine how much room is available in the canvas if you start copying the picture at location (
upperLeftX, upperLeftY)? In other words, how can you determine the width of the space available from the specified upper left corner to the edge of the canvas? How can you determine the height of the space available from the same location?
Analysis Questions: Must the canvas be a blank empty picture? Could you also use this function to copy a picture onto another (non-blank) picture?Modify the function so that it only copies as much of the original or source picture as there is room for. To do this, use the
minfunction to find the smaller of the two values - the width of the picture, and the space available on the canvas. Modify the
widthToCopyvariable to refer to this value. (Alternatively, you could use an
ifstatement to do this: compare the width of the picture with the space available on the canvas. If the space available is smaller than the picture width, modify the
widthToCopyvariable to refer to the remaining width of the canvas instead.) Do something similar for
heightToCopy. After you have adjusted the width and height (if needed), the code above will copy the picture (or however much will fit) to the canvas.
Make sure to comment your function appropriately.
|Picture fits in canvas||Picture does not
fit in canvas
|Picture could fit in
canvas, but overhangs it
mattefunction that takes two parameters, a picture and a matte width, and creates a new picture consisting of the original picture surrounded by a matte of the appropriate width. (A matte is the sheet of cardboard or thick paper that often forms a border around a picture inside a frame.) The function should return the new picture with the matte. You may write your function so that it always creates a black matte, as in the examples below, or, if you have time, you may wish to add an extra parameter that specifies the matte color.
Design Questions: Do you have other functions you can use to make writing this function easier? If you have the original picture and know the width of the matte on all sides of the picture, how should you compute the dimensions of the new picture with the matte? Where should the original picture be placed in the new picture? How should you specify that?
# Returns a new picture 1/4 the size of the # original picture (half as wide and half as high). def quarter(orig): #Get the original width and height and divide them in half newWidth = getWidth(orig)/2 newHeight = getHeight(orig)/2 #Make an empty picture to store the scaled image newCanvas = makeEmptyPicture(newWidth,newHeight) #Copy every other pixel onto the new canvas for targetX in range(newWidth): for targetY in range(newHeight): color = getColor(getPixel(orig, targetX*2, targetY*2)) setColor(getPixel(newCanvas, targetX, targetY), color) return newCanvas
# Fills a canvas with as many copies of a picture as will # fit, including partial copies of the picture along the # right and lower edges if necessary def tile(picture, canvas): for targetY in range(0, getHeight(canvas),getHeight(picture)): for targetX in range(0, getWidth(canvas), getWidth(picture)): canvas = copyInto(picture, canvas, targetX, targetY) return canvas
tileWithQuarters, that takes a picture as a parameter. It should create a new picture the same size as the original picture, and tile four copies of the original image, scaled to 1/4-size. This function should return the new picture. (Hint: There are at least two ways to do this - you may use your
tilefunction or you may think about how to use the
copyIntofunction to do this.)
tileWithQuarterfunction, along with descriptions for both of these.
kzoo.edu. (You may want to review the instructions in Lab 1 if you've forgotten how to do this.)