InterpressColor.tioga
Rick Beach, May 26, 1987 1:28:04 pm PDT
HARRINGTON AND BUCKLEY
COLOR IN INTERPRESS
SIGGRAPH '87 TUTORIAL COURSE NOTES
DOCUMENTATION GRAPHICS
=== length: 1 in
Color in Interpress
[Copyright Ó 1987, Xerox Corporation. Preprint of Chapter 7, Color, excerpted from the forthcoming book Interpress, the Source Book by Steve Harrington and Rob Buckley to be published by Simon & Schuster, Inc. The color plate was not available in time to meet the SIGGRAPH course notes deadline.]
Color in Interpress
Steve Harrington and Rob Buckley
Xerox Webster Research Center
Those little gray cells. It is `up to them.'
Hercule Poirot
For a little work-room of my own at the back, I should rather like to see some patterns of unglossy — well, I'll be hanged if I can describe this red — it's not Turkish and it's not Roman and it's not Indian, but it seems to partake of the two last, and yet it can't be either of them because it ought to be able to go with vermillion. Ah, what a tangled web we weave . . .
Robert Louis Stevenson
1. INTRODUCTION
By now, you are familiar with the Interpress model for producing a page: an ink is pushed through a mask onto the page. Where the ink goes on the page is defined by a mask operator in the Interpress master; what it looks like is determined by the color variable in the Interpress imager. You can use the Interpress facilities for creating masks from characters, geometric shapes and scanned binary images. We will now turn our attention to how you specify and create inks in an Interpress master.
In Interpress, color or ink (the two are used interchangeably) can be black-and-white or gray as well as full color and either constant or sampled. When the color is constant, then the printer fills the area on the page defined by the mask with a uniform ink or flat color. When the color is sampled, the printer uses an ink created from a pixel array or scanned image. The overall ink is a pixel-by-pixel color specification. For example, the makesampledblack operator is used to create a patterned black-and-white ink from a binary pixel array. This chapter will describe how you specify color in an Interpress master, create the ink or color that makes objects visible on a page and produce color images on an Interpress printer.
2. COLOR REPRESENTATIONS
There are several ways of describing the color content of a page: how it was specified in the design, how it looks to a human observer, how it would be analyzed by an instrument or how it would be physically produced by a printer. Each description is appropriate at a different point in the production cycle of a document, from its design at a workstation, through its specification in an Interpress master to its physical realization on an Interpress printer. Interpress does not specify or limit the descriptions which can be used. You can choose whichever color model or ink description is most convenient for your application and use it in a master, provided your printer supports/understands it.
For a document creator and printer to communicate in color, they have to agree beforehand on the color representations which the master will use. This agreement usually takes the form of a standard description to which both the creator and the printer subscribe. The standard color descriptions which the creator uses in the master are part of the printer's environment. Providing an Interpress master with mechanisms for accessing standard color representations rather than making the representations part of the language itself is a powerful feature of Interpress, as we shall see.
Interpress describes an ideal image which the printer attempts to produce. The image should be specified in a device-independent manner, and not in terms of some particular printer's capabilities. Just as you would normally use device-independent spatial coordinates to describe the position, size and orientation of an object in an Interpress master, you would use device-independent color descriptions of the visual appearance of an object. And just as a particular Interpress printer converts the device-independent spatial description into an equivalent printer-specific description, the printer would convert the color described by the master into a visually equivalent or matching color that could be obtained with the its physical inks. For example, if the master uses the instruction (0.5 MAKEGRAY) to specify a medium gray ink, then a black-and-white printer would convert it to instructions that resulted in a halftone dot pattern on the page whenever the ink was applied (see Figure 1). But a CRT display, capable of producing gray intensity levels would image the object with medium gray intensity.
===
[Artwork node; type 'Artwork on' to command tool]
Figure 1. Color representation in the master and printer and on the page.
===
An Interpress master indicates the color to be used by placing a color specification in the color imager variable (index 13). This imager variable requires an object of type Color. Interpress does not define a standard encoding for this type so that its form depends on a particular printer. This allows the printer to convert from the device-independent description of the color to its particular device-dependent representation at the point where the object is constructed. As a result, there is only a limited number of things you can do with an object of type Color. You cannot open it up and look inside, nor can you alter it. You can move it around on the stack using any of the stack operators, you can store it in a frame with FSET or you can combine it with other elements in a vector using MAKEVEC. You cannot, for example, obtain a third color by adding two objects of type Color together. The most useful thing you can do with an object of type Color is store it in imager variable 13, which is where the printer looks for ink when it executes a mask operator.
The value of color specifies the printer-specific form of the color or ink that will be used to render an object when a mask operator is called. In effect, color is the inkwell into which the operator dips its pen before writing on the page. The color applied through the mask replaces whatever was previously laid down at the same position on the page. (The one exception to this is ink created by MAKESAMPLEDBLACK). At the beginning of each page body, the imager sets color to black.
The following sequence from an Interpress master illustrates some of the legal operations you can perform on inks. It assumes an object of unknown type on top of the stack and checks to see if its type is Color. If it is, then the object is stored in the color imager variable; if it is not, the instructions within the IF body replace the object on the stack with black ink (1 MAKEGRAY) and generate an appearance warning.
Example 1
. . . --check object on top of stack--
DUP --copy it for the test--
TYPE --get its type--
7 EQ --Is it type Color?--
NOT IF --if not--
 {
  POP --discard object--
  1 MAKEGRAY --make a black ink--
  66 65 68 32 67 79 76 79 82 --BAD COLOR--
  9 MAKEVEC 
  60 ERROR --appearance warning--
 }
13 ISET --save in imager--
Interpress provides several ways of creating ink, such as (1 MAKEGRAY), that are specifically designed to generate objects of type Color.
2.1 Constant Color
A constant color is an ink that has the same value at every point. Therefore, no matter where you position a mask, the ink applied through it looks the same. Interpress has several mechanisms with which you can specify constant color. You can request a color by name or by executing a color generating operator. The need for generating achromatic or gray colors occurs often enough that Interpress has a primitive operator specifically for grays. We shall begin by describing the MAKEGRAY operator that builds constant colored inks from gray intensity values.
2.2 Gray Intensity
The Interpress operator MAKEGRAY allows you to directly specify shades of gray on a scale from black to white.
<f: Number> MAKEGRAY <col:Constant Color>
It takes as its argument a number f between 0 and 1 and returns on the stack a constant color col with absorptance (the fraction of light absorbed) proportional to f. Absorptance is the complement of intensity; the more light an ink absorbs, the lower the intensity.
Maximum absorptance (f=1) occurs for black and minimum (f=0) for white. Intermediate values describe intensities along a linear scale between these two extremes. If the intensity of white is Iw and the intensity of black is Ib, then the intensity of the constant ink (f MAKEGRAY) is Iw - f X(Iw - Ib).
If the constant color created by MAKEGRAY is destined for the color imager variable, then the convenience operator SETGRAY can be used instead. SETGRAY takes the same argument as MAKEGRAY and creates the same constant color but transfers it to the imager variable color rather than leaving it on the stack.
<f: Number> SETGRAY <>
Therefore, the sequence (f SETGRAY) in an Interpress master is equivalent to (f MAKEGRAY 13 ISET).
The absorptance scale is not the only parameterization of gray levels. Work with transparent materials has led to the idea of optical density. The material absorbs some of the light shining through it, and the thicker the material, the more light absorbed. So instead of specifying the light absorbed, we could specify the thickness of some material that is needed to absorb the light. This ``thickness'' measure is the optical density. The relation between the absorptance (f) and density is
f = 1 - 10-density
Suppose we wanted to see what uniform steps in the density scale look like. We can do this by selecting a set of density values (say 0, 0.3, 0.6, 0.9, and 1.2), converting these to absorptance values by the above equation, and displaying them using rectangles and SETGRAY.
The following Interpress master uses SETGRAY to create the neutral density scale shown in Figure 2.
Example 2
Header "Interpress/Xerox/3.0 " --header--
BEGIN --start of the master--
 { } --preamble--
 { --start of the page--
  0.0254 SCALE CONCATT --inches for master coordinates--
  1 1 TRANSLATE CONCATT --include offset as part of T--
  0.94 SETGRAY --set density to 1.2--
  0 0 1 1 MASKRECTANGLE
  0.87 SETGRAY --set density to 0.9--
  1 0 1 1 MASKRECTANGLE
  0.75 SETGRAY --set density to 0.6--
  2 0 1 1 MASKRECTANGLE
  0.50 SETGRAY --set density to 0.3--
  3 0 1 1 MASKRECTANGLE
  0 SETGRAY --set density to 0--
  4 0 1 1 MASKRECTANGLE
 } --end of the page--
END --end of the master--
===
[Artwork node; type 'Artwork on' to command tool]
Figure 2. Neutral density scale produced with SETGRAY.
===
The density values start at white (density=0) and increment in steps of 0.3 density units.
MAKEGRAY is the only primitive operator in Interpress specifically designed to create gray or neutral inks. None of the primitive operators that we will now turn our attention to make a distinction between gray and full color and they can be applied with equal fluency to both.
2.3 Color Names
One of the common, everyday uses of color is in documents, such as simple business graphics (Plate 1), maps, cartoons and engineering drawings. These applications typically need only a few colors that can be easily recognized and distinguished. The important thing about these colors is not their form but their function and the ability they lend to the document to improve the comprehension and appearance of its content. When a document uses a few colors, the simplest way of specifying them is by name.
3. FINDING A COLOR
We used five colors in Plate 1: red, green, blue, light gray and black. If standard names are defined for these colors, then a document creator would use the FINDCOLOR operator in a master to instruct the printer to look up the specified color by name in its environment and return the color on the stack. The formal definition of FINDCOLOR is
<v: Vector of Identifiers> FINDCOLOR <col: constantColor>
The vector of identifiers v is the universal name of the color. If we use the name [IPBook, Red] to describe the red ink that we used in Plate 1, then the following statements would create and save the specified ink.
Example 3
Identifier "IPBook"
Identifier "Red"
2 MAKEVEC --color name--
FINDCOLOR --look up ink--
13 ISET --save in imager--
(Identifier "IPBook" Identifier "Red" 2 MAKEVEC) is the name which FINDCOLOR uses to look up the specified ink in the printer's environment. If the printer cannot find it there, then it would substitute another color for it and generate an appearance error. The choice of which color to substitute for the unknown one is at the discretion of the printer. It could, for example, select another color whose name most closely resembles the name of the color it could not find.
Named colors in an Interpress master provide a very efficient interface to simple color printers and pen plotters. You would typically define and use named color in a way that gives the printer the greatest latitude in creating the ink specified by the master. You might use [IPBook, Red] when you want an ink that unambiguously looks red and not magenta, orange or pink. The standard which defines what is meant by [IPBook, Red] can include a tolerance. It can indicate that any shade of red within limits is acceptable. The way that the printer implements [IPBook, Red] would reflect this. A color printer might simply overprint solid areas of magenta and yellow ink to obtain red. Since different printers would use different inks (here we mean physical inks, not Interpress inks), no two reds would look exactly the same, but so long as they were within tolerance they would be valid representations of [IPBook, Red], and would not be confused with magenta or orange or any other color in the document. If you wanted to specify red more precisely, then you would use a more specific color name or standard, such as [nbs, cns, strongRed], which is the color ``Strong Red'' in the National Bureau of Standards Color Naming Scheme. You can use this name in a master if your printer supports this standard. The resulting ink would be specified with tolerances of this standard.
Interpress gives you a great deal of freedom in defining what is meant by a color name. It provides the lookup mechanism, but the definition of actual colors is left to whatever standard the creator and printer can agree upon. Standards for color names which will be used by Xerox Corporation are, at the time of this writing, being developed as part of the Xerox Color Encoding Standard.
Because the mechanism is so flexible, you can even agree to very loose specifications, such as ``any color that is not black, white, or gray.'' Perhaps such specifications should be called pseudo colors. There is an example of such a specification built into the Interpress standard; it is [Xerox, highlight] and is a named ``color'' (or pseudo color) which means some non-neutral hue. It is intended for use with highlight-color printers which have two inks; black, and something else. [Xerox, highlight] says use the ``something else,'' whatever it is.
3.1 Color Maps
When dealing with many colors you may wish to structure them. You may wish to organize the colors according to some formula or rule, you can do this by placing the colors in vectors. The colors can then be accessed by their vector indices. For example, you could generate a table of colors from all possible combinations of M amounts of N inks. If the inks are cyan, magenta and yellow, combined in an all or none fashion, then N=3, M=2 and MN=8 colors would result. You would easily recognize the eight colors as cyan, magenta, yellow, red, green blue, black and white. When the set of colors is this small names work just as well as numbers, but when M is large, say 10, then the sample set would consist of 1000 colors. It would be awkward to identify colors by name. The alternative is to number them and then refer to individual colors by number.
To illustrate how this works, we can take the colors we used in Plate 1, add a few more and form the 3 ´ 3 color matrix or map shown in Plate 2. We could store the colors in this matrix as a three-element vector, where each element of the vector is itself a vector made from the three colors in a column of the matrix.
Example 4
. . .
Identifier "IPBook" Identifier "Blue" 2 MAKEVEC FINDCOLOR
Identifier "IPBook" Identifier "Cyan" 2 MAKEVEC FINDCOLOR
Identifier "IPBook" Identifier "Green" 2 MAKEVEC FINDCOLOR
3 MAKEVEC --make vector of inks in column 0--
1 MAKEGRAY --black--
0 MAKEGRAY --white--
0.5 MAKEGRAY --medium gray--
3 MAKEVEC --make vector of inks in column 1--
Identifier "IPBook" Identifier "Magenta" 2 MAKEVEC FINDCOLOR
Identifier "IPBook" Identifier "Red" 2 MAKEVEC FINDCOLOR
Identifier "IPBook" Identifier "Yellow" 2 MAKEVEC FINDCOLOR
3 MAKEVEC --make vector of inks in column 2--
3 MAKEVEC --make matrix--
0 FSET --save matrix in frame--
. . .
We can then build a composed operator that takes a vector containing the column and row number of the required ink and execute it to retrieve the ink from the matrix. The following statements retrieve the color [IPBook, Red] in column 2, row 1 of the matrix.
Example 5
MAKESIMPLECO
{
 2 FSET --save column and row number--
 0 FGET --retrieve color matrix--
 2 FGET 0 GET --get column number--
 GET --extract column from matrix--
 2 FGET 1 GET --get row number--
 GET --extract row from column--
}
1 FSET --save composed operator--
. . .
2 1 2 MAKEVEC --column 2, row 1--
1 FGET DO --execute the operator--
13 ISET --save the color--
. . .
Placing the colors in a vector establishes a correspondence between numbers (the vector indices) and colors (the vector elements). Such a correspondence is called a color map. One of the virtues of a color map is that it makes it easy to change colors throughout a page (or document). Suppose you create a color map at the start of a page, and that throughout the page you always access colors indirectly via the map. If you want red, you first look in the color map under the index of the red entry. The color obtained from the color map is then used in the color imager variable. Now suppose you decide orange would look better than red on the page. You have only to change the entry in the color map. You reconstruct the vector so that the element which was formerly red is now orange. Since the rest of the page references the color map entry, all of the attempts to get the red entry will now yield orange. So with this single change, all red objects become orange.
3.2 Color Operators
Naming colors works fine when you are dealing with only a few colors, but in reality there can be infinite variations in hues, shades, and tones. In order to cope with this variety of colors, a different approach to specification is needed. The approach is to organize the colors along some scale, and then use a value on the scale to specify the color. We have already seen this done with MAKEGRAY. We associate the color white with the number 0, and black with the number 1. Then any possible shades of gray can be specified by a corresponding fractional number between 0 and 1. Many different schemes or models have been devised for mapping full colors into numbers. Often an ordered triple of numbers are used to specify each color. To use this approach we need an operator which takes the specifying numbers as arguments and returns the desired color as a result. In Interpress these are called color operators. An Interpress color operator takes a vector of numbers as an operand and returns an object of type color. The operand is a vector so that the same format can be used for color operators that need one number to specify the color, as for operators that use a two or three number specifications. The result is a constant color.
The composed operator stored in frame variable 0 of Example 5 is a simple example of a color operator. A color operator takes a vector of numbers v and returns a constant color.
<v: Vector of Numbers> <colorOp: Operator> DO <col: Constant Color>
You would use a color operator whenever you specify color by number rather than by name.
Including a color map and a composed operator in your master lets you build and use custom color tables. You could replace or add colors to the table as the need arose. However, if the map grows very large, the master would become unwieldly and printer performance would suffer. When this happens, you might want to move both the map and operator into your printer's environment. You could still reference colors in the same way, but now your master, rather than defining the operator itself, would obtain the color operator from the printer's environment using FINDCOLOROPERATOR.
3.3 FINDCOLOROPERATOR
<v: Vector of Identifiers> FINDCOLOROPERATOR <colorOp: Operator>
The universal name of the desired color operator is v. The printer uses it to look up the operator in the environment and return it on the stack. If the named color operator cannot be found, then a master error occurs.
If we transferred the color operator from Example 5 to the printer's environment and named it [IPBook, ColorMapOp], then we could use the following statements to specify color in the master. They assume that the color map which the color operator uses also exists in the printer's environment.
Example 6
. . .
2 1 2 MAKEVEC --column 2, row 1--
Identifier "IPBook"
Identifier "ColorMapOp"
2 MAKEVEC --name of color operator--
FINDCOLOROPERATOR --retrieve the operator--
DO --execute it--
13 ISET
. . .
Besides leading to the efficient implementation of color operators, FINDCOLOROPERATOR also lets you include standard color maps in your printer where a master can access them. For example, if you want to use the PantoneÒ color set, you would build a table that maps the Pantone color numbers to printer inks and install it on your printer, along with the named color operator [YourName, PantoneOp]. You can then use this named operator in your Interpress masters.
Placing the color operator in the printer's environment frees us from some of the constraints of Interpress. We need a procedure which can produce objects of type Color, but it does not have to be an Interpress composed operator. It does not have to build Interpress vectors. The operator may not require an actual color map, but rather may generate the printer's color representation directly from the numbers passed to it in its operand vector. This can be done when there is a simple function or algorithm describing the correspondence between the color mapping that the operator describes and the internal color representation used by the printer. If the color operator is based on such a function instead of a table it might allow the numbers that specify colors to be fractions (as does MAKEGRAY).
4. COLOR MODELS
The practical limit to the size of a set of named colors falls far short of all the colors you can perceive and conceivably use in a document. Even a conservative estimate puts the number of perceptible colors at over a million, with some estimates as high as ten million. Some applications, such as graphic design and computer-aided engineering, are satisfied with anywhere from a dozen to several hundred judiciously selected colors. Other applications, such as computer image generation and color picture processing, need continuously variable color in order to obtain precise color control and smooth shading. Applications that require continuous or, in the case of digital systems, finely quantized colors use color coordinates to specify the colors they use.
We use various color spaces to help us organize how we think about and control color. For example, we could conceive of a color that we would describe as a ``dark grayish red.'' This description illustrates the three variables of subjective color appearance: hue (``red''), saturation or chroma (``grayish'') and lightness (``dark''). Hue is the attribute with a circular scale, labeled with the names blue, green, yellow, red, purple and so on. Lightness is the intensity of the color on a scale from dark through light. Gray or achromatic colors have no hue but can range in lightness from black to white. Chroma is the difference between a color and a gray with the same lightness. Hue, chroma and lightness define a cylindrical coordinate system for color space (see Figure 3). There have been many attempts to devise numeric scales for these variables; the Munsell Color System is one of the earliest and most popular. To define it, subjects selected painted samples which they judged under controlled viewing conditions to be uniformly distributed along the dimensions of hue, chroma and lightness.
Besides subjective measures of color appearance, we can also use objective measures, such as tristimulus values, which ultimately rely on instrument standards. Objective color coordinate systems are based on trichromacy, an experimental law of human color vision that states that the majority of human observers can match any color by adding together suitable amounts of light from three fixed primary colors. The amounts of the primaries used to match a given color are called its tristimulus values. They specify the visual appearance of a color in the sense that two colors that have the same tristimulus values will look the same. Trichromacy explains why color output devices only need three inks or phosphors: to reproduce tristimulus values, they need only three degrees of freedom.
===
[Artwork node; type 'Artwork on' to command tool]
Figure 3. Cylindrical coordinate system based on lightness, chroma and hue perceptual variables.
===
You can use tristimulus values based on any three primaries. In the interests of standardizing the determination of tristimulus values, the International Commission on Illumination1 defined an ideal or Standard Observer, so that instruments rather than human subjects could be used to measure and specify tristimulus values. The tristimulus values of the Standard Observer are labeled X, Y and Z. The formal description of a color C in terms of X,Y,Z values is
=== length: 1 in
1 It is usually referred to by its initials in French, which are CIE.
C = X X + Y Y + Z Z
The ``='' signifies that the color C is matched by the sum of X units of light from primary X, Y units from Y and Z units from Z. The standard system was designed so that the Y value is the luminance, the correlate of intensity; two different colors with the same luminance will have the same intensity or lightness.
While we could define a color operator that expected X,Y,Z tristimulus values, it makes sense in practical systems to use tristimulus values based on a set of primaries that are close to those used by real color output devices. In particular, if the primaries are red, green and blue, then their tristimulus values R, G and B would represent the red, green and blue content of a color. Since the color matching equation given above is a linear equation, R,G,B values are related to X,Y,Z values by a linear transformation. Most color scanners, many computer graphics programs and all color monitors use R,G,B values, so they are an excellent choice for representing color in an Interpress master.
In the same way that we use (x,y) spatial coordinates to specify the position of a mask on a page, we can use (R,G,B) tristimulus values to specify the location of an ink in color space. Black is at the origin of the coordinate system. The red, green and blue primaries are usually calibrated so that equal amounts give grays along a scale from black to white. The amounts of the primaries that add together to give white are usually normalized so that they have value 1. Therefore, the white point is at (1,1,1) in the coordinate system. The line joining the black and white points in color space is the neutral or gray axis. The point (1,1,0), for example, represents the additive mixture of the red and green primaries, or yellow. (See Figure 4 and Plate 3).
===
[Artwork node; type 'Artwork on' to command tool]
Figure 4. Rectangular coordinate system based on red, green and blue tristimulus values.
===
To use R,G,B values in a master, we will invent a color operator [IPBook, RGBOp] and register it in the environment of our printer. [IPBook, RGBOp] converts the color specification (R G B 3 MAKEVEC) into a constant ink. We can then use it in the following master to create the color chart shown in Plate 2.
Example 7
Header "Interpress/Xerox/3.0 " --header--
BEGIN --start of the master--
 { } --preamble--
 { --start of the page--
  0.0254 SCALE CONCATT --use inches for master coordinates--
  1 1 TRANSLATE CONCATT --include offset in T--
  0 0 1 3 MAKEVEC --RGB values for blue--
  Identifier "IPBook"
  Identifier "RGBOp"
  2 MAKEVEC --color operator name--
  FINDCOLOROPERATOR --retrieve from environment--
  0 FSET --save in frame--
  0 FGET DO 13 ISET --retrieve and execute operator, save color--
  0 0 1 1 MASKRECTANGLE --apply ink to page--
  0 1 1 3 MAKEVEC --cyan--
  0 FGET DO 13 ISET 0 1 1 1 MASKRECTANGLE
  0 1 0 3 MAKEVEC --green--
  0 FGET DO 13 ISET 0 2 1 1 MASKRECTANGLE
  0 0 0 3 MAKEVEC --black--
  0 FGET DO 13 ISET 1 0 1 1 MASKRECTANGLE
  0 0 1 3 MAKEVEC --white--
  0 FGET DO 13 ISET 1 1 1 1 MASKRECTANGLE
  0.5 0.5 0.5 3 MAKEVEC --medium gray--
  0 FGET DO 13 ISET 1 2 1 1 MASKRECTANGLE
  1 0 1 3 MAKEVEC --magenta--
  0 FGET DO 13 ISET 2 0 1 1 MASKRECTANGLE
  1 0 0 3 MAKEVEC --red--
  0 FGET DO 13 ISET 2 1 1 1 MASKRECTANGLE
  1 1 0 3 MAKEVEC --yellow--
  0 FGET DO 13 ISET 2 2 1 1 MASKRECTANGLE
 } --end of the page--
END --end of the master--
The sequence (Identifier "IPBook" Identifier "RGBOp" 2 MAKEVEC) is the name that FINDCOLOROPERATOR uses to retrieve the color operator from the printer's environment. The master saves the operator in the frame so that it does not have to look it up every time it converts an RGB vector to an ink. Since Interpress itself does not define standard color operators other than MAKEGRAY, there is no primitive operator to make a color from an RGB specification. However, the sequence (0 FGET DO) in this master gets and executes such an operator that originated in the printer's environment.
The printer that rendered Plate 2 substituted its notion of red, green and blue for the primaries we used to specify the ink. When it is important to use RGB to define a color precisely, then the exact nature of the red, green and blue primaries and the white used to normalize them would have to be specified (usually in terms of CIE Standard tristimulus values, XYZ) and made part of the color operator.
The color operator [IPBook, RGBOp] behaves analogously to the current transformation T in Interpress. In the same way that T converts master coordinates to device coordinates, a color operator converts the master's color representation of an ink to the device-dependent version of the ink (see Figure 5).
===
[Artwork node; type 'Artwork on' to command tool]
Figure 5. Specifying a constant color ink with color coordinates.
===
The use of named color operators allows each printer to retrieve from its environment an operator that produces a color that is the best interpretation of what the document creator specified in the master. On a color printer, the [IPBook, RGBOp] operator would create an ink using all three color coordinates. On the other hand, the [IPBook, RGBOp] operator on a black-and-white or gray scale printer would create a gray ink that is the printer's best effort at producing the ink specified by the master. It might choose, for instance, to use a gray ink based on the maximum value of the R,G,B values. Or it might choose to do the same thing that black-and-white film or a black-and-white television receiver does when presented with a color scene, which is reproduce the intensity of the colors in the scene but ignore their hue and chroma.
As a document creator, you can ease the burden that full color specifications place on black-and-white printers by using black-and-white compatible color coordinate systems to describe full color inks. A black-and-white compatible color system aligns one of its three coordinate axes with the neutral or gray axis. Therefore, one of the coordinates records the gray intensity or achromatic content of the color while the other two record the chromatic content or hue and chroma of the specified color. As an example of a black-and-white compatible system, we will define a new coordinate system called YES. YES coordinates are related to RGB by the following linear transformation
Y = a1 R + a2 G + (1 - a1 - a2) B
E = 1/2 (R - G)
S = 1/4 (R+G) - 1/2 B
Y is the luminance; a1 and a2 are constants that depend on the red, green and blue primaries and white that define the RGB tristimulus values. We will use values based on the red, green and blue phosphors used in broadcast studio monitors and the standard white illumination used in the graphic arts: a1=0.68 and a2=0.25. For white, Y=1. E and S are opponent-color values: E is red-minus-green and S is yellow-minus-blue. For gray, R,G and B are all equal so that E and S are zero. (See Figure 6 and Plate 4).
To use YES coordinates in a master, we would invent a color operator, call it [IPBook, YESOp] and install it in the environment of our color and black-and-white printers. On a color printer, the operator would be defined so that it created a full color ink, much as if you had used an RGB representation in the master. When a black-and-white printer encounters an ink specified in terms of YES values, it would use its version of the [IPBook, YESOp] to ignore the E and S values and create a gray ink based on the luminance value Y. The effect of executing the color operator [IPBook, YESOp] on a black-and-white printer with the argument (Y E S 3 MAKEVEC) is equivalent to the following statements
===
[Artwork node; type 'Artwork on' to command tool]
Figure 6. Rectangular coordinate system based on luminance Y and opponent-color values E and S.
===
Example 8
Y E S 3 MAKEVEC --YES values--
0 GET --get Y, ignore E and S--
NEG 1 ADD -- f = 1 - Y --
MAKEGRAY --make gray ink--
The following master encodes color using YES coordinates. It produces Plate 2 when executed on a color printer and Figure 7 when run on a black-and-white printer.
Example 9
Header "Interpress/Xerox/3.0 " --header--
BEGIN --start of the master--
 { } --preamble--
 { --start of the page--
  0.0254 SCALE CONCATT --use inches for master coordinates--
  1 1 TRANSLATE CONCATT --include offset in T--
  0.07 0 -0.5 3 MAKEVEC --YES values for blue--
  Identifier "IPBook"
  Identifier "YESOp"
  2 MAKEVEC --color operator name--
  FINDCOLOROPERATOR --retrieve from environment--
  0 FSET --save in frame--
  0 FGET DO 13 ISET --retrieve and execute operator, save color--
  0 0 1 1 MASKRECTANGLE
  0.75 -0.5 -0.25 3 MAKEVEC --cyan--
  0 FGET DO 13 ISET 0 1 1 1 MASKRECTANGLE
  0.68 -0.5 0.25 3 MAKEVEC --green--
  0 FGET DO 13 ISET 0 2 1 1 MASKRECTANGLE
  0 0 0 3 MAKEVEC --black--
  0 FGET DO 13 ISET 1 0 1 1 MASKRECTANGLE
  1 0 0 3 MAKEVEC --white--
  0 FGET DO 13 ISET 1 1 1 1 MASKRECTANGLE
  0.5 0 0 3 MAKEVEC --medium gray--
  0 FGET DO 13 ISET 1 2 1 1 MASKRECTANGLE
  0.32 0.5 -0.25 3 MAKEVEC --magenta--
  0 FGET DO 13 ISET 2 0 1 1 MASKRECTANGLE
  0.25 0.5 0.25 3 MAKEVEC --red--
  0 FGET DO 13 ISET 2 1 1 1 MASKRECTANGLE
  0.93 0 0.25 3 MAKEVEC --yellow--
  0 FGET DO 13 ISET 2 2 1 1 MASKRECTANGLE
 } --end of the page--
END --end of the master--
===
[Artwork node; type 'Artwork on' to command tool]
Figure 7. Luminance only version of Plate 2.
===
4.1 Color Model Operators
The YES color encoding used by the operator [IPBook, YESOp] assumes that the Y value is 0 for black and 1 for white. However, the luminance could be encoded in a digital master using 6, 8, 10 or however many bits of precision are needed by the document creator. When Y is represented by 8 bits, it has 256 levels, with black at 0 and white at 255. You could invent a new color operator for this encoding, but providing different color operators for every conceivable encoding would be inefficient and a wasteful use of printer storage.
Interpress allows you to group together different color operators that share the same general characteristics and treat them as a single color model. An example of a color model is the group of color operators for all possible encodings of YES values. A master uses a color model operator to extract one particular operator from the model.
<parameters:Vector> <colorModelOp:Operator> DO <colorOp:Operator>
colorModelOp is an operator that takes a vector argument parameters and returns the color operator specified by parameters on the stack.
You have the option of composing your own color model operator and including it in a master. For 8 bit Y values, it would return a composed color operator that first scaled the 8 bit Y,E,S values by 1/255 and the invoked the color operator [IPBook, YESOp]. However, as we saw with color operators, obtaining color model operators from the printer's environment almost always leads to more efficient implementations. You can do this with FINDCOLORMODELOPERATOR.
<v:Vector of Identifiers> FINDCOLORMODELOPERATOR <colorModelOp: Operator>
The universal name of the color model operator is v. If the master cannot find the named operator in the environment, then a master error occurs.
To handle different YES encodings in a master, we will invent a color model operator, call it [IPBook, YESModel] and define it to take the argument vector (swhite sblack sneutral srange 4 MAKEVEC). Executing this color model operator returns a color operator that first scales the encoded Y,E,S values so that Y lies between 0 and 1 and E and S between -0.5 and 0.5. It then executes the [IPBook, YESOp] color operator to convert the normalized YES values to a constant ink. The mappings of the encoded Y,E,S values are determined by the parameters of the color model operator's argument vector.
Y = (Yencoded - sblack)/(swhite - sblack)
E = (Eencoded - sneutral)/srange
S = (Sencoded - sneutral)/srange
You will observe that this mapping lets you encode E and S, which can both have negative values, as positive integers in a master. Let us assume that Y,E,S are each encoded with 8 bits and that an offset is added to E and S so that their encoded values are positive. The YES specification for magenta is (0.41 0.5 -0.25 3 MAKEVEC). It would be encoded as (105 255 64 3 MAKEVEC). The parameters vector containing swhite, sblack, sneutral, srange for this encoding is (255 0 128 255 4 MAKEVEC).
From the above equations, which describe what the color operator will do, we see that
Y = (105 - 0) / (255 - 0) = .41
E = (255 - 128) / 255 = .5
S = (64 - 128) / 255 = -.25
The following statements create a constant ink from the YES specification for magenta using this encoding.
Example 10
105 255 64 3 MAKEVEC --encoded YES values for magenta--
255 0 128 255 4 MAKEVEC --argument for color model operator--
Identifier "IPBook"
Identifier "YESModel"
2 MAKEVEC --color model operator name--
FINDCOLORMODELOPERATOR --retrieve it--
DO --execute it to get color operator--
DO --execute color operator to get color--
4.2 Standard Color Models
The progression from FINDCOLOR through FINDCOLOROPERATOR to FINDCOLORMODELOPERATOR allows increasing degrees of abstraction in specifying color or ink color in an Interpress master. Their use permits you to specify color in a way that is most suited to your application, while at the same time allowing the printer to implement the color representation in the most efficient way.
The named colors, operators and color models that a document creator uses in a master and a printer stores in its environment are not part of the Interpress standard but are defined in companion standards. This is because Interpress is only one part of a distributed document processing system which needs color descriptions that would apply to all elements of the system and not just to the link between a document creator and a printer. By obtaining colors and color models from its environment, a printer can use the same color descriptions as the other system elements. Xerox printers, for example, follow the Xerox Raster Encoding Standard which defines color models for gray or neutral colors. It includes color models for gray values sampled in luminance, density and lightness as well as models for mapped color and gray values. The Xerox models for full color representation are under development and although they have been described in the literature, they have not yet been issued as standard. They will, however, take the form that has been described here.
As an example of a color model operator defined in the Xerox Raster encoding standard, let's look at the [Xerox, GrayDensity] operator. We have already seen in Example 2 how optical density can be used to specify grays. In that example we took density values and converted them by hand to absorptance values which we then gave to SETGRAY. Now we shall see how we can replace the SETGRAY with a color operator that understands the density values directly. This operator will be generated by the [Xerox, GrayDensity] color model operator.
The GrayDensity color model operator takes a vector of the form [swhite, sblack, Dblack, pixelMap] as its operand. The pixelMap provides an extra mapping of the encoded values, but this step is ignored if it is 0, and we shall so set it. The swhite, sblack, and Dblack parameterize the encoding according to
d = ( (dencoding - swhite) / (sblack - swhite) ) Dblack
For the simple case of d=dencoding we should create the operator with swhite=0, sblack=1, Dblack=1. To show how this all works, let us now redo Example 2, making and using the density color operator.
Example 10.5
Header "Interpress/Xerox/3.0 " --header--
BEGIN --start of the master--
 { } --preamble--
 { --start of the page--
  0.0254 SCALE CONCATT --inches for master coordinates--
  1 1 TRANSLATE CONCATT --include offset as part of T--
  0 1 1 0 4 MAKEVEC --parameters for the color model operator--
  Identifier "Xerox" Identifier "GrayDensity" 2 MAKEVEC
  FINDCOLORMODELOPERATOR --find the color model operator--
  DO --create the color operator--
  0 FSET --save it in Frame[0]--
  1.2 1 MAKEVEC --density 1.2 argument to color operator--
  0 FGET DO --execute the color operator to make the color--
  13 ISET --install it as the current color--
  0 0 1 1 MASKRECTANGLE --show it--
  0.9 1 MAKEVEC 0 FGET DO 13 ISET --set density to 0.9--
  1 0 1 1 MASKRECTANGLE
  0.6 1 MAKEVEC 0 FGET DO 13 ISET --set density to 0.6--
  2 0 1 1 MASKRECTANGLE
  0.3 1 MAKEVEC 0 FGET DO 13 ISET --set density to 0.3--
  3 0 1 1 MASKRECTANGLE
  0 1 MAKEVEC 0 FGET DO 13 ISET --set density to 0--
  4 0 1 1 MASKRECTANGLE
 } --end of the page--
END --end of the master--
This produces the same output as Example 2. In using the printer's GrayDensity color model operator, a change in color is a little more work for the printer and a little less work for the creator. The printer must now convert the density to absorptance.
5. SAMPLED COLOR
In Interpress, black and white spots can be represented as a vector of binary sample values. One can create pixel arrays from the samples, and used them to print pictures and patterns. Now we have also seen how to specify colors in Interpress. These two ideas can be combined to let us image colored pictures and patterns. We can construct samples vectors where each sample specifies the color of a pixel. Each pixel can have its own color, and the combined raster will form the colored ink. We call this sampled color. Sampled color is used to place full color, gray or black-and-white raster images on a page. The images can come from a document scanner or a computer program; they can be scanned photographs, computer-generated scenes or graphic designs. What they all have in common is that they are represented as a pixel array, where each pixel consists of a color specification. For example, each pixel could have red, green and blue intensity values. This means that there might be more than one sample value per pixel. We would need a sample value for each coordinate so a single pixel in our example would need three samples (one for the red intensity, one for the green, and a third for the blue).
It is also possible to use named colors in the specification of pixels if we first make a table of all the named colors we wish to use. We can then make a samples vector from the indices into the table. In this case, each pixel will have a single sample value, which is a table index. The corresponding entry in the table is the color of the pixel.
5.1 Multi-Sample Pixel Arrays
We construct a colored pixel array in the same way as a binary pixel array; you use the MAKEPIXELARRAY operator. The difference is that now we have a need for all of the arguments to the operator (before, three of them — samplesPerPixel, maxSampleValue, samplesInterleaved — were always set to 1). MAKEPIXELARRAY acts somewhat like the array declaration and initialization statements found in most computer languages. You construct an object known as a pixel array from a vector of image samples and the parameters that describe their format and the raster that produced them. Once again, the formal description of MAKEPIXELARRAY is
<xPixels: Cardinal> <yPixels: Cardinal>
<samplesPerPixel: Cardinal>
<maxSampleValue: Cardinal or Vector of Cardinal>
<samplesInterleaved: Cardinal>
<m: Transformation>
<samples: Vector>
MAKEPIXELARRAY
<pa:PixelArray>
The convention that Interpress uses to orient the pixel array coordinate system with the sampling raster defines the number of pixels per scan line as yPixels and the number of scan lines in the raster as xPixels. The definition of the sampling raster also includes samplesPerPixel, since a pixel can require more than one sample to specify its color. A color image might have three samples per pixel, specifying for example the red, green and blue content at each point in the image. Each sample is a separate element in the samples vector; therefore the number of elements in the vector is
samplesPerPixel ´ yPixels ´ xPixels
An image sample is a Cardinal (a non-negative integer) that can have a value between 0 and a maximum specified in the pixel array declaration. The reason for this limit is to allow mapping between a normalized range of samples used by the printer, and the ranges natural to packed encoding of the samples. For example, the printer may use 1 for black and 0 for white. This is a good match for binary images, but for a gray-scale image the scanner may provide 256 gray levels. These could be packed as one byte per sample, so each sample value can be an integer between 0 and 255 inclusive. The maxSampleValue indicates the largest possible number which can occur as a sample value. This will indicate the minimum number of bits required to store an arbitrary sample. The printer can use this information if it attempts to pack the samples vector into some compact internal representation.
When there is only one sample per pixel, then its value lies between 0 and the argument maxSampleValue. For 1 bit samples, the maximum sample value would be 1; for 8 bit samples, it would be 255. When there is more than one sample per pixel, then we must know the maximum value for each component in the color specification. If they are all the same (say 255 for each), then we only need to specify the single maxSampleValue number. But Interpress allows you to have different limits for each of the components. Suppose that you allowed 3 bits for each red sample, 3 bits for each green sample, but only 2 bits for each blue sample. The red and green samples can have values between 0 and 7, but the blue samples can only range between 0 and 3. To make this known to the printer, we would use a vector of Cardinals as maxSampleValue rather than a single Cardinal. In this case, it would look like:
( 7 7 3 3 MAKEVEC )
When maxSampleValue is a vector, the ith sample of a pixel has a value that lies between 0 and (maxSampleValue i GET), which is the ith element of maxSampleValue. Since the maxSampleValue vector uses zero-based indexing, 0 < i < samplesPerPixel-1. Although Interpress does not allow negative sample values, this is not a serious limitation because, as we have seen, color operators can be constructed with built-in biasing.
The scanned data for multiple-sample pixels are ordered in the samples vector in the way that they were scanned or generated. Although the vector samples containing the image samples is a 1-dimensional vector of length xPixels ´ yPixels ´ samplesPerPixel, it can also can be considered a 3-dimensional array of samples s(x,y,i), where the three indices select the scan line (x), the pixel on the scan line (y) and sample of the pixel (i). There are six permutations of three indices, which reduce to three combinations, since pixels (y index) have to be nested within scan lines (x index). To show the three ways of ordering samples, pixels and scan lines, we use three Pascal array-type definitions
array [0..xPixels-1] of array [0..yPixels-1] of array [0..samplesPerPixel-1] of sample;
 (* samples interleaved *)
array [0..xPixels-1] of array [0..samplesPerPixel-1] of array [0..yPixels-1] of sample;
 (* sample lines interleaved *)
array [0..samplesPerPixel-1] of array [0..xPixels-1] of array [0..yPixels-1] of sample;
 (* sample arrays interleaved *)
These array-type definitions nest arrays from right to left, with the index of the rightmost array looping fastest. Each of these type definitions implies a different ordering of the image samples in the vector argument to MAKEPIXELARRAY.
The first ordering interleaves samples so that the different samples of a single pixel are successive elements in the vector. You can think of the vector as xPixels X yPixels successive sequences of samplesPerPixel elements. Imagine a scanner which examines each pixel and determines its complete color specification (e.g., red, green, and blue components) before moving on to the next pixel. This ordering is also natural to computer-generated sample images, where the computer determines the complete color specification of each pixel.
The third ordering divides the sample vector into samplesPerPixel successive sequences of xPixels X yPixels elements. The first sequence contains the first color component for all the pixels, the second sequence contains all the sample values for the second component, and so on. A samples vector with this ordering would be produced by a scanner which first samples an entire image through a red filter to obtain the red color component of every pixel. Next it samples the entire image through a green filter to obtain the green components. Finally, the scanner samples the image through a blue filter. The result is three ``images'' back-to-back, as seen through the red, green, and blue filters. Putting these three images together yields the full color image.
Because the first and third orderings are common, they are directly supported by MAKEPIXELARRAY. Your sample vector can be in either of the two orders, and all you need do is specify which one you are using. This is done with the samplesInterleaved parameter. This parameter's value can either be 0 or 1. If it is 1, the first ordering is assumed. The samples for the various color components are said to be interleaved. If samplesInterleaved=0, then the third ordering is assumed.
The following statements construct a pixel array from the red, green and blue samples values of the color matrix shown in Plate 2. The samples occur in the standard order: the first pixel of the array is at the lower left corner of the matrix and the pixels are read off bottom to top and the left to right. In this example, the samples are not interleaved.
Example 11
3 3 --3 scan lines, 3 pixels per scan line--
3 --3 samples per pixel--
255 --same maximum sample value for all--
0 --samples not interleaved--
1 SCALE --standard scanning order--
0 0 0 0 255 128 255 255 255 --red samples--
0 255 255 0 255 128 0 0 255 --green samples--
255 255 0 0 255 128 255 0 0 --blue samples--
27 MAKEVEC --make samples vector--
MAKEPIXELARRAY --construct pixel array--
8 FSET --save in frame for next example--
When there is only one sample per pixel, then there is no difference between an interleaved and a non-interleaved sample vector and the value of samplesInterleaved can be either zero or non-zero.
The second ordering of the three corresponds to interleaved sample lines. Since this ordering is rare, it is not directly supported by Interpress. Although you can construct a sample vector in this form, you cannot use it as an argument for MAKEPIXELARRAY, but instead you have to reorder the sample values so that they have one of the two forms that MAKEPIXELARRAY accepts. This reordering can be accomplished by means of a decompression operator. As the name suggests, these operators are intended for decompressing image data, but can be used for any reordering of sampled image data. A decompression operator takes as its argument a vector which contains the pixel data and any other parameters that it needs and returns a vector with either interleaved or non-interleaved samples.
Once you have constructed a pixel array, you can no longer access individual sample values. You can, however, form a new pixel array by selecting a subset of the samples for all the pixels in the array. It may be that your source file has three color components per sample, but you only wish to image one of them. Perhaps you intend to send the image to a black-and-white printer; and instead of relying on the printer's best effort to print the colored image, you prefer to select and print one of the color components. Or perhaps you have a full color printer, but only wish to image one or two of the components for proofing purposes. Interpress provides the primitive operator EXTRACTPIXELARRAY to do this.
<pa:PixelArray> <select:Vector of Cardinal> EXTRACTPIXELARRAY <p:PixelArray>
EXTRACTPIXELARRAY creates a pixel array p from the samples of the original array pa whose indices are given in the vector select. For example, to form a pixel array that contains only the first color component of a pixel array stored in frame variable 8, you would write:
Example 12
8 FGET -- retrieve pixel array--
0 -- select sample with index 0--
1 MAKEVEC -- make it into a vector--
EXTRACTPIXELARRAY  -- construct pixel array from selected samples--
To select the first and third color coordinates for each pixel, you would write:
8 FGET
0 2 --select samples with indices 0 and 2--
2 MAKEVEC
EXTRACTPIXELARRAY  -- construct pixel array from selected samples--
The pixel array p created by EXTRACTPIXELARRAY has the same values for xPixels, yPixels, samplesInterleaved and the transformation m as the original pixel array pa. samplesPerPixel is equal to the number of elements in the vector select. Just as EXTRACTPIXELARRAY extracts the indicated samples from each pixel in the original array, it extracts their maximum sample values from the original maxSampleValue vector to form a new maxSampleValue vector.
5.2 MAKESAMPLEDCOLOR
Pixel arrays that are created from binary samples could be made into masks or black-and-white inks. The pixel arrays that we now know how to make from color samples would be meaningless as masks but can be made into inks. An Interpress master places scanned color images on the page by making them into sampled inks and applying them through a mask.
To create a sampled ink from a pixel array, you have to supply two pieces of information. One is a coordinate transformation so that the printer can map the pixel array to device coordinates. The other is a color operator that tells the printer how to interpret the sample values of the pixel array. The Interpress operator MAKESAMPLEDCOLOR uses both of these to create a sampled ink from a pixel array.
<pa: PixelArray> <um:Transformation> <colorOp:Operator> MAKESAMPLEDCOLOR
 <col: Color>
pa is the array of pixels: each pixel consists of samplesPerPixel samples which the color operator colorOp uses as coordinates of the color specified by each pixel in a color space or a color map. You have to match the color operator to the contents of the pixel array. If the pixel array contains RGB values encoded with 8 bits, for example, then you must specify the color operator that converts that encoding to ink values.
The xPixels ´ yPixels scanned image is transformed to device coordinates by the transformation <m um CONCAT>. The transformation m is part of the pixel array definition; you can use it to size, orient and position the pixel array in the master coordinate system. You then use um to transform the pixel array from master to device coordinates; um is usually the same as the current transformation.
MAKESAMPLEDCOLOR combines the transformation, color operator and pixel array to create an object of type Color which it leaves on the stack. To show the ink created by MAKESAMPLEDCOLOR, you would store it in the color imager variable using the statement (13 ISET) and then use a mask operator to apply it to the page. You may remember that a color operator was defined as taking a vector of numbers and using them to produce a constant ink. In the case of MAKESAMPLEDCOLOR, the samples of a pixel are the arguments to the color operator. Therefore, the color operator converts an array of pixels into an array of constant inks or a sampled ink. This ink can be tiled in the same way that the sampled ink we created by using MAKESAMPLEDBLACK could be tiled. In fact, MAKESAMPLEDBLACK can be considered a special case of MAKESAMPLEDCOLOR. Instead of a color operator, MAKESAMPLEDBLACK used the variable clear, since there were only two interpretations allowed for the binary sample values of the array (0 is white ink or transparent ink, 1 is black ink).
To convert the pixel array that we created in Example 11 to a sampled ink, we need a color operator for 8 bit RGB values. Although we could define a color model operator for RGB samples and use it to produce a color operator for 8 bit values, we will instead create a color operator [IPBook, RGBOp8] specifically for this encoding, since we want the most efficient operator implementation possible. This color operator is obtained by executing the following statements
Example 13
Identifier "IPBook"
Identifier "RGBOp8"
2 MAKEVEC --color operator name--
FINDCOLOROPERATOR --look up color operator---
The following Interpress master uses this result to turn the RGB pixel array of Example 11 into a sampled ink which is then applied to the page to produce the color image shown in Plate 2.
Example 14
Header "Interpress/Xerox/3.0 " --header--
BEGIN --start of the master--
 { } --preamble--
 { --start of the page--
  0.0254 SCALE CONCATT --use inches for master coordinates--
  1 1 TRANSLATE CONCATT --include offset in T--
  3 3 --3 scan lines, 3 pixels per scan line--
  3 --3 samples per pixel--
  255 --same maximum sample value for all--
  0 --samples not interleaved--
  1 SCALE --image is 3 inches square--
  0 0 0 0 255 128 255 255 255 --red samples--
  0 255 255 0 255 128 0 0 255 --green samples--
  255 255 0 0 255 128 255 0 0 --blue samples--
  27 MAKEVEC --make samples vector--
  MAKEPIXELARRAY --construct pixel array--
  4 IGET --use current transformation as um--
  Identifier "IPBook" Identifier "RGBOp8"
  2 MAKEVEC --color model operator name--
  FINDCOLOROPERATOR --look up color model operator---
  MAKESAMPLEDCOLOR --create sampled ink--
  13 ISET --save in imager--
  0 0 3 3 MASKRECTANGLE --apply ink to page--
 } --end of the page--
END --end of the master--
The transformation (1 SCALE) produces a 3 inch square pixel array in the master coordinate system, with its lower left hand corner at the origin. um is the transformation (1 1 TRANSLATE 0.0254 SCALE CONCAT TID CONCAT). It first translates the pixel array in master coordinates to the desired location on the page using (1 1 TRANSLATE). It then transforms the array to device coordinates using (0.0254 SCALE TID CONCAT). MAKESAMPLEDCOLOR converts the transformed pixel array to a sampled ink using the color operator for 8 bit RGB values. To image the pixel array on the page, we store the sampled ink created in the color imager variable and then call the MASKRECTANGLE operator to apply the ink to the page (see Figure 8).
===
[Artwork node; type 'Artwork on' to command tool]
Figure 8. Specifying a sampled ink with an array of color coordinates.
===
When we use constant inks that by definition have the same value over the entire page, the object that we want to make visible on the page is defined by the mask. But with a sampled ink created from a scanned image, the object we want to make visible is defined by the ink so that we pay particular attention to how it is transformed. We position the pixel array (and hence the sampled ink) as required and make sure that the rectangular mask has the same position. They start with the same position and size in the master coordinate system. The pixel array is transformed to device coordinates by the current transformation T. Since um and T have the same value in this example, the sampled ink and the mask end up with the same size and position in the device coordinate system.
Interpress has a convenience operator SETSAMPLEDCOLOR for creating sampled inks.
<pa: PixelArray> <vm:Transformation> <colorOp:Operator> SETSAMPLEDCOLOR <>
SETSAMPLEDCOLOR differs from MAKESAMPLEDCOLOR in two ways. First, it does not leave the sample ink on the stack but instead transfers it to the imager; therefore, there is no need to use (13 ISET). Second, SETSAMPLEDCOLOR applies the transformation (m vm CONCAT T CONCAT) to the pixel array to map it from pixel array to device coordinates. With MAKESAMPLEDCOLOR, you had to explicitly transform the ink to device coordinates. But with SETSAMPLEDCOLOR, you don't have to be too concerned about device coordinates. You can include the translation required for positioning in the current transformation, as was done for MAKESAMPLEDCOLOR. In this case vm is the identity (1 SCALE). But alternatively you can use vm to specify the positioning transformation. You define vm so that the transformation (m vm CONCAT) positions the ink where you want it in the master coordinate system. SETSAMPLEDCOLOR then automatically applies the current transformation to map the ink to device coordinates. Unless you need direct control over the placement of sampled ink in device coordinates, you normally use SETSAMPLEDCOLOR to create sampled inks in master coordinates and then let the current transformation take care of their placement in the device coordinate system.
Rewriting Example 14 so that it uses SETSAMPLEDCOLOR gives the following master.
Example 15
Header "Interpress/Xerox/3.0 " --header--
BEGIN --start of the master--
 { } --preamble--
 { --start of the page--
  0.0254 SCALE CONCATT --use inches for master coordinates--
  1 1 TRANSLATE CONCATT --include offset in T--
  3 3 --3 scan lines, 3 pixels per scan line--
  3 --3 samples per pixel--
  255 --same maximum sample value for all--
  0 --samples not interleaved--
  1 SCALE --image is 3 inches square--
  0 0 0 0 255 128 255 255 255 --red samples--
  0 255 255 0 255 128 0 0 255 --green samples--
  255 255 0 0 255 128 255 0 0 --blue samples--
  27 MAKEVEC --make samples vector--
  MAKEPIXELARRAY --construct pixel array--
  1 SCALE --already positioned and sized--
  Identifier "IPBook" Identifier "RGBOp8"
  2 MAKEVEC --color model operator name--
  FINDCOLOROPERATOR --look up color model operator--
  SETSAMPLEDCOLOR --create and store sampled ink--
  0 0 3 3 MASKRECTANGLE --apply ink to page--
 } --end of the page--
END --end of the master--
In this example, we placed the origin of the master coordinate system at the lower left corner of the image. The rectangular mask has the same size and position in master coordinates as the pixel array. We defined the current transformation T so that it would translate both of them together to the desired location on the page (expressed in master coordinates) and then transform them to device coordinates.
While the examples that we have used created only simple sampled inks, the principles they have demonstrated apply equally well to imaging larger and more complicated pixel arrays. The next example shows the master that takes a 4"´5" color photograph, scanned by an RGB input scanner in the standard order (bottom to top, left to right) at 200 pixels per inch in both directions. Executing this master produces the illustration shown in Plate 5.
Example 16
Header "Interpress/Xerox/3.0 " --header--
BEGIN --start of the master--
 { } --preamble--
 { --start of the page--
  0.0254 SCALE CONCATT --use inches for master coordinates--
  1 1 TRANSLATE CONCATT --include offset in T--
  800 1000 --800 scan lines, 1000 pixels per scan line--
  3 --3 samples per pixel--
  255 --same maximum sample value for all--
  1 --samples interleaved--
  1/200 SCALE --scale to 4"
´5"--
  sequenceLargeVector --long sequence encoding of sample vector--
  24 9F 01 --sequence length--
  01 --1 byte per sample--
  34 12 . . . 28 --sample bytes--
  MAKEPIXELARRAY --construct pixel array--
  1 SCALE --use identity transformation for vm--
  Identifier "IPBook" Identifier "RGBOp8"
  2 MAKEVEC --color operator name--
  FINDCOLOROPERATOR --look up color operator--
  SETSAMPLEDCOLOR --create and save sampled ink--
  0 0 4 5 MASKRECTANGLE
 } --end of the page--
END --end of the master--
This master uses the sequenceLargeVector encoding to encode the sample vector as a sequence of 2,400,001 bytes (249F01 in hex). The first byte in the sequence is ``01'' and means that each of the samples is stored in a single byte. The master scales the pixel array by 1/200 so that its size is 4´5 in master coordinate units (inches). The ink created by SETSAMPLEDCOLOR and the rectangular mask through which it will be applied to the page have the same position and size in the master coordinate system. The printer applies the current transformation to them both to transform them to the device coordinate system.
5.3 Color Operators Revisited
The scanned image in the last example had 800,000 pixels, so that you would not casually send the master that contains it to your local printer. We sent this master to a process color printer that used four halftoned inks (cyan, magenta, yellow and black or C,M,Y,K) to produce Plate 5. In processing the master, the printer ``applied'' the color operator [IPBook/RGBOp8] 800,000 times. The effect that this could have on printer performance is so important that we will consider again what it means to ``apply'' a color operator.
By definition, the color operator converts the RGB specification of the sampled ink in the master to a halftoned CMYK specification that the printer actually uses to render the image. In practice, this conversion is done in two steps. The first step transforms RGB values to CMYK values (color correction). The second converts CMYK values to binary images at the resolution of the printer (halftoning).
Although you could include a composed color operator in the master to do the color correction and halftoning, you would not want to constrain the printer to use it since the resulting performance would likely be intolerable. If there are to be any constraints on printer performance, you would want them to come from the printer and not the master. A color operator retrieved from the printer's environment would almost always give superior performance, since its implementation would be printer-specific and be able to take advantage of special features that the printer has for dealing with certain color encodings. For example, the printer may have hardware for both color correction and halftoning. In this case, ``applying'' the color operator would simply mean marking or tagging the pixel array for hardware processing. On less capable printers, the color operator may have to do the actual processing, using whatever software is at its disposal.
Alternatively, the document creator could assume some of the burden of preparing printer-ready (i.e printer-dependent) samples. The document creator could include in a master already color corrected images, along with a color operator that halftones them, or halftone the image as well and represent them in the master as binary pixel arrays. Nothing in Interpress prevents you from using either of these alternatives. Whether you use RGB files in the master, as we did in Example 16, or CMYK files is not an issue for Interpress, since it can handle both cases, given the proper color operators. Instead, which you use is determined by the standards and procedures for representing color images on your network. Since Interpress was designed for the device-independent representation of printable pages and documents, it encourages the use of device-independent color representations as well by providing powerful facilities in the form of color operators that support them.
6. CONCLUSION
In this chapter we have considered color and the ink component of the Interpress imaging model. We have seen how to produce constant gray shades with the primitive MAKEGRAY and SETGRAY operators. We have also seen how constant colors of any hue or tint can be specified either by name, or by means of a color operator from the printer's environment. We learned how color operators can be generated by color model operators. Finally, we saw how full color patterns and images can be represented as arrays of samples where more than one sample per pixel may be needed. The images can be derived from the samples vectors by the MAKESAMPLEDCOLOR and SETSAMPLEDCOLOR (see Figure 9).
===
[Artwork node; type 'Artwork on' to command tool]
Figure 9. Interpress operators for specifying color. The instructions within a box point to what they produce when they are executed
===