<> <> <> <<>> 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; 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 ~ { <> 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[( 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 ~ { <> 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]]]; }; contrast: REAL _ settings[contrast]-0.5; dark: REAL _ settings[dark]-0.5; black: REAL _ settings[black]; white: REAL _ MAX[settings[white], black+0.01]; scale: REAL _ white-black; trc _ IF trc=NIL THEN NEW[TRC] ELSE old; 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[ q2: ScaleVec[vanMag*RealFns.Cos[ ], segments: 20, proc: PutInTRC ]; }; ByeBye: AdjustColorStd.ByeProc ~ {}; <> 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.