Summary: In this laboratory, you will experiment with a variety of techniques for transforming RGB colors and images built from RGB colors.
functo its old color and setting that pixel to the resulting color.
In this laboratory, you will be creating a few images and manipulating others. We will also be working with some colors.
a. Create a new 4x3 image, call it
canvas, show it, and
zoom in to 16x or greater resolution. (Note that a shortcut for zooming
in is to expand the window and then use
View->Zoom->Fit Image in Window.)
b. You may have created definitions for three favorite colors,
a previous lab. Check your library to see if they are there. If
not, add some definitions. For example,
(define fave1 (color-name->rgb "blueviolet")) (define fave2 (rgb-new 240 0 180)) (define fave3 (rgb-new 180 0 240))
rgb->string, remind yourself of the three
b. Determine what happens to the components when you apply
fave1. You'll need to apply
rgb-darker and then find out the components of the
c. Determine what happens when you apply
draw three pixels side-by-side on
canvas (say, in
positions (0,1), (1,1), and (2,1)). The first should be the lighter
fave1. The second should be
The third should be the darker version of
fave1. Do you
see a difference?
e. What do you expect to happen to the red, green, and blue components
if you apply
rgb-lighter three times to the color
127/20/20, as in the following?
(define newcolor (rgb-lighter (rgb-lighter (rgb-lighter (rgb-new 127 20 20)))))
f. Check your answer experimentally.
g. What do you expect to happen to the red, green, and blue components
if you apply
rgb-darker three times to the color 127/20/20,
as in the following?
(define newcolor (rgb-darker (rgb-darker (rgb-darker (rgb-new 127 20 20)))))
h. Check your answer experimentally.
As you may recall from the reading, there are also color transformations
that make more significant changes to colors. For example,
rgb-phaseshift shifts each component by 128 (adding to
small components and subtracting from large components). In contrast,
rgb-complement computes the complement of a color.
Suppose we've defined the following colors:
(define c0 (rgb-new 64 128 196)) (define c1 (rgb-new 32 96 255)) (define c2 (rgb-new 240 0 127))
a. What do you expect the complements of
c2 to be?
b. Check your answer experimentally.
c. What do you expect the phase shifts of
c2 to be?
d. Check your answer experimentally.
a. Set pixels (0,0) and (1,1) of
b. Make the top-left pixel darker using the more verbose instruction from the reading.
(image-set-pixel! canvas 0 0 (rgb-darker (image-get-pixel canvas 0 0)))
c. Make the pixel at (1,1) darker using the
the more concise
(image-transform-pixel! canvas 1 1 rgb-darker)
d. Do you see any advantages of using the longer instruction?
You're halfway through the lab. Take a deep breath.
We have just a few basic transformations. However, we can get more transformations by combining the basic transformations. For example, we get a different color when we complement and darken a color than when we complement or darken the color alone.
a. Does the order in which we apply transformations matter?
In particular, do you get the same or different color when you
complement and then darken a color as compared to when you darken and
then complement the color? In code, what is the relationship between
(define newcolor1 (rgb-darker (rgb-complement fave1))) (define newcolor2 (rgb-complement (rgb-darker fave1)))
b. Check your answer experimentally.
c. What do you expect to have happen if you complement a color twice, as in this example?
(define newcolor3 (rgb-complement (rgb-complement fave2)))
d. Check your answer experimentally.
e. At first glance, lightening and darkening an image seem to be
inverse operations. Are there ever times in which the sequence of
does not give you back the same color?
(define newcolor4 (rgb-new ___ ___ ___)) (define newcolor5 (rgb-darker (rgb-lighter newcolor4)))
f. Check your answer experimentally. In doing so, try colors near the extremes, such as black, white, yellow, 10/255/127, and such.
In the corresponding
reading, there is a set of sample code that is intended to
canvas by complementing every pixel.
(image-transform-pixel! canvas 0 0 rgb-complement) (image-transform-pixel! canvas 0 1 rgb-complement) (image-transform-pixel! canvas 0 2 rgb-complement) (image-transform-pixel! canvas 0 3 rgb-complement) (image-transform-pixel! canvas 1 0 rgb-complement) (image-transform-pixel! canvas 1 1 rgb-complement) (image-transform-pixel! canvas 1 2 rgb-complement) (image-transform-pixel! canvas 1 3 rgb-complement) (image-transform-pixel! canvas 2 0 rgb-complement) (image-transform-pixel! canvas 2 1 rgb-complement) (image-transform-pixel! canvas 2 2 rgb-complement) (image-transform-pixel! canvas 2 3 rgb-complement)
a. There is a subtle error in the code. Identify the error and fix it. (If you can't figure out the error, try running the code to see what error messages you get.)
canvas so that it has a variety of colors. Here
is one set of simple changes, but you can do what you want.
(image-set-pixel! canvas 0 0 (rgb-new 0 0 0)) (image-set-pixel! canvas 1 0 (rgb-new 255 0 0)) (image-set-pixel! canvas 2 0 (rgb-new 0 255 0)) (image-set-pixel! canvas 3 0 (rgb-new 0 0 255)) (image-set-pixel! canvas 0 1 (rgb-new 255 255 255)) (image-set-pixel! canvas 1 1 (rgb-new 255 0 255)) (image-set-pixel! canvas 2 1 (rgb-new 255 255 0)) (image-set-pixel! canvas 3 1 (rgb-new 0 255 255)) (image-set-pixel! canvas 0 2 (rgb-new 63 127 195)) (image-set-pixel! canvas 1 2 (rgb-new 127 195 63)) (image-set-pixel! canvas 2 2 (rgb-new 195 63 127))
c. Verify that the repaired instructions do, in fact, complement all of the pixels.
d. What do you expect to have happen if you run this code twice?
e. Check your answer to the previous question experimentally.
As you may recall, we defined two new transformations in the reading.
(define greener2 (lambda (color) (rgb-greener (rgb-greener (rgb-greener (rgb-darker (rgb-darker color))))))) (define bound (lambda (val lower upper) (min (max val lower) upper))) (define rgb-bound (lambda (rgb) (rgb-new (bound (rgb-red rgb) 64 192) (bound (rgb-green rgb) 64 192) (bound (rgb-blue rgb) 64 192))))
a. Verify that each works as advertised.
b. Write a procedure,
( that makes
color redder using a technique of
your choice. (It should, however, do more than just call
c. Test your procedure.
If you have extra time, try either an Extra problem (which emphasizes Scheme issues) on an Exploration (which emphasizes thinking about colors and images). You should be able to do these problems in any order. Choose the one that seems most interesting to you.
At first glance, some find that
rgb-phaseshift is a lot
rgb-complement. After all, each changes a color by
shifting the components, and adding or subtracting 128 may feel like
an easier way to get something that sums to 255. However, as we've
suggested in the reading, the two operations are quite different.
a. Find two colors whose pseudo-complements are fairly close to their phase-shifted versions. You may find the following code useful as you visually compare the different colors.
(define color1 (rgb-new __ __ __)) (define color2 (rgb-new __ __ __)) (define ps1 (rgb-phaseshift color1)) (define ps2 (rgb-phaseshift color2)) (define comp1 (rgb-complement color1)) (define comp2 (rgb-complement color2)) (image-set-pixel! canvas 0 0 color1) (image-set-pixel! canvas 1 0 ps1) (image-set-pixel! canvas 2 0 comp1) (image-set-pixel! canvas 0 2 color2) (image-set-pixel! canvas 1 2 ps2) (image-set-pixel! canvas 2 2 comp2)
b. Find two colors whose phase-shifted versions are much different than their pseudo-complements.
c. Do you expect there to be more colors like those in a, or more colors like those in b? (That is, is it more likely that the pseudo-complement of a color is close to the phase-shifted color, or that they are different?) Explain your answer.
As you have undoubtedly noticed, RGB colors are represented as integers. That means that we can transform colors with arithmetic operations as well as with component based operations. What do you think the following operations will do to the sample color? Try some of them to find out. Try using different sample colors (black, grey, white, primaries, favorite colors, whatever). (Don't worry if you can't figure it out and the results don't necessarily make sense; even those who designed the representation can't easily make sense of it.)
(define sample fave1) (rgb->string sample) (rgb->string (* 2 sample)) (rgb->string (* 3 sample)) (rgb->string (* 256 sample)) (rgb->string (quotient sample 2)) (rgb->string (quotient sample 3)) (rgb->string (quotient sample 256)) (rgb->string (+ RGB-RED sample)) (rgb->string (+ RGB-GREEN sample)) (rgb->string (+ RGB-BLUE sample)) (rgb->string (quotient (+ RGB-RED sample) 2)) (rgb->string (- sample RGB-RED)) (rgb->string (- sample RGB-GREEN)) (rgb->string (- sample RGB-BLUE))
Try developing your own interesting transformation procedures using some of the numerical operations you know about.
Copyright (c) 2007-10 Janet Davis, Matthew Kluber, Samuel A. Rebelsky, and Jerod Weinman. (Selected materials copyright by John David Stone and Henry Walker and used by permission.)
This material is based upon work partially supported by the National Science Foundation under Grant No. CCLI-0633090. Any opinions, findings, and conclusions or recommendations expressed in this material are those of the author(s) and do not necessarily reflect the views of the National Science Foundation.
This work is licensed under a Creative Commons
Attribution-NonCommercial 2.5 License. To view a copy of this
or send a letter to Creative Commons, 543 Howard Street, 5th Floor,
San Francisco, California, 94105, USA.