Due: 9 a.m. Wednesday 4 March 2009
Summary: A potpourri of problems involving repetition over lists of colors.
Purposes:
To practice iteration over lists using map.
To practice writing recursive procedures.
To see a cool technique for creating images that combines lists with
image-compute.
Expected Time: Two to three hours.
Collaboration: We encourage you to work in groups of size three. You may, however, work alone or work in a group of size two or size four. You may discuss this assignment with anyone, provided you credit such discussions when you submit the assignment.
Submitting:
Email your answer to <weinman>. The title of your email
should have the form HW6 and
should contain your answers to all parts of the assignment. Scheme code
should be in the body of the message.
Warning: So that this assignment is a learning experience for everyone, we may spend class time publicly critiquing your work.
Consider the following instructions.
(define stripe-colors
(list (rgb-new 255 0 0)
(rgb-new 255 255 0)
(rgb-new 0 255 0)
(rgb-new 0 255 255)
(rgb-new 0 0 255)))
(image-compute
(lambda (col row) (list-ref stripe-colors (modulo col 5)))
100 100)
a. What do you expect these instructions to do?
b. Check your answer experimentally.
c. Extend that code to use seven colors instead of five. That is, you'll need to add two values to the list (presumably, by redefining the list) and use a different modulus.
d. As you should have observed, this makes a sequence of vertical
stripes, each of width one pixel. We can make the stripes wider
by computing the quotient of the column and the desired width.
Try expanding your columns to a width of 5 and then 10. (Note that in
order to use the result as a parameter to modulo
and then in list-ref, we need to guarantee
that it is an integer. Hence, you should compute the quotient with
quotient rather than /.)
e. Suppose that we wanted to fill the image with exactly one stripe of each color. How many stripes would there be? How wide would they be? Modify the code so that there is exactly one stripe of each color. (They might not be exactly the same width.)
f. Predict the result of the following instructions, and then try executing them.
(define canvas (image-show (image-new 200 200)))
(region-compute-pixels!
canvas
100 0 100 100
(lambda (col row)
(list-ref stripe-colors (modulo (quotient col 10) 5))))
(region-compute-pixels!
canvas
0 100 100 100
(lambda (col row)
(list-ref stripe-colors (modulo (quotient row 10) 5))))
(region-compute-pixels!
canvas
100 100 100 100
(lambda (col row)
(list-ref stripe-colors
(modulo (quotient (+ row col) 10) 5))))
Similar to an artist's palette, in digital graphics a palette is a list of colors to be used in an image. In this problem you will use the techniques you experimented with above to visualize palettes and the results of applying color transformations to those palettes.
a. Using the techniques you learned above,
implement the procedure (.
This procedure should return a new image of the specified width and height,
created using image-palette
colors
width
height)image-compute,
that has one vertical stripe of each color.
For example,
|
|
b. Write an expression using image-palette and
map that creates an image showing the
complements of a list of colors.
c. Implement the procedure (.
The image-palette-comparison
transform
colors
width
height)image-palette-comparison procedure
should be similar to
the image-palette procedure from above.
However, the new parameter,
the transform procedure, should be an RGB
transformation, that is, a procedure that takes an RGB color and
produces a new RGB color.
The top half of the resulting image should show the original colors and
the bottom half should show the transformed colors.
Your procedure should use map to apply the given
transformation to all the colors in the list,
and then name the resulting list using
let.
For example,
|
|
|
|
Write a procedure,
(,
that, given a nonempty list of colors, finds the darkest of those
colors.
rgb-darkest colors)
You will need the definition of rgb-brightness;
you may also find rgb-darker-of-two useful.
;;; Procedure:
;;; rgb-brightness
;;; Parameters:
;;; color, an RGB color
;;; Purpose:
;;; Computes the brightness of color on a 0 (dark) to 100 (light) scale.
;;; Produces:
;;; b, an integer
;;; Preconditions:
;;; color is a valid RGB color. That is, each component is between
;;; 0 and 255, inclusive.
;;; Postconditions:
;;; If color1 is likely to be perceived as lighter than color2,
;;; then (brightness color1) > (brightness color2).
(define rgb-brightness
(lambda (color)
(round (* 100 (/ (+ (* 0.30 (rgb-red color))
(* 0.59 (rgb-green color))
(* 0.11 (rgb-blue color)))
255)))))
;;; Procedure:
;;; rgb-darker-of-two
;;; Parameters:
;;; color1, an RGB color.
;;; color2, an RGB color.
;;; Purpose:
;;; Find the darker of color1 and color2.
;;; Produces:
;;; darker, an RGB color.
;;; Preconditions:
;;; [No additional]
;;; Postconditions:
;;; darker is either color1 or color2
;;; (rgb-brightness darker) <= (rgb-brightness color1)
;;; (rgb-brightness darker) <= (rgb-brightness color2)
(define rgb-darker-of-two
(lambda (color1 color2)
(if (< (rgb-brightness color1) (rgb-brightness color2))
color1
color2)))
Note: This problem appears as Extra 1 in the lab on helper recursion. You should finish that lab before attempting this problem!
Although we've primarily used helpers to keep track of one intermediate result, we can certainly pass along more than one intermediate result. For example, in averaging a list of colors, we can keep track of the sum of reds, the sum of greens, the sum of blues, and the count of colors. In the end, we can build a new color from these computed values.
(define rgb-list-average
(lambda (colors)
(rgb-list-average-helper 0 0 0 0 colors)))
(define rgb-list-average-helper
(lambda (red-so-far green-so-far blue-so-far count remaining-colors)
(if (null? remaining-colors)
(rgb-new (/ red-so-far count)
(/ green-so-far count)
(/ blue-so-far count))
(rgb-list-average-helper ...))))
a. Fill in the remaining code in the recursive call.
b. Test this code to average white and black.
(rgb->string (rgb-list-average (list (rgb-new 255 255 255) (rgb-new 0 0 0))))
c. Test this code on a few other colors of your choice.
d. What do you expect to have happen if you provide rgb-list-average with the empty list?
e. Check your answer experimentally.
The lab on list
recursion, revisited asks you to implement a procedure called
member?.
This is a very important procedure, and we want to make sure everyone
has a chance to implement it.
Give your definition of that procedure here, crediting your lab partner(s) if appropriate.
Write a procedure, (, that, given a list of colors,
computes a new list of colors, by averaging subsequent pairs of
colors. For example, if the input list is the standard seven
rainbow colors (red, orange, yellow, green, blue, indigo, and violet),
the output list will consist of
a red-orange average, an orange-yellow average, a yellow-green
average, a green-blue average, a blue-indigo average, and an
indigo-violet average.
rgb-averages
colors)
Note that the length of the result list is one less than the length of the input list.
Hint: Use the rgb-average
procedure, which averages two RGB colors, to help do the work.
Hint: Although this problem appears as an extra in the basic recusion lab, you will find it easier after you complete the lab on list recursion, revisited. You will need to use a special base case to stop the recursion when there are too few colors in the list to produce an average.
We will consider the correctness, clarity, and conciseness of your code.