TRCShapes.mesa
Copyright © 1985, Xerox Corporation. All rights reserved.
Last edited by Eric Nickell, December 19, 1985 6:37:45 pm PST
DIRECTORY
AdjustColor USING [NewGamma],
AdjustColorStd USING [ByeProc, RegisterStdAdjuster, RequestControl, SetProc, Settings, TRC],
PixelGraphics USING [Hermite, InterpolateLines, InterpolatePoints, InterpolateSpline, Point],
Real USING [RoundLI],
RealFns USING [Cos, Sin, Tan]
;
TRCShapes: CEDAR PROGRAM
IMPORTS AdjustColor, AdjustColorStd, PixelGraphics, Real, RealFns
= BEGIN
OPEN PG: PixelGraphics;
Point: TYPE ~ PG.Point;
Settings: TYPE ~ AdjustColorStd.Settings;
TRC: TYPE ~ AdjustColorStd.TRC;
p: REAL ← 3.141592653589793238462643383279;
xSize, ySize: CARDINAL ~ 256;
xMax: CARDINAL ~ xSize-1;
yMax: CARDINAL ~ ySize-1;
Gamma: AdjustColorStd.SetProc ~ {
gamma: REAL ~ settings[contrast]*4.4;
trc ← IF trc=NIL THEN NEW[TRC] ELSE old;
FOR i: CARDINAL IN [0..256) DO
trc[i] ← i;
ENDLOOP;
AdjustColor.NewGamma[gamma];
};
Linear: AdjustColorStd.SetProc ~ {
Control a simple line via Contrast and Darkness. The line has a slope which is a fcn of contrast. The darkness affects only the offset. If only the darkness is changed, the slope of the line remains unchanged. If only the contrast is changed, then the line will rotate about a point on the line which also lies on the line between the upper-left and lower-right corners.
PutInTRC: PROC [p: Point] ~ {
trc[p.x] ← p.y;
};
XY2UV: PROC [x, y: REAL] RETURNS [p: Point] ~ INLINE {
p.x ← MAX[0, MIN[xMax, Real.RoundLI[x*xMax]]];
p.y ← MAX[0, MIN[yMax, Real.RoundLI[y*yMax]]];
};
m, b: REAL;  --m and b for the equation y=mx+b. Note that x=(y-b)/m.
points: LIST OF Point;
trc ← IF trc=NIL THEN NEW[TRC] ELSE old;
m ← RealFns.Tan[(p/2)*settings[contrast] ! ANY => {m� CONTINUE}];
b ← 1-(m+1)*settings[dark];
SELECT m+b FROM  --Does line hit right edge above or below square?
> 1.0 => points ← LIST[XY2UV[(1-b)/m, 1], XY2UV[1, 1]]; --Above
< 0.0 => points ← LIST[XY2UV[(-b)/m, 0], [1, 0]];  --Below
ENDCASE => points ← LIST[ XY2UV[1, m+b] ];
SELECT b FROM  --Does line hit left edge above or below square?
> 1.0 => {points ← CONS[XY2UV[0, 1], CONS[XY2UV[(1-b)/m, 1], points]]};
< 0.0 => {points ← CONS[[0, 0], CONS[XY2UV[(-b)/m, 0], points]]};
ENDCASE => points ← CONS[XY2UV[0, b], points];
PG.InterpolateLines[points, PutInTRC];
};
vanMag: REAL ← 2.5;
Spline: AdjustColorStd.SetProc ~ {
The basic idea is that we will use a single Hermite spline to model the TRC. The two control points on the ends (P1 and P2) will be set at the lower-left and upper-right corners respectively. Q1 and Q2, the tangents at the control points, are set to respond in parallel to contrast, and oppositely to darkness.
PutInTRC: PROC [p: Point] ~ {
trc[p.x] ← p.y;
};
Squish: PROC [x, y: REAL] RETURNS [p: Point] ~ INLINE {
RETURN [XY2UV[x: x*scale+black, y: y]];
};
ScaleVec: PROC [dx, dy: REAL] RETURNS [p: Point] ~ INLINE {
RETURN [XY2UV[x: dx*scale, y: dy]];
};
XY2UV: PROC [x, y: REAL] RETURNS [p: Point] ~ INLINE {
p.x ← MAX[0, MIN[xMax, Real.RoundLI[x*xMax]]];
p.y ← MAX[0, MIN[yMax, Real.RoundLI[y*yMax]]];
};
a, b: REAL;   --Angles for Q1 and Q2
contrast: REAL ← settings[contrast]-0.5;
dark: REAL ← settings[dark]-0.5;
black: REAL ← settings[black];
white: REALMAX[settings[white], black+0.01];
scale: REAL ← white-black;
trc ← IF trc=NIL THEN NEW[TRC] ELSE old;
a ← -MAX[MIN[contrast+dark, 0.5], -0.5]*p/2+p/4;
b ← -MAX[MIN[contrast-dark, 0.5], -0.5]*p/2+p/4;
PG.InterpolatePoints[XY2UV[0,0], Squish[0,0], PutInTRC];
PG.InterpolatePoints[Squish[1,1], XY2UV[1,1], PutInTRC];
PG.InterpolateSpline[
m: PG.Hermite[
p1: Squish[0, 0],
p2: Squish[1, 1],
q1: ScaleVec[vanMag*RealFns.Cos[a], vanMag*RealFns.Sin[a]],
q2: ScaleVec[vanMag*RealFns.Cos[b], vanMag*RealFns.Sin[b]]
],
segments: 20,
proc: PutInTRC
];
};
ByeBye: AdjustColorStd.ByeProc ~ {};
Start-up
Init: PROC ~ TRUSTED {
AdjustColorStd.RegisterStdAdjuster[[
flavor: $Gamma,
setProc: Gamma,
byeProc: ByeBye
]];
AdjustColorStd.RegisterStdAdjuster[[
flavor: $Linear,
setProc: Linear,
byeProc: ByeBye
]];
AdjustColorStd.RegisterStdAdjuster[
adjuster: [
flavor: $Spline,
setProc: Spline,
byeProc: ByeBye
],
initialSettings: [dark: 0.5, contrast: 0.5, black: 0.0, white: 1.0]
];
[] ← AdjustColorStd.RequestControl[$Gamma];
};
Init[];
END.