G3dSpectrum.mesa
Copyright Ó 1984, 1992 by Xerox Corporation. All rights reserved.
Glassner, May 10, 1989 12:13:06 pm PDT
Bloomenthal, October 21, 1992 5:01 pm PDT
DIRECTORY G2dBasic, G2dMatrix, ImagerColor;
G3dSpectrum: CEDAR DEFINITIONS
~ BEGIN
Type Declarations
RealSequence:   TYPE ~ G2dBasic.RealSequence;
RealSequenceRep:  TYPE ~ G2dBasic.RealSequenceRep;
Matrix:     TYPE ~ G2dMatrix.Matrix;
RGB:      TYPE ~ ImagerColor.RGB;   -- unscaled RGB: Reals [0-1]
XYZ:      TYPE ~ RECORD [x, y, z: REAL]; -- unscaled XYZ: Reals [0-1]
Triple:     TYPE ~ G2dBasic.Triple;
SpectralSample:   TYPE ~ RECORD [
wavelength:     REAL,
amplitude:     REAL
];
Spectrum:     TYPE ~ REF SpectrumRep;
SpectrumRep:   TYPE ~ RECORD [
length:      CARDINAL,
element:      SEQUENCE maxlength: CARDINAL OF SpectralSample
];
Globals
ntscXYZtoRGBMatrix:     Matrix;
This is the default matrix for conversions from spectra to RGB. It matches a monitor with standard NTSC phosphors: red=[.670, .330], grn=[.210, .710], blu=[.140, .080], wht=[.313, .329]. Thus this matrix is equivalent to the matrix returned by the following call:
TransformFromChromaticities[
[0.670, 0.330, 0.000], [0.210, 0.720, .080], [0.140, 0.080, 0.780], [0.313, 0.329, 0.358]];
ntscRGBtoSpectrumMatrix:    Matrix;
This is the default matrix for the (unsupported) conversion of RGB to spectra.
Basic Operations on a Single Spectrum
New: PUBLIC PROC [firstWavelength: REAL ¬ 380.0, deltaWavelength: REAL ¬ 30.0, numSamples: INT ¬ 16, amplitudes: RealSequence ¬ NIL] RETURNS [new: Spectrum];
Builds a new spectrum. If amplitudes.length < numSamples, the last value is repeated as needed - giving only one value in the sequence thus results in a flat spectrum.
Flatten: PUBLIC PROC [s: Spectrum, amplitude: REAL] RETURNS [Spectrum];
Stores a constant into all entries of the spectrum
Normalize: PUBLIC PROC [s: Spectrum, totalEnergy: REAL ¬ 1.0] RETURNS [Spectrum];
Scales the spectrum so the sum of all entries is totalEnergy
Integrate: PUBLIC PROC [s: Spectrum] RETURNS [energy: REAL];
returns total energy in the spectrum
Scale: PUBLIC PROC [s: Spectrum, scale: REAL] RETURNS [Spectrum];
Multiplies each entry by scale
Offset: PUBLIC PROC [s: Spectrum, offset: REAL] RETURNS [Spectrum];
Adds offset to each entry
Duplicate: PUBLIC PROC [s: Spectrum] RETURNS [new: Spectrum];
Returns a duplicate spectrum (note: this creates a new spectrum, not just a copy of pointers)
Sample: PUBLIC PROC [s: Spectrum, wavelength: REAL] RETURNS [REAL];
Finds the value at the specified wavelength using linear interpolation. Requests above or below the range in the spectrum get the value at the max or min frequency.
Color Space Conversions
SetTransformMatrix: PUBLIC PROC [transform: Matrix ¬ ntscXYZtoRGBMatrix];
Sets the current transformation matrix. This matrix is used by RGBToSpectrum and SpectrumToRGB. The matrix converts from CIE 1931 XYZ space to RGB space for a particular monitor. The default is for the standard NTSC primaries. This procedure need not be called unless you want a different transformation.
TransformFromChromaticities: PUBLIC PROC [r, g, b, w: Triple]
  RETURNS [transform: Matrix];
Returns the CIE XYZ to RGB transformation matrix associated with the given monitor phosphor chromaticities. The chromaticies are given as Triples (XYZ) in CIE XYZ space. To make the result the default, say SetTransformMatrix[TransformFromChromaticities[]].
SpectrumToRGB: PUBLIC PROC [s: Spectrum] RETURNS [rgb: RGB];
Converts from a spectrum to RGB. It uses the current transformation matrix.
RGBToSpectrum: PUBLIC PROC [rgb: RGB] RETURNS [Spectrum];
Returns a spectrum which will convert under SpectrumToRGB to the same RGB as provided in the input. For more information, you might check out "How to Derive A Spectrum From An RGB Triplet" by Andrew Glassner in the July 1989 IEEE Computer Graphics & Applications.
Basic Operations on Two Spectra
Union: PUBLIC PROC [a, b: Spectrum] RETURNS [newa, newb: Spectrum];
Builds two new spectra from the input spectra. Both of the output spectra contain the same number of samples, at the same wavelengths. The wavelengths used are the union of the wavelengths in a and b. When an output value is needed at a wavelength not specified in the original, Sample is called to linearly interpolate a new value.
Conform: PUBLIC PROC [a, b: Spectrum] RETURNS [newa: Spectrum];
Builds a new spectrum newa from a. newa has entries at the wavelengths in b. Sample is used to find any values at wavelengths in b but not in a.
The following six procedures (Add, Sub, Lerp, Blend, Filter, and Damp) all construct an output spectrum c by first calling Union on the input spectra, and then operating on the result. Thus, the output spectrum contains a sample at every wavelength specified in either input spectrum.
Add: PUBLIC PROC [a, b: Spectrum] RETURNS [c: Spectrum];
c ← a+b
Sub: PUBLIC PROC [a, b: Spectrum] RETURNS [c: Spectrum];
c ← a-b
Lerp: PUBLIC PROC [a, b: Spectrum, alpha: REAL] RETURNS [c: Spectrum];
c ← lerp(a, b, alpha) (linear interpolation from a to b; @ alpha=0, c=a; @ alpha=1, c=b)
Blend: PUBLIC PROC [a, b: Spectrum, aScl, bScl: REAL] RETURNS [c: Spectrum];
c ← (a * aScl) + (b * bScl)
Filter: PUBLIC PROC [a, b: Spectrum] RETURNS [c: Spectrum];
c ← a*b
Damp: PUBLIC PROC [a, b: Spectrum] RETURNS [c: Spectrum];
c ← a/b (when an entry of b=0, the corresponding entry of c𡤀)
END.