~ {
OuterData: TYPE ~ Controls.OuterData;
Cmap: TYPE ~ ColorTrixMap.Cmap;
CmSave: Commander.CommandProc ~ {
arg: Rope.ROPE ← Args.GetRope[cmd];
IF arg = NIL THEN RETURN[$Failure, "Save requires a filename as argument"];
ColorTrixMap.Save[ColorTrixMap.Read[], arg];
};
CmLoad: Commander.CommandProc ~ {
arg: Rope.ROPE ← Args.GetRope[cmd];
IF arg = NIL THEN RETURN[$Failure, "Filename required as argument"];
IF NOT ColorTrixMap.Load[arg] THEN RETURN[$Failure, "Can't read file."];
};
CmMono: Commander.CommandProc ~ {ColorTrixMap.Mono[]};
CmGamma: Commander.CommandProc ~ {
arg: Args.Arg ← Args.ArgReal[cmd];
IF arg.ok
THEN ColorTrixMap.Gamma[arg.real]
ELSE [] ← Controls.OuterViewer[
name: "Gamma",
controls: LIST[Controls.NewControl[name: "gamma", type: horiz, min: 0.0, max: 5.0, init: 2.2, x: 60, y: 10, w: 200, h: 20, detents: LIST[[, 2.2]], proc: Gammaler]]];
};
Gammaler: Controls.ControlProc ~ {
IF control.mouse.state = up THEN ColorTrixMap.Gamma[control.val];
};
CmRamp: Commander.CommandProc ~ {
args: ARRAY[0..8) OF Args.Arg;
FOR i:
INT
IN [0..8)
DO
args[i] ← Args.ArgIntRange[cmd, i, 0, 255];
IF NOT args[i].ok THEN RETURN[$Failure, "bad arguments"];
ENDLOOP;
ColorTrixMap.Ramp[args[0].int, args[1].int, args[2].int, args[3].int, args[4].int, args[5].int, args[6].int, args[7].int];
};
CmPrint: Commander.CommandProc ~ {
cm: Cmap ← ColorTrixMap.Read[];
FOR i:
INT
IN [0..256)
DO
cmd.out.PutF["%3g:\t%3g\t%3g\t%3g\n", IO.int[i], IO.int[cm[0][i]], IO.int[cm[1][i]], IO.int[cm[2][i]]];
ENDLOOP;
};
CmOnly: Commander.CommandProc ~ {
a: Rope.ROPE ← Args.GetRope[cmd];
IF a = NIL THEN RETURN[$Failure, "Only requires an argument"];
SELECT
TRUE
FROM
a.Equal["red"] => ColorTrixMap.PrimaryOnly[red];
a.Equal["green"] => ColorTrixMap.PrimaryOnly[green];
a.Equal["blue"] => ColorTrixMap.PrimaryOnly[blue];
ENDCASE => RETURN[$Failure, "argument one of: red, green, blue."];
};
CmTents: Commander.CommandProc ~ {
a: Args.Arg ← Args.ArgInt[cmd];
IF a.ok THEN ColorTrixMap.Tents[a.int] ELSE RETURN[$Failure, "argument needed."];
};
CmSin: Commander.CommandProc ~ {
a: Args.Arg;
v: ARRAY[0..2] OF REAL;
IF Args.NArgs[cmd] < 1 THEN RETURN[$Failure, "argument(s) needed."];
FOR i:
NAT
IN[0..2]
DO
a ← Args.ArgReal[cmd, i];
IF NOT a.ok AND i = 0 THEN RETURN[$Failure, "bad argument."];
v[i] ← IF a.ok THEN a.real ELSE v[i-1];
ENDLOOP;
ColorTrixMap.Sin[v[0], v[1], v[2]];
};
CmGauss: Commander.CommandProc ~ {ColorTrixMap.Gauss[]};
CmColor: Commander.CommandProc ~ {
i, r, g, b: Args.Arg;
IF NOT (i ← Args.ArgIntRange[cmd, 0, 0, 255]).ok THEN RETURN[$Failure, "bad arguments"];
IF NOT (r ← Args.ArgIntRange[cmd, 1, 0, 255]).ok THEN RETURN[$Failure, "bad arguments"];
IF NOT (g ← Args.ArgIntRange[cmd, 2, 0, 255]).ok THEN RETURN[$Failure, "bad arguments"];
IF NOT (b ← Args.ArgIntRange[cmd, 3, 0, 255]).ok THEN RETURN[$Failure, "bad arguments"];
ColorTrixMap.WriteEntry[i.int, r.int, g.int, b.int];
};
Restore: Controls.ClickProc ~ {
ColorTrixMap.Write[NARROW[NARROW[clientData, OuterData].data]];
};
RestoreAndQuit: Controls.ClickProc ~ {
Controls.EndViewer[NARROW[parent, Controls.Viewer].parent];
Process.Pause[Process.MsecToTicks[100]];
ColorTrixMap.Write[NARROW[NARROW[clientData, OuterData].data]];
};
CmCycle: Commander.CommandProc ~ {
cmSave: Cmap ← ColorTrixMap.Read[];
cm: Cmap ← ColorTrixMap.Copy[cmSave];
outer: Controls.Viewer ← Controls.OuterViewer[
name: "Cycle",
entries: LIST[["Restore", Restore]],
controls: LIST[Controls.NewControl[type: horiz, report: FALSE, x: 60, y: 10, w: 200, h: 20, min: -25.0, max: 25.0, init: 0.0, detents: LIST[[, 0.0]]]],
data: cmSave];
TRUSTED {Process.Detach[FORK Cycler[NARROW[outer.data], cm]]};
};
Cycler:
PROC [data: Controls.OuterData, cm: Cmap] ~ {
CedarProcess.SetPriority[background];
WHILE
NOT data.destroyed
DO
abs: REAL ← ABS[data.val];
n: INT ← MAX[1, Real.RoundI[abs]];
IF data.val = 0.0 THEN {Process.Pause[Process.MsecToTicks[100]]; LOOP};
ColorTrixMap.Write[ColorTrixMap.Cycle[cm, IF data.val > 0 THEN n ELSE -n]];
IF abs > 0.01 THEN Process.Pause[Process.MsecToTicks[Real.Round[100.0/abs]]];
ENDLOOP;
};
CmNBits: Commander.CommandProc ~ {
a: Args.Arg ← Args.ArgInt[cmd];
IF NOT a.ok THEN RETURN[$Failure, "argument needed."];
ColorTrixMap.NBits[ColorTrixMap.Read[], a.int];
};
CmScale: Commander.CommandProc ~ {
a: Args.Arg ← Args.ArgReal[cmd];
IF NOT a.ok THEN RETURN[$Failure, "argument needed."];
ColorTrixMap.Scale[ColorTrixMap.Read[], a.real];
};
CmAdd: Commander.CommandProc ~ {
a: Args.Arg ← Args.ArgInt[cmd];
IF NOT a.ok THEN RETURN[$Failure, "argument needed."];
ColorTrixMap.Add[ColorTrixMap.Read[], a.int];
};
CmCompose: Commander.CommandProc ~ {
cm1, cm2: Cmap;
ok1: BOOL ← ColorTrixMap.Load[Args.GetRope[cmd, 0], cm1 ← ColorTrixMap.NewCmap[]];
ok2: BOOL ← ColorTrixMap.Load[Args.GetRope[cmd, 1], cm2 ← ColorTrixMap.NewCmap[]];
IF NOT ok1 OR NOT ok2 THEN RETURN[$Failure, "bad color map name(s)."];
ColorTrixMap.Compose[cm1, cm2];
};
CmInterp: Commander.CommandProc ~ {
cmLoad: Cmap ← ColorTrixMap.NewCmap[];
a: Args.Arg ← Args.ArgReal[cmd, 0];
IF
NOT a.ok
OR
NOT ColorTrixMap.Load[Args.GetRope[cmd, 1], cmLoad]
THEN RETURN[$Failure, "bad argument(s)."];
ColorTrixMap.Interp[a.real, cmLoad, ColorTrixMap.Read[]];
};
CmScramble: Commander.CommandProc ~ {ColorTrixMap.Scramble[ColorTrixMap.Read[]]};
CmRandom: Commander.CommandProc ~ {ColorTrixMap.Rand[]};
CmShift: Commander.CommandProc ~ {
arg: Args.Arg ← Args.ArgInt[cmd];
cmSave: Cmap ← ColorTrixMap.Read[];
IF arg.ok
THEN ColorTrixMap.Write[ColorTrixMap.Cycle[ColorTrixMap.Read[], arg.int]]
ELSE [] ← Controls.OuterViewer[
name: "Shift",
controls: LIST[Controls.NewControl[type: circ, report: FALSE, x: 60, y: 10, w: 80, h: 80, min: 0.0, max: 255.0, init: 0.0, detents: LIST[[, 0.0]], proc: Shifter, data: cmSave]]];
};
Shifter: Controls.ControlProc ~ {
cmSave: Cmap ← NARROW[control.data];
cm: Cmap ← ColorTrixMap.ObtainCmap[];
[] ← ColorTrixMap.Copy[cmSave, cm];
ColorTrixMap.Write[ColorTrixMap.Cycle[cm, Real.Round[control.val]]];
ColorTrixMap.ReleaseCmap[cm];
};
CmSpeckle: Commander.CommandProc ~ {
cmSave: Cmap ← ColorTrixMap.Read[];
outer: Controls.Viewer ← Controls.OuterViewer[
name: "Speckle",
entries:
LIST[
["Quit", Controls.Quit],
["Restore", Restore],
["Restore&Quit", RestoreAndQuit]],
controls: LIST[Controls.NewControl[type: horiz, report: FALSE, x: 60, y: 10, w: 200, h: 20, min: 1.0, max: 0.0, init: 0.5]],
data: cmSave];
TRUSTED {Process.Detach[FORK Speckler[NARROW[outer.data]]]};
};
Speckler:
PROC [data: Controls.OuterData] ~ {
RandInt: PROC RETURNS [INTEGER] ~ {RETURN[Random.ChooseInt[max: 255]]};
CedarProcess.SetPriority[background];
WHILE
NOT data.destroyed
DO
Process.Pause[Process.MsecToTicks[Real.Round[100.0*data.val]]];
ColorTrixMap.WriteEntry[RandInt[], RandInt[], RandInt[], RandInt[]];
ENDLOOP;
};
CmFlash: Commander.CommandProc ~ {
cmSave: Cmap ← ColorTrixMap.Read[];
outer: ViewerClasses.Viewer ← Controls.OuterViewer[
name: "Flash",
entries:
LIST[
["Quit", Controls.Quit],
["Restore", Restore],
["Restore&Quit", RestoreAndQuit]],
controls: LIST[Controls.NewControl[type: horiz, report: FALSE, x: 60, y: 10, w: 200, h: 20, min: 1.0, max: 0.0, init: 0.5]],
data: cmSave];
TRUSTED {Process.Detach[FORK Flasher[NARROW[outer.data]]]};
};
Flasher:
PROC [data: Controls.OuterData] ~ {
CedarProcess.SetPriority[background];
WHILE
NOT data.destroyed
DO
ColorTrixMap.Rand[];
Process.Pause[Process.MsecToTicks[Real.Round[1000.0*data.val]]];
ENDLOOP;
};
CmRipple: Commander.CommandProc ~ {
outer: ViewerClasses.Viewer ← Controls.OuterViewer[
name: "Ripple",
controls:
LIST[
Controls.NewControl[type:horiz,report:FALSE,x:60,y:10,w:200,h:20,min:0.0,max:1.0,init:0.5],
Controls.NewControl[type:horiz,report:FALSE,x:60,y:40,w:200,h:20,min:0.0,max:1.0,init:0.5],
Controls.NewControl[type:horiz,report:FALSE,x:60,y:70,w:200,h:20,min:0.0,max:1.0,init:0.5],
]];
TRUSTED {Process.Detach[FORK Rippler[NARROW[outer.data]]]};
};
Rippler:
PROC [data: Controls.OuterData] ~ {
vals: ARRAY [0..2] OF REAL ← ALL[0.0];
cs: ARRAY [0..2] OF Controls.ControlData;
incs: ARRAY [0..2] OF INTEGER ← ALL[1];
cs[0] ← data.controls.first;
cs[1] ← data.controls.rest.first;
cs[2] ← data.controls.rest.rest.first;
CedarProcess.SetPriority[background];
WHILE
NOT data.destroyed
DO
FOR i:
NAT
IN[0..2]
DO
IF vals[i] < 0.25 THEN incs[i] ← 1 ELSE IF vals[i] > 25.0 THEN incs[i] ← -1;
vals[i] ← vals[i]+incs[i]*cs[i].val;
ENDLOOP;
ColorTrixMap.Sin[vals[0], vals[1], vals[2]];
ENDLOOP;
};
rec: TYPE ~ RECORD [data: SEQUENCE num: NAT OF Cmap];
CmBlend: Commander.CommandProc ~ {
ncm: NAT ← 0;
outer: Controls.Viewer;
cm: REF rec ← NEW[rec[Args.NArgs[cmd]]];
FOR a:
NAT
IN[0..Args.NArgs[cmd])
DO
Process.CheckForAbort[];
IF ColorTrixMap.Load[Args.GetRope[cmd, a], cm.data[ncm] ← ColorTrixMap.NewCmap[]]
THEN ncm ← ncm+1
ELSE cmd.out.PutF["Can't read %g\n", IO.rope[Args.GetRope[cmd, a]]];
ENDLOOP;
IF ncm = 0 THEN RETURN;
outer ← Controls.OuterViewer[
name: "Color Map Blender",
controls: LIST[Controls.NewControl[type: horiz, report: FALSE, x: 60, y: 10, w: 200, h: 20, min: 0.01, max: 1.0, init: 0.1]]];
TRUSTED {Process.Detach[FORK Blender[NARROW[outer.data], cm, ncm]]};
};
Blender:
PROC [d: Controls.OuterData, cm:
REF rec, ncm:
NAT] ~ {
inc: INTEGER ← 1;
n0, n1: INTEGER ← 0;
WHILE
NOT d.destroyed
DO
Process.CheckForAbort[];
IF (n1 ← n0+inc) = -1 OR n1 = ncm THEN {inc ← -inc; n1 ← n0+inc};
FOR t:
REAL ← 0, t+d.val
WHILE t <= 1.0
DO
ColorTrixMap.Interp[t, cm.data[n0], cm.data[n1]];
ENDLOOP;
n0 ← n1;
ENDLOOP;
};
CmSnake: Commander.CommandProc ~ {
cmSave: Cmap ← ColorTrixMap.Read[];
outer: Controls.Viewer ← Controls.OuterViewer[
name: "Snake",
entries:
LIST[
["Quit", Controls.Quit],
["Restore", Restore],
["Restore&Quit", RestoreAndQuit]],
data: cmSave];
TRUSTED {Process.Detach[FORK Snaker[NARROW[outer.data]]]};
};
Snaker:
PROC [data: Controls.OuterData] ~ {
r, g, b: REAL;
cm: Cmap ← ColorTrixMap.Read[];
CedarProcess.SetPriority[background];
WHILE
NOT data.destroyed
DO
[r, g, b] ← GetSnake[];
[] ← ColorTrixMap.Cycle[cm, 1];
ColorTrixMap.SetEntry[cm, 1, Real.RoundI[255*r], Real.RoundI[255*g], Real.RoundI[255*b]];
ColorTrixMap.Write[cm];
ENDLOOP;
};
r, g, b: Section;
Section: TYPE ~ RECORD [count: INTEGER ← 0, p, d: REAL ← 0.0];
GetSnake:
PROC
RETURNS [
REAL,
REAL,
REAL] ~ {
RandomReal:
PROC
RETURNS [
REAL] ~ {
RETURN[(1.0/1024.0)*REAL[Random.ChooseInt[min: 1, max: 1024]]];
};
NewSection:
PROC [p:
REAL]
RETURNS[s: Section] ~ {
s.p ← p;
s.count ← Random.ChooseInt[min: 5, max: 30];
s.d ← (RandomReal[]-p)/REAL[s.count];
};
IF (r.count ← r.count-1) <= 0 THEN r ← NewSection[r.p];
IF (g.count ← g.count-1) <= 0 THEN g ← NewSection[g.p];
IF (b.count ← b.count-1) <= 0 THEN b ← NewSection[b.p];
r.p ← MAX[0.0, MIN[1.0, r.p+r.d]];
g.p ← MAX[0.0, MIN[1.0, g.p+g.d]];
b.p ← MAX[0.0, MIN[1.0, b.p+b.d]];
RETURN[r.p, g.p, b.p];
};
Commander.Register["CmSave", CmSave, "\nCmSave <filename: Cmap>."];
Commander.Register["CmLoad", CmLoad, "\nCmLoad <filename: Cmap>."];
Commander.Register["CmMono", CmMono, "\nPut linear ramp in color map."];
Commander.Register["CmGamma", CmGamma, "\nGamma correct the color map."];
Commander.Register["CmRamp", CmRamp, "\nCmRamp <i0 r0 g0 b0 i1 r1 g1 b1>"];
Commander.Register["CmPrint", CmPrint, "\nPrint the color map."];
Commander.Register["CmOnly", CmOnly, "\nCmOnly <red|green|blue>."];
Commander.Register["CmTents", CmTents, "\nCmTents <nTents: NAT>."];
Commander.Register["CmSin", CmSin, "\nCmSin <nCycles: REAL>."];
Commander.Register["CmGauss", CmGauss, "\nPut Gaussian curve in color map."];
Commander.Register["CmColor", CmColor, "\nCmColor <i r g b: INT IN [0..255]>."];
Commander.Register["CmCycle", CmCycle, "\nCycle the color map."];
Commander.Register["CmNBits", CmNBits, "\nCMNBits <nBits: NAT>."];
Commander.Register["CmScale", CmScale, "\nCmScale <s: REAL>."];
Commander.Register["CmAdd", CmAdd, "\nCmAdd <a: INTEGER>."];
Commander.Register["CmCompose", CmCompose, "\nCmCompose <c1 c2: Cmap>."];
Commander.Register["CmInterp", CmInterp, "\nCmInterp <t: REAL, cm: Cmap>."];
Commander.Register["CmScramble", CmScramble, "\nScramble the color map."];
Commander.Register["CmRandom", CmRandom, "\nRandomize the color map."];
Commander.Register["CmShift", CmShift, "\nRotate the color map."];
Commander.Register["CmSpeckle", CmSpeckle, "\nSpeckle the color map."];
Commander.Register["CmFlash", CmFlash, "\nRandomly change the color map."];
Commander.Register["CmBlend", CmBlend, "\nCmBlend <List of Cmaps> [-s #]."];
Commander.Register["CmRipple", CmRipple, "\nRipple through some sine waves."];
Commander.Register["CmSnake", CmSnake, "\nSnake through color space."];
}.