''' 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 # This is the green screen color we are detecting so we can use it # to paint over def distance( p1, p2 ) : ''' Returns the distance between p1 and p2 RGB values ''' # Extract r,g,b values for p1 and p2 r1, g1, b1 = p1 r2, g2, b2 = p2 distance_between_pixels = abs( r2-r1 ) + abs( g2-g1 ) + abs( b2-b1 ) return distance_between_pixels def similar( p1, p2 ) : ''' Returns whether the distance between pixels p1 and p2 is less than the similarity threshold ''' # Use the distance() function defined earlier d = distance( p1, p2 ) # Pass in the parameters p1, p2 in this function as arguments to the function distance() if ( d < SIMILARITY_THRESHOLD ): return True else: return False # We will use the similar() function to see how close the colors in the image are # to the green screen color def is_background( p, back_screen ) : ''' Returns whether p is similar to the back_screen color ''' # Use the similar() function defined earlier similarity = similar( p, back_screen ) # This function returns True or False using the arguments p and back_screen if ( similarity == True ): return True else: return False # Or just return similarity since similar()'s return value is True / False def inbounds( spot, img ) : ''' Returns whether spot lies on img. ''' # Determines if the spot is in the bounds of the image (0<=x= w ): # x coordinate is out of bounds return False elif ( y >= h ): # y coordinate is out of bounds return False else: # This means that x was positive and less than the width and y was positive and less than the height 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 ''' # This function uses functions inbounds() and is_background() spot_on_image = inbounds( spot, img ) # Will be True if the spot is in bounds p_is_background_color = is_background( p, back_screen ) # Will be true if p is similar to backgorund if ( spot_on_image == False ): # Should be True to be colorable return False elif ( p_is_background_color == True ): # Should be False to be colorable return False else: # This means the spot was on the image and p was not the background color (so it's colorable!) 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()