parent previous next question (Smalltalk Textbook 08)

EngiColorModelViewController

This section is about color. VisualWorks supports several color models: RGB (Red, Green, Blue). CMY (Cyan, Magenta, Yellow), and HSB (Hue, Saturation, Brightness). I think HSB is the most convenient model.

Seeing is believing so please execute the following program.


Program-8-1: (ColorValue, ScheduledControllers; displayRectangle, paint:,
sensor, activeController, noButtonPressed, display)
-----------------------------------------------------------------
| colorValue activeWindow graphicsContext |
colorValue := ColorValue
            hue: 1
            saturation: 1
            brightness: 1.
activeWindow := ScheduledControllers activeController view.
graphicsContext := activeWindow graphicsContext.
graphicsContext paint: colorValue.
graphicsContext displayRectangle: activeWindow bounds.
[activeWindow sensor noButtonPressed] whileTrue.
activeWindow display
--------------------------------------------------------------------

Surprise! This program makes an instance of 'ColorValue' which is red, then paints the whole window. Click the mouse to restore the window.

First, let's examine hue. Program 8-2 fixes saturation and brightness at 1.0 and shows 7 different values of hue.


Program-8-2: (ColorValue, ScheduledControllers, OrderedCollection, Transcript; 
hue:saturation:brightness, paint:, displayRectangle:, waitClickButton)
----------------------------------------------------------------
| activeWindow graphicsContext hueCollection colorValue |
activeWindow := ScheduledControllers activeController view.
graphicsContext := activeWindow graphicsContext.
hueCollection := OrderedCollection new.
hueCollection add: 0 / 6.
hueCollection add: 1 / 6.
hueCollection add: 2 / 6.
hueCollection add: 3 / 6.
hueCollection add: 4 / 6.
hueCollection add: 5 / 6.
hueCollection add: 6 / 6.
hueCollection
    do: 
        [:hue | 
        colorValue := ColorValue
                    hue: hue
                    saturation: 1
                    brightness: 1.
        Transcript cr; show: colorValue printString.
        graphicsContext paint: colorValue.
        graphicsContext displayRectangle: activeWindow bounds.
        activeWindow sensor waitClickButton].
activeWindow display
--------------------------------------------------------------------

With each mouse click, the color of the window change to red, yellow, green, cyan, blue, magenta, and back to red. Hue maps to the wavelength of light. Values of hue circle around: 0/3 is red, 1/3 is green, 2/3 is blue and 3/3 circles back around to red.

Next is saturation. Program 8-3 fixes hue and brightness at 1.0 and shows 7 different values of saturation.


Program-8-3: (ColorValue, ScheduledControllers, OrderedCollection, 
Transcript; saturation, hue:saturation:brightness:, paint:, 
displayRectangle:, waitClickButton)
------------------------------------------------------------------
| activeWindow graphicsContext saturationCollection colorValue |
activeWindow := ScheduledControllers activeController view.
graphicsContext := activeWindow graphicsContext.
saturationCollection := OrderedCollection new.
saturationCollection add: 6 / 6.
saturationCollection add: 5 / 6.
saturationCollection add: 4 / 6.
saturationCollection add: 3 / 6.
saturationCollection add: 2 / 6.
saturationCollection add: 1 / 6.
saturationCollection add: 0 / 6.
saturationCollection
    do: 
        [:saturation | 
        colorValue := ColorValue
                    hue: 1
                    saturation: saturation
                    brightness: 1.
        Transcript cr; show: colorValue printString.
        graphicsContext paint: colorValue.
        graphicsContext displayRectangle: activeWindow bounds.
        activeWindow sensor waitClickButton].
activeWindow display
------------------------------------------------------------------

With each mouse click, the color of the window change from red to salmon and eventually to white. Saturation is the measure of white in a color: zero is pure white and 1.0 is pure color. When saturation is 0, the value of hue no longer matters because the color is pure white..

The last factor is brightness. Program 8-4 fixes hue and saturation at 1.0 and shows 7 different values of brightness.


Program-8-4: (ColorValue, ScheduledControllers, OrderedCollection, 
Transcript; brightness, hue:saturation:brightness:, paint:, 
displayRectangle:, waitClickButton)
------------------------------------------------------------------
| activeWindow graphicsContext brightnessCollection colorValue |
activeWindow := ScheduledControllers activeController view.
graphicsContext := activeWindow graphicsContext.
brightnessCollection := OrderedCollection new.
brightnessCollection add: 6 / 6.
brightnessCollection add: 5 / 6.
brightnessCollection add: 4 / 6.
brightnessCollection add: 3 / 6.
brightnessCollection add: 2 / 6.
brightnessCollection add: 1 / 6.
brightnessCollection add: 0 / 6.
brightnessCollection
    do: 
        [:brightness | 
        colorValue := ColorValue
                    hue: 1
                    saturation: 1
                    brightness: brightness.
        Transcript cr; show: colorValue printString.
        graphicsContext paint: colorValue.
        graphicsContext displayRectangle: activeWindow bounds.
        activeWindow sensor waitClickButton].
activeWindow display
--------------------------------------------------------------------

The window color changes from red to black. When the brightness is zero, hue and saturation don't matter, because the color is pure black. At 1.0, the color contains no black.

What happens if you modify Program 8-4 to make the value of saturation zero instead of 1? You'll see the window color change from white to gray to black. A saturation of zero makes colors be monochromatic, or grayscale.

This is one reason why the HSB model is often used for color in Smalltalk; it makes it easy to use monochromatic colors, i.e. grayscale.

In the RGB model or CMY model, you must give all three factors the same value to achieve a gray scale, because in those models, the gray scale is located on a diagonal line of three factors in a 3d cube. In other words, the line goes from the point 0,0,0 to the point 1,1,1 in a unit cube.

A 3d visualization of the HSB model is like an ear of corn. The top row is black and the center of the bottom circle is white. Hue is arranged on the bottom circle surface.

Load (file in) Appendix 05 and evaluate the following expression.

--------------------------------------------
EngiColorModel openOn: ColorValue green
--------------------------------------------

You'll see a window to choose a color. Green is shown in the left view. On the right, the top view controls hue, the middle view controls saturation and the bottom view controls brightness. Explore various settings of the sliders to get a feel for the role of hue, saturation, and brightness in making a specific ColorValue.

Click right (operate) on the left view to get a 'copy/print' menu. 'Copy' places a text string in the Edit buffer which, when evaluated will create an instance of the current ColorValue. Actually the statement has HSB values of the color. After doing 'copy,' select a work area and choose 'paste' from the menu. From the left view, choosing 'Print' will write the statement to the Transcript instead.

Click left (select) on the left view to set the color to one of several predefined colors.

Evaluate the next expression.

------------------------------------------------------
EngiColorModel select: ColorValue cyan
------------------------------------------------------

You'll see a dialogue window with two buttons, 'accept' and 'cancel'. Choose 'accept' to return the color shown (an instance of 'ColorValue'). Choose 'cancel' to return nil. You can use this statement to interact with a user to choose a color.

I don't cover the details in Appendix 05 because we haven't covered 'GraphicsContext' and 'Pixmap' classes, but feel free to explore the appendix now if you're curious.


parent previous next question
Copyright (C) 1994-1996 by Atsushi Aoki
Translated by Kaoru Rin Hayashi & Brent N. Reeves