<<-- BuildTRCImpl.mesa>> <<-- Mik Lamming - December 11, 1984 1:22:03 pm PST>> DIRECTORY Icons, Convert, Hist, Terminal, Buttons, FS, IO, RealFns, ColorMap, MessageWindow, UserProfile, Commander, Containers, Real, Rope, Rules, TRCViewer, ViewerTools, UPOps, ViewerClasses ; BuildTRCImpl: CEDAR MONITOR IMPORTS Icons, Real, Convert, Terminal, Buttons, Hist, FS, IO, ColorMap, RealFns, MessageWindow, UserProfile, Commander, Containers, Rules, TRCViewer, UPOps, Rope, ViewerTools SHARES Terminal = BEGIN LogFlag: Rope.ROPE _ "Log"; LinFlag: Rope.ROPE _ "Linear"; vt: Terminal.Virtual; DisplayState: TYPE = {bpp8, bpp24, off}; displayState: DisplayState _ off; icon: Icons.IconFlavor _ Icons.NewIconFromFile["BuildTRC.icons", 0]; State: TYPE = REF StateRec; StateRec: TYPE = RECORD [ container: ViewerClasses.Viewer, linBut, logBut, negBut, shiftBut, rotateBut, initBut, simBut: Buttons.Button, setHistWhite, setHistBlack, setGamma, setInputModeBut, setOutputModeBut: Buttons.Button, showHistBut, calcHistBut, equaliseBut, histSourceBut, wdBut: Buttons.Button, trcFileBut, saveTRCBut, getTRCBut: Buttons.Button, inputScaleTypeIn, outputScaleTypeIn, histSourceTypeIn, wdTypeIn, trcFileTypeIn, whiteTypeIn, blackTypeIn, gammaTypeIn: ViewerClasses.Viewer, trcViewer: ViewerClasses.Viewer, wd: Rope.ROPE, maxInputDens, maxOutputDens: REAL _ 99.0, inputMode, outputMode: TRCViewer.FeedBackMode _ density, connectMode: TRCViewer.ConnectMode _ linear, histoOn: BOOLEAN _ FALSE, addVertexOnShiftOrRotate: BOOLEAN _ FALSE, histo: Hist.Histogram _ NIL, simRed, simGrn, simBlu: BOOLEAN _ TRUE, gamma: REAL _ 2.2 ]; Simulate: ENTRY Buttons.ButtonProc -- [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] -- = { state: State _ NARROW[clientData]; IF displayState=off THEN { vt _ Terminal.Current[]; IF NOT vt.hasColorDisplay THEN displayState _ off ELSE IF vt.colorMode.full THEN displayState_bpp24 ELSE displayState_bpp8; UpdateColorMap[state]; Buttons.SetDisplayStyle[state.simBut, $WhiteOnBlack]; } ELSE { Buttons.SetDisplayStyle[state.simBut, $BlackOnWhite]; displayState _ off; } }; UpdateColorMap: PROC [state:State] ~ { SetMap: PROC [entry:NAT, value:NAT] ~ { reflectance:REAL; IF state.outputMode=density THEN reflectance _ RealFns.Power[10, - ((255 - value) / 255.0) * maxDensityOut] ELSE reflectance _ minROut + rangeR * value / 255.0; SELECT displayState FROM bpp8 => { ColorMap.SetRGBColor[entry, reflectance, reflectance, reflectance]; }; bpp24 => { SELECT value FROM IN [1..254] => { reflectance _ RealFns.Power[reflectance, oneOverGamma]; }; ENDCASE; value _ MAX[MIN[255, Real.RoundC[reflectance*255]], 0]; IF state.simRed THEN Terminal.SetRedMap[vt, entry, value]; IF state.simGrn THEN Terminal.SetGreenMap[vt, entry, value]; IF state.simBlu THEN Terminal.SetBlueMap[vt, entry, value]; }; ENDCASE; }; minROut, rangeR, maxDensityOut: REAL; err: BOOLEAN; oneOverGamma: REAL ; IF displayState=off THEN RETURN []; [state.gamma, err] _ GetRealFromViewer[state.gammaTypeIn]; IF err OR state.gamma <= 0 THEN { MessageWindow.Append["Gamma should be > 0", TRUE]; MessageWindow.Blink[]; RETURN []; }; IF displayState=bpp8 THEN ColorMap.SetGamma[state.gamma] ELSE oneOverGamma _ 1 / state.gamma; [maxDensityOut, err] _ GetDensityFromScaleViewer[state.outputScaleTypeIn, state.outputMode]; IF ~err THEN { trc: Hist.TRCVec _ TRCViewer.Get[state.trcViewer]; minROut _ TRCViewer.DensToRef[maxDensityOut]; rangeR _ 1 - minROut; FOR i: NAT IN [0..255] DO SetMap[i, trc[i].out] ENDLOOP; }; }; FixUpMap: TRCViewer.ChangeProc ~ { UpdateColorMap[NARROW[clientData]] }; StartNewInstance: Commander.CommandProc ~ { AddButton: PROC [label: Rope.ROPE, proc: Buttons.ButtonProc, left, top: NAT, width:NAT _ 0, clientData: REF ANY _ state] RETURNS [b: Buttons.Button, right, bottom: NAT] ~ { b _ Buttons.Create[ info: [ parent: state.container, name: label, wx: left, wy: top, ww:width ], proc: proc, clientData: clientData ]; RETURN [b, left+b.ww, top+b.wh] }; AddTypeIn: PROC [left, top, width, height: NAT, init:Rope.ROPE _ NIL] RETURNS [t: ViewerClasses.Viewer, right, bottom: NAT] ~ { t _ ViewerTools.MakeNewTextViewer[ info:[ wx:left, wy:top, ww:width, wh:height, parent: state.container, border: FALSE, scrollable: FALSE, data: init]]; RETURN [t, left+t.ww, top+t.wh] }; pStream: IO.STREAM _ IO.RIS[cmd.commandLine]; empty:BOOLEAN _ FALSE; p1: Rope.ROPE; leftMargin: NAT ~ 2; row0: NAT ~ 2; colSep: NAT ~ 2; groupSep: NAT ~ 8; rowSep: NAT ~ 4; scaleTypeInWidth: NAT ~ 85; fileTypeInWidth: NAT ~ 160; wdTypeInWidth: NAT ~ 260; cardWidth: NAT ~ 40; fileNameButTab, butHt, nextX, nextY, tempY : NAT ; state: State _ NEW[StateRec]; p1 _ IO.GetTokenRope[pStream, IO.IDProc ! IO.EndOfStream => { empty _ TRUE; CONTINUE; }].token; state.simRed _ state.simGrn _ state.simBlu _ TRUE; IF NOT empty AND Rope.Length[p1]>0 THEN { -- parameter present SELECT TRUE FROM Rope.Equal[p1, "-B", FALSE] => state.simRed _ state.simGrn _ FALSE; Rope.Equal[p1, "-R", FALSE] => state.simBlu _ state.simGrn _ FALSE; Rope.Equal[p1, "-G", FALSE] => state.simRed _ state.simBlu _ FALSE; ENDCASE }; ScanProfile[state]; state.container _ Containers.Create[info: [name:Rope.Cat["TRC Builder", p1], scrollable:FALSE, icon:icon]]; state.container.class.paintRectangles _ FALSE; -- disable viewers bug state.container.class.bltContents _ none; nextX _ leftMargin; nextY _ row0; [state.linBut, nextX, tempY] _ AddButton["Linear", SetLinearMode, nextX, nextY]; Buttons.SetDisplayStyle[state.linBut, $WhiteOnBlack]; butHt _ tempY - row0; [state.logBut, nextX, ] _ AddButton["Log", SetLogMode, nextX+colSep, nextY]; [state.negBut, nextX, ] _ AddButton["Negative", Negate, nextX+colSep, nextY]; [state.shiftBut, nextX, ] _ AddButton["Shift", Shift, nextX+colSep, nextY]; [state.rotateBut, nextX, ] _ AddButton["Rotate", Rotate, nextX+colSep, nextY]; [state.initBut, nextX, ] _ AddButton["Init", InitTRC, nextX+colSep, nextY]; [] _ Rules.Create[info:[wx:nextX+groupSep/2-1, wy:0, ww:2, wh:row0+butHt+1, parent:state.container]]; [state.simBut, nextX, ] _ AddButton["Simulate", Simulate, nextX+groupSep, nextY]; [] _ Rules.Create[info:[wx:nextX+groupSep/2-1, wy:0, ww:2, wh:row0+2*(butHt+3), parent:state.container]]; fileNameButTab _ nextX+groupSep; [state.wdBut, nextX, ] _ AddButton["WD", SelectWD, fileNameButTab, nextY]; [state.wdTypeIn, nextX, nextY] _ AddTypeIn[fileNameButTab+40, nextY, wdTypeInWidth, butHt, state.wd]; FS.SetDefaultWDir[state.wd ! FS.Error => { MessageWindow.Append[IO.PutFR["Bad WD: %g is not a local directory", IO.rope[state.wd]], TRUE]; MessageWindow.Blink[]; CONTINUE}]; [] _ Rules.Create[info:[wx:0, wy:nextY+1, ww:1000, wh:2, parent:state.container]]; nextY _ nextY + rowSep; [state.setInputModeBut, nextX, ] _ AddButton["MaxDIn", SelectInScale, leftMargin, nextY]; [state.inputScaleTypeIn, nextX, ] _ AddTypeIn[nextX+colSep, nextY, scaleTypeInWidth, butHt, IO.PutFR["%g", IO.real[state.maxOutputDens]]]; [state.setOutputModeBut, nextX, ] _ AddButton["MaxDOut", SelectOutScale, nextX+colSep, nextY]; [state.outputScaleTypeIn, nextX, tempY] _ AddTypeIn[nextX+colSep, nextY, scaleTypeInWidth, butHt, IO.PutFR["%g", IO.real[state.maxInputDens]]]; [] _ Rules.Create[info:[wx:nextX+groupSep/2-1, wy:tempY+1, ww:1000, wh:2, parent:state.container]]; [state.trcFileBut, nextX, ] _ AddButton["TRC", SelectTRC, fileNameButTab, nextY]; [state.trcFileTypeIn, nextX, ] _ AddTypeIn[fileNameButTab+40, nextY, fileTypeInWidth, butHt]; [state.saveTRCBut, nextX, ] _ AddButton["Save", SaveTRC, nextX+colSep, nextY]; [state.getTRCBut, nextX, nextY] _ AddButton["Restore", ReadTRC, nextX+colSep, nextY]; [] _ Rules.Create[info:[wx:0, wy:nextY+1, ww:1000, wh:2, parent:state.container]]; nextY _ nextY + rowSep; [] _ Rules.Create[info:[wx:nextX+groupSep/2-1, wy:tempY+1, ww:2, wh:-2*(butHt+rowSep), parent:state.container]]; [state.setGamma, nextX, ] _ AddButton["Gamma", SelGamma, leftMargin, nextY]; [state.gammaTypeIn, nextX, tempY] _ AddTypeIn[nextX+colSep, nextY, scaleTypeInWidth, butHt, IO.PutFR["%g", IO.real[state.gamma]]]; [] _ Rules.Create[info:[wx:nextX+1, wy:tempY+3, ww:2, wh:-(butHt+5), parent:state.container]]; [state.setHistBlack, nextX, ] _ AddButton["Black", SelBlack, nextX+6, nextY]; [state.blackTypeIn, nextX, ] _ AddTypeIn[nextX+colSep, nextY, cardWidth, butHt, "0"]; [state.setHistWhite, nextX, ] _ AddButton["White", SelWhite, nextX, nextY]; [state.whiteTypeIn, nextX, ] _ AddTypeIn[nextX+colSep, nextY, cardWidth, butHt, "255"]; [state.histSourceBut, nextX, ] _ AddButton["Hist", SelectHist, fileNameButTab, nextY]; [state.histSourceTypeIn, nextX, ] _ AddTypeIn[fileNameButTab+40, nextY, fileTypeInWidth, butHt]; [state.showHistBut, nextX, ] _ AddButton["Off", ToggleHisto, nextX+colSep, nextY]; [state.calcHistBut, nextX, ] _ AddButton["Calc", CalcHisto, nextX+colSep, nextY]; [state.equaliseBut, nextX, nextY] _ AddButton["Eq", Equalise, nextX+colSep, nextY]; [] _ Rules.Create[info:[wx:0, wy:nextY+1, ww:1000, wh:2, parent:state.container]]; state.trcViewer _ ViewerOps.CreateViewer[ flavor: $TRCViewer, info: [ parent: state.container, wx: leftMargin, wy: nextY+rowSep, ww:100, wh:100]]; Containers.ChildYBound[state.container, state.trcViewer]; Containers.ChildXBound[state.container, state.trcViewer]; TRCViewer.SetMaxDensityIn[state.trcViewer, state.maxInputDens]; TRCViewer.SetMaxDensityOut[state.trcViewer, state.maxOutputDens]; TRCViewer.RegisterChangeProc[state.trcViewer, FixUpMap, state]; }; ScanProfile: PROC [state:State] ~ { tempRope: Rope.ROPE; state.wd _ UserProfile.Token["BuildTRC.WD", NIL]; IF state.wd=NIL THEN state.wd _ FS.GetDefaultWDir[]; state.maxInputDens _ Convert.RealFromRope[ tempRope _ UserProfile.Token[ "BuildTRC.MaxInputDensity", "3.0"] ! Convert.Error => { MessageWindow.Append[IO.PutFR["Bad user profile entry for BuildTRC.MaxInputDensity: %g is not a valid real number", IO.rope[tempRope]], TRUE]; MessageWindow.Blink[]; state.maxInputDens _ 88.0; CONTINUE; }]; state.maxOutputDens _ Convert.RealFromRope[ tempRope _ UserProfile.Token[ "BuildTRC.MaxOutputDensity", "3.0"] ! Convert.Error => { MessageWindow.Append[IO.PutFR["Bad user profile entry for BuildTRC.MaxOutputDensity: %g is not a valid real number", IO.rope[tempRope]], TRUE]; MessageWindow.Blink[]; state.maxOutputDens _ 88.0; CONTINUE; }]; state.gamma _ Convert.RealFromRope[ tempRope _ UserProfile.Token[ "BuildTRC.Gamma", "2.2"] ! Convert.Error => { MessageWindow.Append[IO.PutFR["Bad user profile entry for BuildTRC.Gamma: %g is not a valid real number", IO.rope[tempRope]], TRUE]; MessageWindow.Blink[]; state.gamma _ 2.2; CONTINUE; }]; }; GetDensityFromScaleViewer: PROC [ v: ViewerClasses.Viewer, mode: TRCViewer.FeedBackMode] RETURNS [d:REAL, err:BOOLEAN _ FALSE] ~ { r: REAL; [r, err] _ GetRealFromViewer[v]; IF err THEN RETURN; IF mode=density THEN { IF r<0 THEN { MessageWindow.Append["Scale value should be positive", TRUE]; MessageWindow.Blink[]; err _ TRUE; } ELSE { d _ r; }; } ELSE IF r<0 OR r>1 THEN { MessageWindow.Append["Scale value should be [0..1]", TRUE]; MessageWindow.Blink[]; err _ TRUE; } ELSE { d _ TRCViewer.RefToDens[r]; }; }; GetRealFromViewer: PROC [v: ViewerClasses.Viewer] RETURNS [r:REAL, err:BOOLEAN _ FALSE] ~ { rope: Rope.ROPE _ ViewerTools.GetContents[v]; in:IO.STREAM _ IO.RIS[rope]; r _ IO.GetReal[in ! IO.Error => { MessageWindow.Append["Invalid format in real number specification", TRUE]; MessageWindow.Blink[]; err _ TRUE; CONTINUE }; IO.EndOfStream => { MessageWindow.Append["Parameter absent", TRUE]; MessageWindow.Blink[]; err _ TRUE; CONTINUE }]; }; GetCardFromViewer: PROC [v: ViewerClasses.Viewer] RETURNS [r:NAT, err:BOOLEAN _ FALSE] ~ { rope: Rope.ROPE _ ViewerTools.GetContents[v]; in:IO.STREAM _ IO.RIS[rope]; r _ IO.GetCard[in ! IO.Error => { MessageWindow.Append["Invalid format in number specification", TRUE]; MessageWindow.Blink[]; err _ TRUE; CONTINUE }; IO.EndOfStream => { MessageWindow.Append["Parameter absent", TRUE]; MessageWindow.Blink[]; err _ TRUE; CONTINUE }]; }; ToggleHisto: ENTRY Buttons.ButtonProc -- [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] -- = { state: State _ NARROW[clientData]; IF state.histo=NIL THEN { MessageWindow.Append["No histogram has been calculated yet", TRUE]; MessageWindow.Blink[]; Buttons.SetDisplayStyle[state.histSourceBut, $BlackOnWhite]; RETURN []; }; state.histoOn _ ~state.histoOn; Buttons.SetDisplayStyle[state.histSourceBut, $WhiteOnBlack]; IF state.histoOn THEN { Buttons.ReLabel[state.showHistBut, "On"]; TRCViewer.SetHistogram[state.trcViewer, state.histo]; } ELSE { Buttons.ReLabel[state.showHistBut, "Off"]; TRCViewer.SetHistogram[state.trcViewer, NIL]; }; }; ReadTRC: ENTRY Buttons.ButtonProc -- [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] -- = { SetOutput: TRCViewer.EnumerateProc ~ { xIndex: NAT _ Real.RoundC[x]; IF ~trc[xIndex].pinned THEN trc[xIndex].out _ Real.RoundC[y]; }; state: State _ NARROW[clientData]; trc: Hist.TRCVec; bomb: BOOLEAN _ FALSE; pinned: ARRAY [0..255] OF BOOLEAN _ ALL[FALSE]; fileList: LIST OF Rope.ROPE; dotIndex: INTEGER; in:IO.STREAM; modeRope: Rope.ROPE; prev: NAT _ 0; fileName: Rope.ROPE _ ViewerTools.GetContents[state.trcFileTypeIn]; IF fileName=NIL OR Rope.Length[fileName]=0 THEN { MessageWindow.Append["Enter a TRC filename in TRC field please", TRUE]; MessageWindow.Blink[]; RETURN [] }; dotIndex _ Rope.Find[fileName, ".", 0, FALSE]; IF dotIndex<0 THEN fileList _ UPOps.Expand["%g.%k|TRCExtensions|trc|", IO.rope[fileName]] ELSE fileList _ LIST[fileName]; IF ~SetWDir[state] THEN RETURN []; DO { success:BOOLEAN _ TRUE; IF fileList = NIL THEN { MessageWindow.Append["Couldn't find specified TRC input file", TRUE]; MessageWindow.Blink[]; RETURN []; }; in _ FS.StreamOpen[fileName: fileList.first ! FS.Error => { success _ FALSE; CONTINUE }]; IF success THEN EXIT; fileList _ fileList.rest }; ENDLOOP; <<-- read the file in>> trc _ NEW[Hist.TRCVecRec]; modeRope _ in.GetID[ ! IO.Error => { MessageWindow.Append["TRC format error - Couldn't find interpolation mode flag", TRUE]; MessageWindow.Blink[]; bomb _ TRUE; CONTINUE; } ]; IF bomb THEN RETURN []; SELECT TRUE FROM Rope.Equal[modeRope, LogFlag, FALSE] => { state.connectMode _ log; Buttons.SetDisplayStyle[state.linBut, $BlackOnWhite]; Buttons.SetDisplayStyle[state.logBut, $WhiteOnBlack]; }; Rope.Equal[modeRope, LinFlag, FALSE] => { state.connectMode _ linear; Buttons.SetDisplayStyle[state.linBut, $WhiteOnBlack]; Buttons.SetDisplayStyle[state.logBut, $BlackOnWhite]; }; ENDCASE => { MessageWindow.Append["TRC format error - Invalid interpolation mode flag", TRUE]; MessageWindow.Blink[]; RETURN []; }; FOR i:CARDINAL IN [0..255] DO c: CHAR; index:CARDINAL; prev _ index; index _ IO.GetCard[in ! IO.EndOfStream => { bomb _ TRUE; CONTINUE; }; IO.Error => { bomb _ TRUE; MessageWindow.Append[IO.PutFR["TRC format error following vertex %g", IO.card[prev]], TRUE]; MessageWindow.Blink[]; CONTINUE; }]; prev _ index; IF bomb THEN EXIT; trc[index].out _ IO.GetCard[in ! IO.EndOfStream => { bomb _ TRUE; MessageWindow.Append["TRC format error - Unexpected EOF", TRUE]; MessageWindow.Blink[]; CONTINUE; }; IO.Error => { bomb _ TRUE; MessageWindow.Append[IO.PutFR["TRC format error at vertex %g", IO.card[index]], TRUE]; MessageWindow.Blink[]; CONTINUE; }]; IF bomb THEN EXIT; trc[index].pinned _ TRUE; c _ in.GetChar[ ! IO.EndOfStream => {bomb _ TRUE; CONTINUE}]; IF bomb THEN EXIT; WHILE (c # IO.CR) DO SELECT c FROM '* => { pinned[index] _ TRUE; EXIT; }; IO.BS, IO.TAB, IO.LF, IO.FF, IO.NUL, IO.SP, IO.DEL, IO.ESC, IO.ControlX, IO.BEL, IO.ControlA => NULL; ENDCASE => { bomb _ TRUE; MessageWindow.Append[IO.PutFR["TRC format error following vertex %g '*' or CR expected", IO.card[prev]], TRUE]; MessageWindow.Blink[]; EXIT; }; c _ in.GetChar[ ! IO.EndOfStream => {bomb _ TRUE; CONTINUE}]; IF bomb THEN EXIT; ENDLOOP; IF bomb THEN EXIT; ENDLOOP; in.Close[]; TRCViewer.Set[state.trcViewer, trc, FALSE]; TRCViewer.Enumerate[state.trcViewer, SetOutput, 0, 255]; FOR i: NAT IN [0..255] DO trc[i].pinned _ pinned[i] ENDLOOP; <> TRCViewer.SetTitle[state.trcViewer, fileList.first]; }; SaveTRC: ENTRY Buttons.ButtonProc -- [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] -- = { PrintOutput: TRCViewer.EnumerateProc ~ { xIndex: NAT _ Real.RoundC[x]; out.PutF["%g %g", IO.card[xIndex], IO.card[trc[xIndex].out]]; IF trc[xIndex].pinned THEN out.PutChar['*]; out.PutChar['\n]; }; state: State _ NARROW[clientData]; trc: Hist.TRCVec; bomb: BOOLEAN _ FALSE; fileList: LIST OF Rope.ROPE; dotIndex: INTEGER; out: IO.STREAM; fileName: Rope.ROPE _ ViewerTools.GetContents[state.trcFileTypeIn]; IF fileName=NIL OR Rope.Length[fileName]=0 THEN { MessageWindow.Append["Enter a TRC filename in TRC field please", TRUE]; MessageWindow.Blink[]; RETURN [] }; dotIndex _ Rope.Find[fileName, ".", 0, FALSE]; IF dotIndex<0 THEN fileList _ UPOps.Expand["%g.%k|TRCExtensions|trc|", IO.rope[fileName]] ELSE fileList _ LIST[fileName]; IF ~SetWDir[state] THEN RETURN []; out _ FS.StreamOpen[fileName: fileList.first, accessOptions:create ! FS.Error => { bomb _ TRUE; CONTINUE }]; IF bomb THEN { MessageWindow.Append["Could not create specified TRC file", TRUE]; MessageWindow.Blink[]; RETURN [] }; out.PutF["-- %g \n", IO.rope[fileList.first]]; SELECT state.connectMode FROM log => out.PutF["Log\n"]; linear => out.PutF["Linear\n"]; ENDCASE => ERROR; trc _ TRCViewer.Get[state.trcViewer]; TRCViewer.Enumerate[state.trcViewer, PrintOutput, 0, 255]; out.Close[]; }; SetWDir: PROC [state: State] RETURNS [ok:BOOLEAN _ TRUE] ~ { dirName: Rope.ROPE _ ViewerTools.GetContents[state.wdTypeIn]; IF dirName=NIL OR Rope.Length[dirName]=0 THEN { dirName _ FS.GetDefaultWDir[]; MessageWindow.Append[IO.PutFR["Assuming working directory %g", IO.rope[dirName]], TRUE]; MessageWindow.Blink[]; RETURN [] }; FS.SetDefaultWDir[dirName ! FS.Error => { MessageWindow.Append[IO.PutFR["Funny working directory name: %g", IO.rope[dirName]], TRUE]; MessageWindow.Blink[]; ok _ FALSE; CONTINUE; }]; }; CalcHisto: ENTRY Buttons.ButtonProc -- [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] -- = { state: State _ NARROW[clientData]; fileList: LIST OF Rope.ROPE; dotIndex: INTEGER; min, max:NAT; err:BOOLEAN _ FALSE; fileName: Rope.ROPE _ ViewerTools.GetContents[state.histSourceTypeIn]; IF fileName=NIL OR Rope.Length[fileName]=0 THEN { MessageWindow.Append["Enter an AIS filename in Hist field please", TRUE]; MessageWindow.Blink[]; RETURN [] }; dotIndex _ Rope.Find[fileName, ".", 0, FALSE]; IF dotIndex<0 THEN fileList _ UPOps.Expand["%g.%k|AISExtensions|AIS|", IO.rope[fileName]] ELSE fileList _ LIST[fileName]; IF ~SetWDir[state] THEN RETURN []; [min, err] _ GetCardFromViewer[state.blackTypeIn]; IF err OR min NOT IN [0..255] THEN { MessageWindow.Append["Invalid value for histogram black value [0..255]", TRUE]; MessageWindow.Blink[]; RETURN [] }; [max, err] _ GetCardFromViewer[state.whiteTypeIn]; IF err OR max NOT IN [0..255] THEN { MessageWindow.Append["Invalid value for histogram white value [0..255]", TRUE]; MessageWindow.Blink[]; RETURN [] }; DO { success:BOOLEAN _ TRUE; IF fileList = NIL THEN { MessageWindow.Append["Couldn't find specified input file", TRUE]; MessageWindow.Blink[]; state.histo _ NIL; state.histoOn _ FALSE; Buttons.SetDisplayStyle[state.histSourceBut, $BlackOnWhite]; Buttons.ReLabel[state.showHistBut, "Off"]; TRCViewer.SetHistogram[state.trcViewer, NIL]; RETURN []; }; state.histo _ Hist.Calc[fileList.first, min, max ! FS.Error => { success _ FALSE; CONTINUE }]; IF success THEN EXIT; fileList _ fileList.rest }; ENDLOOP; Buttons.SetDisplayStyle[state.histSourceBut, $WhiteOnBlack]; state.histoOn _ TRUE; Buttons.ReLabel[state.showHistBut, "On"]; TRCViewer.SetHistogram[state.trcViewer, state.histo]; }; Equalise: ENTRY Buttons.ButtonProc -- [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] -- = { state: State _ NARROW[clientData]; trc: Hist.TRCVec; IF state.histo=NIL THEN { MessageWindow.Append["No histogram has been calculated yet", TRUE]; MessageWindow.Blink[]; RETURN [] }; trc _ Hist.Equalize[state.histo]; trc[0].pinned _ trc[255].pinned _ TRUE; TRCViewer.Set[state.trcViewer, trc]; }; SelGamma: ENTRY Buttons.ButtonProc -- [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] -- = { state: State _ NARROW[clientData]; ViewerTools.SetSelection[NARROW[clientData, State].gammaTypeIn]; UpdateColorMap[state]; }; SelBlack: ENTRY Buttons.ButtonProc -- [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] -- = { state: State _ NARROW[clientData]; ViewerTools.SetSelection[NARROW[clientData, State].blackTypeIn]; }; SelWhite: ENTRY Buttons.ButtonProc -- [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] -- = { state: State _ NARROW[clientData]; ViewerTools.SetSelection[NARROW[clientData, State].whiteTypeIn]; }; Shift: ENTRY Buttons.ButtonProc = { state: State _ NARROW[clientData]; newVertices: Hist.TRCVec _ NEW[Hist.TRCVecRec]; oldVertices: Hist.TRCVec _ TRCViewer.Get[state.trcViewer]; delta: NAT _ 1; dir: INT _ 1; IF shift THEN delta _ delta * 16; IF control THEN delta _ delta * 4; IF mouseButton=blue THEN dir _ -1; FOR i: NAT IN [0..Hist.MaxPixel] DO p:INT _ i+(delta*dir); SELECT TRUE FROM p<0 => { newVertices[i].out _ oldVertices[0].out}; p>255 => { newVertices[i].out _ oldVertices[255].out}; ENDCASE => newVertices[i] _ oldVertices[p]; ENDLOOP; IF state.addVertexOnShiftOrRotate THEN newVertices[0].pinned _ newVertices[255].pinned _ TRUE; TRCViewer.Set[state.trcViewer, newVertices]; }; Rotate: ENTRY Buttons.ButtonProc = { state: State _ NARROW[clientData]; newVertices: Hist.TRCVec _ NEW[Hist.TRCVecRec]; oldVertices: Hist.TRCVec _ TRCViewer.Get[state.trcViewer]; delta: NAT _ 1; dir: INT _ 1; IF shift THEN delta _ delta * 16; IF control THEN delta _ delta * 4; IF mouseButton=blue THEN dir _ -1; FOR i: NAT IN [0..Hist.MaxPixel] DO p:INT _ i+(delta*dir); newVertices[i] _ oldVertices[(256+p) MOD 256]; ENDLOOP; IF state.addVertexOnShiftOrRotate THEN newVertices[0].pinned _ newVertices[255].pinned _ TRUE; TRCViewer.Set[state.trcViewer, newVertices]; }; SelectWD: ENTRY Buttons.ButtonProc -- [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] -- = { ViewerTools.SetSelection[NARROW[clientData, State].wdTypeIn]; }; SelectTRC: ENTRY Buttons.ButtonProc -- [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] -- = { ViewerTools.SetSelection[NARROW[clientData, State].trcFileTypeIn]; }; SelectHist: ENTRY Buttons.ButtonProc -- [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] -- = { ViewerTools.SetSelection[NARROW[clientData, State].histSourceTypeIn]; }; SelectInScale: ENTRY Buttons.ButtonProc -- [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] -- = { state: State _ NARROW[clientData]; d: REAL; err: BOOLEAN; [d, err] _ GetDensityFromScaleViewer[state.inputScaleTypeIn, state.inputMode]; IF ~err THEN { state.maxInputDens _ d; TRCViewer.SetMaxDensityIn[state.trcViewer, d]; }; IF mouseButton=red OR mouseButton=blue THEN { SELECT state.inputMode FROM density => { state.inputMode _ reflectance; Buttons.ReLabel[state.setInputModeBut, "MinRIn"]; ViewerTools.SetContents[state.inputScaleTypeIn, IO.PutFR["%g", IO.real[TRCViewer.DensToRef[state.maxInputDens]]]]; }; ENDCASE => { state.inputMode _ density; Buttons.ReLabel[state.setInputModeBut, "MaxDIn"]; ViewerTools.SetContents[state.inputScaleTypeIn, IO.PutFR["%g", IO.real[state.maxInputDens]]]; }; TRCViewer.SetFeedBackModes[state.trcViewer, state.inputMode, state.outputMode]; }; ViewerTools.SetSelection[state.inputScaleTypeIn]; }; SelectOutScale: ENTRY Buttons.ButtonProc -- [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] -- = { state: State _ NARROW[clientData]; d: REAL; err: BOOLEAN; [d, err] _ GetDensityFromScaleViewer[state.outputScaleTypeIn, state.outputMode]; IF ~err THEN { state.maxOutputDens _ d; TRCViewer.SetMaxDensityOut[state.trcViewer, d]; }; IF mouseButton=red OR mouseButton=blue THEN { SELECT state.outputMode FROM density => { state.outputMode _ reflectance; Buttons.ReLabel[state.setOutputModeBut, "MinROut"]; ViewerTools.SetContents[state.outputScaleTypeIn, IO.PutFR["%g", IO.real[TRCViewer.DensToRef[state.maxOutputDens]]]]; }; ENDCASE => { state.outputMode _ density; Buttons.ReLabel[state.setOutputModeBut, "MaxDOut"]; ViewerTools.SetContents[state.outputScaleTypeIn, IO.PutFR["%g", IO.real[state.maxOutputDens]]]; }; TRCViewer.SetFeedBackModes[state.trcViewer, state.inputMode, state.outputMode]; }; ViewerTools.SetSelection[state.outputScaleTypeIn]; TRCViewer.SetConnectMode[state.trcViewer, state.connectMode]; -- just a refresh really }; SetLinearMode: ENTRY Buttons.ButtonProc -- [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] -- = { state: State _ NARROW[clientData]; state.connectMode _ linear; Buttons.SetDisplayStyle[state.linBut, $WhiteOnBlack]; Buttons.SetDisplayStyle[state.logBut, $BlackOnWhite]; TRCViewer.SetConnectMode[state.trcViewer, state.connectMode]; }; SetLogMode: ENTRY Buttons.ButtonProc -- [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] -- = { state: State _ NARROW[clientData]; state.connectMode _ log; Buttons.SetDisplayStyle[state.linBut, $BlackOnWhite]; Buttons.SetDisplayStyle[state.logBut, $WhiteOnBlack]; TRCViewer.SetConnectMode[state.trcViewer, state.connectMode]; }; InitTRC: ENTRY Buttons.ButtonProc -- [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] -- = { SetOutput: TRCViewer.EnumerateProc ~ { trc[Real.RoundC[x]].out _ Real.RoundC[y]; }; state: State _ NARROW[clientData]; trc: Hist.TRCVec _ NEW[Hist.TRCVecRec]; trc[0].pinned _ trc[255].pinned _ TRUE; trc[0].out _ 0; trc[255].out _ 255; TRCViewer.Set[state.trcViewer, trc, FALSE]; TRCViewer.Enumerate[state.trcViewer, SetOutput, 0, 255]; TRCViewer.SetConnectMode[state.trcViewer, state.connectMode]; -- just a refresh really }; Negate: ENTRY Buttons.ButtonProc -- [parent: REF ANY, clientData: REF ANY _ NIL, mouseButton: Menus.MouseButton _ red, shift: BOOL _ FALSE, control: BOOL _ FALSE] -- = { state: State _ NARROW[clientData]; trc: Hist.TRCVec _ TRCViewer.Get[state.trcViewer]; FOR i: NAT IN [0..Hist.MaxPixel] DO trc[i].out _ 255 - trc[i].out; ENDLOOP; TRCViewer.Set[state.trcViewer, trc]; }; Register: PROC ~ { Commander.Register[key:"BuildTRC", proc:StartNewInstance]; }; Register[]; END.