Skip to main content

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 r g b) MediaScheme Color Procedure.
Build an integer-encoded RGB color whose red, green, and blue components are the specified values, each of which is an integer between 0 and 255, inclusive. If given real values, rounds them to the nearest integer. If given values outside the bouds, caps them at the bounds.
(irgb-red irgb-color) MediaScheme Color Procedure.
Get the red component of an integer-encoded RGB color.
(irgb-green color) MediaScheme Color Procedure.
Get the green component of an integer-encoded RGB color.
(irgb-blue irgb-color) MediaScheme Color Procedure.
Get the blue component of an integer-encoded RGB color.
(irgb->string irgb-color) MediaScheme Color Procedure.
Convert the given RGB color to an easy-to-read string. (The string is not so easy to convert back to an RGB color.)
(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.
(irgb-add irgb-color-1 irgb-color-2) MediaScheme Color Procedure.
Add the corresponding RGB components of irgb-color-1 and irgb-color-2. If any component sum is greater than 255, uses 255 for the resulting component.
(irgb-average irgb-color-1 irgb-color-2) MediaScheme Color Procedure.
Average the corresponding RGB components of irgb-color-1 and irgb-color-2.
(irgb-subtract irgb-color-1 irgb-color-2) MediaScheme Color Procedure.
Subtract the RGB components of irgb-color-2 from the corresponding components of irgb-color-1. If any component difference is less than 0, uses 0 for the resulting component.
(color-swatch color1) , (color-swatch color1 color2) , (color-swatch color1 color2 color3 ...) MediaScheme Color Procedure.
Create an small image (“swatch”) that shows the given colors. Permits up to six colors.
(compose f g) Traditional Higher-Order Procedure.
Build a one-parameter procedure that applies g to its parameter, and then f to that result. ((compose f g) x) is the same as (f (g x)).

Preparation

In this laboratory, you will be experimenting with a variety of colors. It will help to have names for some of these 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, you might write the following.

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

b. If you have not already done so, open a terminal window and type /home/rebelsky/bin/csc151-setup and /home/rebelsky/bin/csc151-update.

c. Start both DrRacket and GIMP.

d. In GIMP, select DBus Server from under the MediaScript menu. You’ll get no feedback that anything has happened, but GIMP is now ready to talk to DrRacket.

e. In DrRacket, add the following line to the Definitions pane, directly under the #racket language specification.

(require gigls/unsafe)

f. Click DrRacket’s Run button. If all goes well, DrRacket will think for a moment and then give you a prompt in the interactions pane. If things don’t go well, you’ll probably see an incomprehensible error message. Ask your teacher or class mentor for help or refer to the list of possible error messages and their solutions.

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. Using color-swatch, make a swatch of three versions of fave1. The first should be the lighter version of fave1. The second should be fave1. The third should be the darker version of fave1. Do you see a difference between the colors?

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 using irgb->string. You should consider 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 pseudo-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 pseudo-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: 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 in the following?

(define newcolor1 (irgb-darker (irgb-complement fave1)))
(define newcolor2 (irgb-complement (irgb-darker fave1)))

b. Check your answer experimentally. You may find it useful to look at the two colors using color-swatch and irgb->string.

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 a color 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 4: A New Transformation

The reading noted that we can create new transformations by composing existing transformations. Let’s check whether that is indeed the case. Consider the following definitions.

> (define mycolor (irgb 64 128 192))
> (define irgb-rotrot (compose irgb-rotate irgb-rotate))
> (define irgb-gb (compose irgb-greener irgb-bluer))
> (define mycolor-rot (irgb-rotate mycolor))
> (define mycolor-rr (irgb-rotrot mycolor))
> (define mycolor-gb (irgb-gb mycolor))

a. What components do you expect for mycolor-rot, mycolor-rr, and mycolor-gb?

b. Check your answers experimentally.

Exercise 5: Ordering

In an earlier exercise, we observed that the order in which we do transformations can make a difference. In building compound transformations with compose, it is important to understand what order the component functions will be applied.

Consider the following definitions.

> (define greyish (irgb 127 127 127))
> (define irgb-modify1 (compose irgb-darker irgb-complement))
> (define irgb-modify2 (compose irgb-complement irgb-darker))
> (define greyish1 (irgb-modify1 greyish))
> (define greyish2 (irgb-modify2 greyish))

a. What values do you expect to get for the red, green, and blue components of greyish1 and greyish2?

b. Check your answer experimentally, using irgb->string.

c. What do your results say about the order in which f1, f2, and f3 are applied in (compose f1 f2 f3)?

Exercise 6: A New Transformation

Consider the following definitions.

> (define greyish (irgb 127 127 127))
> (define irgb-modify (compose irgb-complement irgb-redder irgb-redder irgb-complement))
> (define greyish-modified (irgb-modify greyish))

a. What values do you expect greyish-modified to have?

b. Check your results experimentally, using irgb->string and color-swatch.

c. Describe, in English, what irgb-modify does.

Exercise 7: Writing Your Own Transformations

As you may have discovered, irgb-modify makes its parameter less red. Write another procedure that makes its parameter less red, but don’t use irgb-redder in writing that procedure.

Exercise 8: Combining RGB Colors

Consider the following definitions.

(define red (irgb 255 0 0))
(define green (irgb 0 255 0))
(define blue (irgb 0 0 255))
(define black (irgb 0 0 0))
(define white (irgb 255 255 255))

a. What color do you expect to get if you add red and green?

b. Check your results experimentally with the following.

> (irgb->string (irgb-add red green))
> (image-show (color-swatch (irgb-add red green)))

c. What color do you expect to get if you add white to blue?

d. Check your answer experimentally.

e. What color do you expect to get if you average red and white?

f. Check your answer experimentally.

g. What color do you expect to get if you average red and black?

h. Check your answer experimentally.

i. What color do you expect to get if you subtract blue from white?

j. Check your answer experimentally.

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 an expression that computes an “extreme” version of a value named mycolor. Components whose value is less than 128 should become 0. Components whose value is at least 128 should become 255. For example,

> (define mycolor (irgb 64 200 120))
> (define mycolor2 (irgb (_____) (_____) (____)))
> (irgb->string mycolor2)
"0/255/0"
> (define mycolor (irgb 200 10 180))
> (define mycolor2 (irgb (_____) (_____) (____)))
> (irgb->string mycolor2)
"255/0/255"

You should be able to use the same set of three expressions for each of the transformations.

Hint: You can do some clever arithmetic tricks to achieve this goal.

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-show (color-swatch ps1 comp1 ps2 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))