Homework 26 – image manipulation

Module do.py

• Complete the implementation of the eleven functions. They provide underlying support for coloring a picture from a digital coloring book. The module functions will be used by crayon.py in the next assignment to do the actual coloring.
• The term coordinate is often used below. A coordinate is a two-tuple for representing a pixel location. The first element of the tuple is the x part of the coordinate and the second element of the tuple is the y part of the coordinate. Suppose `spot` is a coordinate. We can get set `sx` to be its x part and `sy` to be its y part with the following statement.

sx, sy = spot

• The term color is also often used below. For our purposes, a color is a three-tuple representing an RGB value; that is, and amount of red, green, and blue. Suppose `drawing` is an `Image`, and `spot` is a coordinate. We can set `sr`, `sg`, and `sb` to be the red, green, and blue levels of the RGB color (pixel) at coordinate `spot` on `drawing` with the following statement.

sr, sg, sb = drawing.getpixel( spot )

Function `random_color()`

• Returns a random RGB three-tuple, where each element of the tuple is a random integer value from the inclusive interval 0 ... 255 (i.e., there are base 256 integers). For example, code segment

random.seed( 'cs' )

c1 = do.random_color()

random.seed( '1112' )

c2 = do.random_color()

print( c1, c2 )

should print

(104, 190, 51) (190, 230, 218)

Function `get_width( drawing )`

• Returns the width of the `Image` represented by `drawing`. For example, code segment

ml_url = 'http://www.cs1112.org/images/ml.png'

tj_url = 'http://www.cs1112.org/images/tj.png'

ml = url.get_image( ml_url )

tj = url.get_image( tj_url )

w1 = do.get_width( ml )

w2 = do.get_width( tj )

print( w1, w2 )

should print

512 580

Function `get_height( drawing )`

• Returns the height of the `Image` represented by `drawing`. For example, code segment

ml_url = 'http://www.cs1112.org/images/ml.png'

tj_url = 'http://www.cs1112.org/images/tj.png'

ml = url.get_image( ml_url )

tj = url.get_image( tj_url )

h1 = do.get_height( ml )

h2 = do.get_height( tj )

print( h1, h2 )

should print

765 664

Function `left( spot )`

• Returns the coordinate immediately left of `spot`; that is, its x-coordinate is one less than that of `spot` and its y-coordinate is the same as that of `spot`. For example, code segment

xy1 = ( 2, 4 );

xy2 = ( 3, 9 )

l1 = do.left( xy1 )

l2 = do.left( xy2 )

print( l1, l2 )

should print

(1, 4) (2, 9)

Function `right( spot )`

• Returns the coordinate immediately right of `spot`; that is, its x-coordinate is one greater than that of `spot` and its y-coordinate is the same as that of `spot`. For example, code segment

xy1 = ( 2, 4 );

xy2 = ( 3, 9 )

r1 = do.right( xy1 );

r2 = do.right( xy2 );

print( r1, r2 )

should print

(3, 4) (4, 9)

Function `above( spot )`

Returns the coordinate immediately above `spot`; that is, its x-coordinate is the same as that of `spot` and its y-coordinate is one less than that of `spot`. For example, code segment

xy1 = ( 2, 4 );

xy2 = ( 3, 9 );

a1 = do.above( xy1 );

a2 = do.above( xy2 );

print( a1, a2 )

should print

(2, 3) (3, 8)

Function `below( spot )`

• Returns the coordinate immediately below `spot`; that is, its x-coordinate is the same as that of `spot` and its y-coordinate is one greater than that of `spot`. For example, code segment

xy1 = ( 2, 4 );

xy2 = ( 3, 9 );

b1 = do.below( xy1 );

b2 = do.below( xy2 );

print( b1, b2 )

should print

(2, 5) (3, 10 )

Function `is_inbounds( drawing, spot )`

• Returns `True` or `False` whether coordinate `spot` is inbounds on the `Image` represented by `drawing`. Obervations.
• If the x- or y-coordinate of `spot` is negative, then `spot` is out of bounds.
• If the x- coordinate of `spot` is greater than or equal to the width of `drawing`, then `spot` is out of bounds.
• If the y- coordinate of `spot` is greater than or equal to the height of `drawing`, then `spot` is out of bounds.
• Otherwise, `spot` is inbounds.

For example, code segment

ml_url = 'http://www.cs1112.org/images/ml.png'

ml = url.get_image( ml_url )

w = do.get_width( ml )

h = do.get_height( ml )

xy1 = ( w // 2, h // 2 )

xy2 = ( w, h )

xy3 = ( -1, -1 )

i1 = do.is_inbounds( ml, xy1 )

i2 = do.is_inbounds( ml, xy2 )

i3 = do.is_inbounds( ml, xy3 )

print( i1, i2, i3 )

should print

True False False

Function `get_color( drawing, spot )`

• If coordinate `spot` is inbounds on the `Image` represented by `drawing`, the function returns the color at `spot` in the `drawing`; otherwise, the function returns `None`. For example, code segment

ml_url = 'http://www.cs1112.org/images/ml.png'

ml = url.get_image( ml_url )

w = do.get_width( ml )

h = do.get_height( ml )

xy1 = ( w // 4, h // 5 )

xy2 = ( w, h )

xy3 = ( -1, -1 )

c1 = do.get_color( ml, xy1 )

c2 = do.get_color( ml, xy2 )

c3 = do.get_color( ml, xy3 )

print( c1, c2, c3 )

should print

(137, 128, 97) None None

Function `is_colorable( drawing, spot, bg=(255,255,255) )`

• Returns `True` or `False` whether coordinate `spot` is a colorable pixel in `drawing`. To be colorable `spot` must be inbounds and equal to the background color `bg`. For example, code segment

ml_url = 'http://www.cs1112.org/images/ml.png'

ml = url.get_image( ml_url )

w = do.get_width( ml )

h = do.get_height( ml )

xy1 = ( w // 5, h // 4 )

xy2 = ( w, h )

xy3 = ( -1, -1 )

xy4 = ( w // 4, h // 5 )

b1 = do.is_colorable( ml, xy1 )

b2 = do.is_colorable( ml, xy2, (255, 0, 255 ) )

b3 = do.is_colorable( ml, xy3 )

c = ml.getpixel( xy4 )

b4 = do.is_colorable( ml, xy4, c )

print( b1, b2, b3, b4 )

should print

False False False True

Function `paint( drawing, spot, c, bg=(255,255,255) )`

• If `spot` is a colorable pixel on `drawing`, then that pixel is set to `c`; otherwise, no action is taken. For example, code segment

ml_url = 'http://www.cs1112.org/images/ml.png'

ml = get.web_image( ml_url )

for y in range( 175, 220 ) :

for x in range( 228, 235 ) :

xy = ( x, y )

bg = ml.getpixel( xy )

do.paint( ml, xy, ( 255, 215, 0 ), bg )

get.popup( ml )

should produce

†. The above code segments are bundled into snippets.py.