''' Purpose: better experience functional development ''' from PIL import Image # helpful constants SIMILARITY_THRESHOLD = 85 # minimum distance to be dissimilar GREEN = ( 0, 255, 0 ) # back screen color def distance( p1, p2 ) : ''' Returns the distance between p1 and p2 RGB values ''' pass def similar( p1, p2 ) : ''' Returns whether the distance between pixels p1 and p2 is less than the similarity threshold ''' # We want to see if p1 and p2 (two pixels - two colors - two r,g,b tuples) # are similar. d = distance( p1, p2 ) # Call the distance function if ( d < SIMILARITY_THRESHOLD ): # if the distance is less than the threshold return True # we know they're similar! else: return False def is_background( p, back_screen ) : ''' Returns whether p is similar to the back_screen color ''' # We want to see if p is SIMILAR to the back_screen color not only equal # Either the same color or something similar to it. # The green screen has a lot of different greens even though they look the same # We want to account for ALL of those similar greens and get rid of that green # stuff around the foreground image (dino, beyonce, etc.) if ( similar(p, back_screen) ): return True else: return False def inbounds( spot, img ) : ''' Returns whether spot lies on img. ''' # See the spot exists on the image (if it's in the bounds of the image) # We know our image has a certain width and height # The spot's x coordinate and y coordinate have to fall inside of the image # meaning that the x coordinate has to be in the image's width # meaning that the y coordinate has to be in the image's height width, height = img.size # Extract the image's width and height x,y = spot # Extract the x and y coordinate from the spot # x goes from 0 to width - 1 # y goes from 0 to height - 1 # Anything outside that is not in the bounds of our image! if ( x < 0 ): # x cannot be less than 0! return False elif ( y < 0 ): # y cannot be less than 0! return False elif ( x >= width ): # x cannot be greater than the width return False elif ( y >= height ): # y cannot be greater than the height return False else: return True def colorable( spot, img, p, back_screen ) : ''' Returns whether both spot is a location on img and color p is not similar to color back_screen ''' if ( inbounds( spot, img) == False ): # not on the image, so it is not colorable return False elif ( similar( p, back_screen ) == True ) : # pixel p is the "green" color, so do not want to copy it return False else: # otherwise, the spot lies on the image, and color is not "green" return True ### DO NOT MODIFY THE BELOW CODE def combine( bg, fg, sx, sy, back_screen ) : ''' Returns mash up of background image bg and foreground image fg, where the pixels in fg that are dissimilar to back_screen are copied on top of the background. The mash up uses location (sx, sy) as the spot in the background to start the lay over of fg. ''' bw, bh = bg.size # size of background image fw, fh = fg.size # size of foreground image copy = bg.copy() # get a copy of background image new_image = copy.convert( 'RGB' ) # to be the basis of new image for fx in range( 0, fw ) : # consider every (fx, fy) for fy in range( 0, fh ): # possibility of the new image fspot = ( fx, fy ) # name spot (fx, fy ) fpixel = fg.getpixel( fspot ) # get the pixel at fspot nx = sx + fx # determine spot on new image ny = sy + fy # to paint fpixel nspot = ( nx, ny ) # check whether fpixel should be painted on new image at nspot if ( colorable( nspot, new_image, fpixel, back_screen ) ) : new_image.putpixel( nspot, fpixel ) return new_image # return the mash up if ( __name__ == '__main__' ) : import smashing smashing.test_with_dino() smashing.test_with_beyonce() smashing.test_with_ww()