Functional Problem Solving (CSC 151 2014F) : Labs

Laboratory: Transforming RGB Colors


Summary: In this laboratory, you will experiment with a variety of techniques for transforming RGB colors and images built from RGB colors.

Reference:

(irgb-lighter irgb-color)
MediaScheme Color Procedure. Build a lighter version of the given color.
(irgb-darker irgb-color)
MediaScheme Color Procedure. Build a darker version of the given color.
(irgb-redder irgb-color)
MediaScheme Color Procedure Build a redder version of the given color.
(irgb-greener irgb-color)
MediaScheme Color Procedure. Build a greener version of the given color.
(irgb-bluer irgb-color)
MediaScheme Color Procedure. Build a bluer version of the given color.
(irgb-rotate irgb-color)
MediaScheme Color Procedure. Rotate the three components of the given color, setting the red component to the value of the green component, the green component to the value of the blue component, and blue compnent to the value of the red component.
(irgb-phaseshift irgb-color)
MediaScheme Color Procedure.Phase shift” the color by adding 128 to components less than 128 and subtracting 128 from components greater than 128.
(irgb-complement irgb-color)
MediaScheme Color Procedure. Compute the psuedo-complement of the given color.
(image-transform-pixel! image column row func)
MediaScheme GIMP Procedure. Modify the pixel at (col,row) in image by applying func to its old color and setting that pixel to the resulting color.

Preparation

In this laboratory, you will be creating a few images and manipulating others. We will also be working with some colors.

a. You may have created definitions for three favorite colors, fave1, fave2, and fave3 in a previous lab. If you don't still have these definitions, then create new ones. For example,

(define fave1 (color-name->irgb "blueviolet"))
(define fave2 (irgb 240 0 180))
(define fave3 (irgb 180 0 240))

Exercises

Exercise 1: Lighter and Darker

a. Using irgb->rgb-list or irgb->string, remind yourself of the three components of fave1.

b. Determine what happens to the components when you apply irgb-darker to fave1. You'll need to apply irgb-darker and then find out the components of the new color.

c. Determine what happens when you apply irgb-lighter to fave1.

d. In the interactions pane, create, but do not show, a new 4x3 image called canvas.

e. Using image-set-pixel!, draw three pixels side-by-side on canvas (say, in positions (0,1), (1,1), and (2,1)). The first should be the lighter version of fave1. The second should be fave1. The third should be the darker version of fave1. Then show canvas and then zoom in so that you can see individual pixels. (Note that the shortcut for zooming in is to expand the window and then use View->Zoom->Fit Image in Window.) Do you see a difference between the pixels?

f. What do you expect to happen to the red, green, and blue components if you apply irgb-lighter three times to the color 127/20/20, as in the following?

(define newcolor (irgb-lighter (irgb-lighter (irgb-lighter (irgb 127 20 20)))))

g. Check your answer experimentally. That is, look at the red, green, and blue values of the new color.

h. What do you expect to happen to the red, green, and blue components if you apply irgb-darker three times to the color 127/20/20, as in the following?

(define newcolor (irgb-darker (irgb-darker (irgb-darker (irgb 127 20 20)))))

i. Check your answer experimentally.

Exercise 2: Other Transformations

As you may recall from the reading, there are also color transformations that make more significant changes to colors. For example, irgb-phaseshift shifts each component by 128 (adding to small components and subtracting from large components). In contrast, irgb-complement computes the complement of a color.

Suppose we've defined the following colors:

(define c0 (irgb 64 128 196))
(define c1 (irgb 32 96 255))
(define c2 (irgb 240 0 127))

a. What do you expect the complements of c0, c1, and c2 to be?

b. Check your answer experimentally.

c. What do you expect the phase shifts of c0, c1, and c2 to be?

d. Check your answer experimentally.

Exercise 3: Transforming Pixels

a. Create, but do not show, a new small image called canvas.

> (define canvas (image-new 4 3))

b. Set pixels (0,0) and (1,1) of canvas to fave1.

c. Make the top-left pixel darker using the more verbose instruction from the reading.

(image-set-pixel! canvas 0 0 
                  (irgb-darker (image-get-pixel canvas 0 0)))

d. Make the pixel at (1,1) darker using the the more concise image-transform-pixel! procedure.

(image-transform-pixel! canvas 1 1 irgb-darker)

e. Show and zoom in on canvas to compare the two results.

f. Do you see any advantages of using the longer instruction?

Exercise 4: Pause for Breath

You're halfway through the lab. Take a deep breath.

Exercise 5: Multiple Transformations

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 newcolor1 and newcolor2?

(define newcolor1 (irgb-darker (irgb-complement fave1)))
(define newcolor2 (irgb-complement (irgb-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 (irgb-complement (irgb-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 irgb-lighter and then irgb-darker does not give you back the same color?

(define newcolor4 (irgb ___ ___ ___))
(define newcolor5 (irgb-darker (irgb-lighter newcolor4)))
(irgb->string newcolor5)

f. Check your answer experimentally. In doing so, try colors near the extremes, such as black, white, yellow, 10/255/127, and such.

Exercise 6: Transforming Larger Sections

a. Create, but do not show, a new 4x3 canvas.

> (define canvas (image-new 4 3))

b. In the corresponding reading, there is a set of sample code that is intended to transform our 4x3 image named canvas by complementing every pixel.

(image-transform-pixel! canvas 0 0 irgb-complement)
(image-transform-pixel! canvas 0 1 irgb-complement)
(image-transform-pixel! canvas 0 2 irgb-complement)
(image-transform-pixel! canvas 0 3 irgb-complement)
(image-transform-pixel! canvas 1 0 irgb-complement)
(image-transform-pixel! canvas 1 1 irgb-complement)
(image-transform-pixel! canvas 1 2 irgb-complement)
(image-transform-pixel! canvas 1 3 irgb-complement)
(image-transform-pixel! canvas 2 0 irgb-complement)
(image-transform-pixel! canvas 2 1 irgb-complement)
(image-transform-pixel! canvas 2 2 irgb-complement)
(image-transform-pixel! canvas 2 3 irgb-complement)

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. If that still doesn't help, ask a mentor or teacher.)

c. Update 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 (irgb 0 0 0))
(image-set-pixel! canvas 1 0 (irgb 255 0 0))
(image-set-pixel! canvas 2 0 (irgb 0 255 0))
(image-set-pixel! canvas 3 0 (irgb 0 0 255))
(image-set-pixel! canvas 0 1 (irgb 255 255 255))
(image-set-pixel! canvas 1 1 (irgb 255 0 255))
(image-set-pixel! canvas 2 1 (irgb 255 255 0))
(image-set-pixel! canvas 3 1 (irgb 0 255 255))
(image-set-pixel! canvas 0 2 (irgb 63 127 195))
(image-set-pixel! canvas 1 2 (irgb 127 195 63))
(image-set-pixel! canvas 2 2 (irgb 195 63 127))

d. Verify that the repaired instructions from step b do, in fact, complement all of the pixels.

e. What do you expect to have happen if you run the repaired instructions from step b twice?

f. Check your answer to the previous question experimentally.

Exercise 7: Writing Your Own Transformations

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 irgb-bound
  (lambda (color)
    (irgb (bound (irgb-red color) 64 192)
          (bound (irgb-green color) 64 192)
          (bound (irgb-blue color) 64 192))))

a. Verify that each works as advertised.

b. Write a procedure, (redder color) that makes color redder (assuming that it is possible to make it redder), using a technique or techniques of your choice. You may not just call irgb-redder. You might find it useful to think about how you make a color appear redder, even if it's red component is already 255.

c. Experiment with your procedure.

For Those With Extra Time

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.

Extra 1: Making Components Extreme

Write a procedure, (extreme color) that makes an “extreme” version of color by turning components below 128 to 0 and components 128 and above to 255.

Hint: In an earlier lab, we thought about how to turn grades below 80 to 0 and grades 80 and above to 1. You can use a similar technique here, and then multiply by 255. (The technique involves division and rounding.)

Extra 2: Phase Shifting vs. Complementing

At first glance, some find that irgb-phaseshift is a lot like irgb-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 (irgb __ __ __))
(define color2 (irgb __ __ __))
(define ps1 (irgb-phaseshift color1))
(define ps2 (irgb-phaseshift color2))
(define comp1 (irgb-complement color1))
(define comp2 (irgb-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.

Explorations

Exploration 1: Arithmetical Transformations

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. Instead, think about how these transformations might be useful it making interesting images.

(define sample fave1)
(irgb->string sample)
(irgb->string (* 2 sample))
(irgb->string (* 3 sample))
(irgb->string (* 256 sample))
(irgb->string (quotient sample 2))
(irgb->string (quotient sample 3))
(irgb->string (quotient sample 256))
(irgb->string (+ RGB-RED sample))
(irgb->string (+ RGB-GREEN sample))
(irgb->string (+ RGB-BLUE sample))
(irgb->string (quotient (+ RGB-RED sample) 2))
(irgb->string (- sample RGB-RED))
(irgb->string (- sample RGB-GREEN))
(irgb->string (- sample RGB-BLUE))

Exploration 2: Your Own Transformations

Try developing your own interesting transformation procedures using some of the numerical operations you know about.