DIRECTORY AIS, AISCopy, Buttons, Commander, Containers, ExtraAIS, Icons, IO, FS, Imager, ImagerBackdoor USING [GetBounds, invert], ImagerColorOperator USING [GrayLinearColorModel], ImagerPixelArray USING [PixelArray, FromAIS], ImagerTransformation USING [Scale], Labels, PieViewers, Real, Rope, Rules, TIPUser, ViewerOps, ViewerClasses, ViewerIO, ViewerTools; AISCopyImpl: CEDAR PROGRAM IMPORTS AIS, Buttons, Commander, Containers, ExtraAIS, Icons, IO, FS, Imager, ImagerBackdoor, ImagerColorOperator, ImagerPixelArray, ImagerTransformation, PieViewers, Real, Rope, Rules, TIPUser, ViewerOps, ViewerIO, ViewerTools = BEGIN icon: Icons.IconFlavor _ Icons.NewIconFromFile[file: "AISCopy.icons", n: 1]; Go: Buttons.ButtonProc = { s: AISCopy.State _ NARROW[clientData]; fdIn,fdOut: AIS.FRef; rIn: AIS.Raster; rOut: AIS.Raster _ NEW[AIS.RasterPart]; wIn: ExtraAIS.VRef; wOut: AIS.WRef; inFn, outFn: Rope.ROPE; emptyValue: CARDINAL; s.parameterError _ FALSE; inFn _ GetFileName[s, s.inFnViewer]; outFn _ GetFileName[s, s.outFnViewer]; s.imageX _ GetNumberFromViewer[s, s.leftViewer, -1024, 2048, "Left"]; s.imageY _ GetNumberFromViewer[s, s.topViewer, -1024, 2048, "Top"]; s.imageH _ GetNumberFromViewer[s, s.heightViewer, 0, 2048, "Scans"]; s.imageW _ GetNumberFromViewer[s, s.widthViewer, 0, 2048, "Pixels"]; s.copyH _ GetNumberFromViewer[s, s.oScansViewer, 0, 2048, "Output Scans"]; s.copyW _ GetNumberFromViewer[s, s.oPixelsViewer, 0, 2048, "Output Pixels"]; emptyValue _ GetNumberFromViewer[s, s.emptyViewer, 0, LAST[INTEGER], "Empty Value"]; s.scaleX _ s.copyW / Real.Float[s.imageW]; s.scaleY _ s.copyH / Real.Float[s.imageH]; s.abort _ FALSE; IF s.parameterError THEN RETURN[]; TRUSTED { fdIn _ AIS.OpenFile[name: inFn ! AIS.Error => { IO.PutF[s.out, "\n%g does not exist", IO.rope[inFn]]; GOTO notThere; }]; IO.PutF[s.out, "\nOpening %g", IO.rope[inFn]]; rIn _ AIS.ReadRaster[fdIn]; rOut^ _ rIn^; rOut.scanCount _ s.copyH; rOut.scanLength _ s.copyW; IO.PutF[s.out, "\nCreating %g", IO.rope[outFn]]; fdOut _ AIS.CreateFile[name: outFn, raster: rOut]; wIn _ ExtraAIS.OpenWindow[fdIn, s.imageY, s.imageY+(s.imageH-1), s.imageX, s.imageX+(s.imageW-1), emptyValue]; wOut _ AIS.OpenWindow[fdOut]; IO.PutF[s.out, "\nProcessing %g", IO.rope[outFn]]; IF s.scaleY < 1.0 THEN ShrinkNoOfLines[s, wIn, wOut] ELSE ExpandNoOfLines[s, wIn, wOut]; ExtraAIS.CloseWindow[wIn]; AIS.CloseWindow[wOut]; AIS.CloseFile[fdIn]; AIS.CloseFile[fdOut]; IO.PutF[s.out, "\nDone"]; IF ~s.abort THEN { PieViewers.Set[s.pie, 0]; Init[outFn]; }; EXITS notThere => NULL; }; }; Abort: Buttons.ButtonProc = { s: AISCopy.State _ NARROW[clientData]; IO.PutF[s.out,"\nABORT"]; s.abort _ TRUE; }; Peek: Buttons.ButtonProc = { s: AISCopy.State _ NARROW[clientData]; s.parameterError _ FALSE; Show[s]; }; Show: PROC[s: AISCopy.State] = TRUSTED { f: Rope.ROPE _ GetFileName[s, s.inFnViewer]; fdIn: AIS.FRef; rIn: AIS.Raster _ NEW[AIS.RasterPart]; IF s.parameterError THEN RETURN; fdIn _ AIS.OpenFile[name: f ! FS.Error, AIS.Error => { IO.PutF[s.out, "\n%g does not exist", IO.rope[f]]; GOTO notThere; }]; IO.PutF[s.out, "\nOpening %g", IO.rope[f]]; rIn _ AIS.ReadRaster[fdIn]; s.copyH _ s.sourceH _ s.imageH _ rIn.scanCount; s.copyW _ s.sourceW _ s.imageW _ rIn.scanLength; s.imageX _ s.imageY _ 0; AIS.CloseFile[fdIn]; RefreshParams[s]; s.container.name _ s.showFilename _ f; ViewerOps.PaintViewer[s.container, caption]; ViewerOps.PaintViewer[s.AISViewer, client]; EXITS notThere => NULL; }; RefreshParams: PROC [s: AISCopy.State] = BEGIN ViewerTools.SetContents[s.topViewer, IO.PutFR["%g", IO.card[s.imageY]]]; ViewerTools.SetContents[s.leftViewer, IO.PutFR["%g", IO.card[s.imageX]]]; ViewerTools.SetContents[s.heightViewer, IO.PutFR["%g", IO.card[s.imageH]]]; ViewerTools.SetContents[s.widthViewer, IO.PutFR["%g", IO.card[s.imageW]]]; ViewerTools.SetContents[s.oScansViewer, IO.PutFR["%g", IO.card[s.copyH]]]; ViewerTools.SetContents[s.oPixelsViewer, IO.PutFR["%g", IO.card[s.copyW]]]; ViewerTools.SetContents[s.oScaleP, IO.PutFR["%g", IO.real[s.scaleX]]]; ViewerTools.SetContents[s.oScaleS, IO.PutFR["%g", IO.real[s.scaleY]]]; END; Select: Buttons.ButtonProc = { l: LIST OF REF ANY _ NARROW[clientData]; s: AISCopy.State _ NARROW[l.first]; v: ViewerClasses.Viewer _ NARROW[l.rest.first]; s.parameterError _ FALSE; s.imageH _ GetNumberFromViewer[s, s.heightViewer, 0, 2048, "Scans"]; s.imageW _ GetNumberFromViewer[s, s.widthViewer, 0, 2048, "Pixels"]; s.scaleY _ GetRealFromViewer[s, s.oScaleS, 0, 10, "Scans scale"]; s.scaleX _ GetRealFromViewer[s, s.oScaleP, 0, 10, "Pixels scale"]; s.copyH _ GetNumberFromViewer[s, s.oScansViewer, 0, 32000, "Output Scans"]; s.copyW _ GetNumberFromViewer[s, s.oPixelsViewer, 0, 32000, "Output Pixels"]; IF ~s.parameterError AND mouseButton#red THEN SELECT v FROM s.heightViewer => { s.imageH _ Real.RoundC[s.copyH / s.scaleY]; ViewerTools.SetContents[s.heightViewer, IO.PutFR["%g", IO.card[s.imageH]]]; }; s.widthViewer => { s.imageW _ Real.RoundC[s.copyW / s.scaleX]; ViewerTools.SetContents[s.widthViewer, IO.PutFR["%g", IO.card[s.imageW]]]; }; s.oScansViewer => { s.copyH _ Real.RoundC[s.imageH * s.scaleY]; ViewerTools.SetContents[s.oScansViewer, IO.PutFR["%g", IO.card[s.copyH]]]; }; s.oPixelsViewer => { s.copyW _ Real.RoundC[s.imageW * s.scaleX]; ViewerTools.SetContents[s.oPixelsViewer, IO.PutFR["%g", IO.card[s.copyW]]]; }; s.oScaleP => { s.scaleX _ s.copyW / Real.Float[s.imageW]; ViewerTools.SetContents[s.oScaleP, IO.PutFR["%f", IO.real[s.scaleX]]]; }; s.oScaleS => { s.scaleY _ s.copyH / Real.Float[s.imageH]; ViewerTools.SetContents[s.oScaleS, IO.PutFR["%f", IO.real[s.scaleY]]]; }; ENDCASE; ViewerTools.SetSelection[v]; }; AvBuf: TYPE = REF AvBufRec; AvBufRec: TYPE = ARRAY[0..2048] OF LONG CARDINAL; IOBuffer: TYPE = REF IOBufferRec; IOBufferRec: TYPE = PACKED ARRAY [0..2048) OF [0..255]; ShrinkNoOfLines: PUBLIC PROC[s: AISCopy.State, wIn: ExtraAIS.VRef, wOut: AIS.WRef] = { iLineIx,oLineIx: CARDINAL _ 0; avBuf: AvBuf _ NEW[AvBufRec]; ioBuffer: IOBuffer _ NEW[IOBufferRec]; ExpandNoOfPixels: PROC[s: AISCopy.State, avBuf: AvBuf, ioBuffer: IOBuffer] = BEGIN FOR inIx: CARDINAL IN [0..s.imageW] DO outPrevCIx: INTEGER _ Real.FixI[(inIx-0.5)*s.scaleX]; outThisCIx: INTEGER _ Real.FixI[(inIx+0.5)*s.scaleX]; lb: CARDINAL _ MAX[0, outPrevCIx]; ub: CARDINAL _ MIN[outThisCIx, s.copyW]; inIxM1: CARDINAL = IF inIx = 0 THEN 0 ELSE inIx - 1; FOR i: CARDINAL IN [lb..ub) DO f: REAL _ (i - outPrevCIx) / Real.Float[(outThisCIx - outPrevCIx)]; r: REAL _ ioBuffer[inIxM1] + (ioBuffer[MIN[inIx, s.imageW-1]] - ioBuffer[inIxM1]) * f; avBuf[i] _ avBuf[i] + Real.RoundC[r]; ENDLOOP; ENDLOOP; END; ShrinkNoOfPixels: PROC[s: AISCopy.State, avBuf: AvBuf, ioBuffer: IOBuffer] = BEGIN k: CARDINAL _ 0; FOR i: CARDINAL IN [0..s.copyW) DO noOfPixels: CARDINAL _ 0; -- counts number of pixels to be averaged sum: LONG CARDINAL _ 0; -- where pixel sum is accumulated for averaging DO sum _ sum + ioBuffer[k]; -- pick up an input pixel k _ k + 1; noOfPixels _ noOfPixels + 1; -- keep score of no. of inputs needed for this output IF i+1 < k*s.scaleX THEN { avBuf[i] _ avBuf[i] + Real.RoundC[sum / Real.Float[noOfPixels]]; EXIT; }; ENDLOOP; ENDLOOP; END; TRUSTED { -- transfer input to output with compression WHILE oLineIx < s.copyH DO noOfLines: CARDINAL _ 0; -- find first input line for this output line iLineIx _ Real.FixC[oLineIx / s.scaleY]; -- zero the averaging buffer FOR i: CARDINAL IN [0..s.copyW] DO avBuf[i] _ 0; ENDLOOP; -- compress and add in the next few input lines DO ExtraAIS.UnsafeReadLine[v: wIn, buffer: [length: s.imageW, addr: LOOPHOLE[ioBuffer]], line: iLineIx]; -- scale this input line IF s.scaleX<=1.0 THEN ShrinkNoOfPixels[s, avBuf, ioBuffer] ELSE ExpandNoOfPixels[s, avBuf, ioBuffer]; iLineIx _ iLineIx + 1; noOfLines _ noOfLines + 1; IF s.abort THEN RETURN; IF oLineIx+1 <= iLineIx*s.scaleY OR iLineIx=s.imageH THEN EXIT; ENDLOOP; FOR i: CARDINAL IN [0..s.copyW] DO ioBuffer[i] _ Real.RoundC[avBuf[i] / Real.Float[noOfLines]]; ENDLOOP; AIS.UnsafeWriteLine[w: wOut, buffer: [length: s.copyW, addr: LOOPHOLE[ioBuffer]], line: oLineIx]; PieViewers.Set[s.pie, ((s.imageH-iLineIx)*100.0)/s.imageH]; oLineIx _ oLineIx + 1; ENDLOOP; }; }; ExpandNoOfLines: PUBLIC PROC[s: AISCopy.State, wIn: ExtraAIS.VRef, wOut: AIS.WRef] = { inBuffer: IOBuffer _ NEW[IOBufferRec]; oPrevBuffer: IOBuffer _ NEW[IOBufferRec]; oNextBuffer: IOBuffer _ NEW[IOBufferRec]; outBuffer: IOBuffer _ NEW[IOBufferRec]; temp: IOBuffer; ExpandNoOfPixels: PROC[s: AISCopy.State, outBuf: IOBuffer, inBuf: IOBuffer] = { FOR inIx: CARDINAL IN [0..s.imageW] DO outPrevCIx: INTEGER _ Real.RoundI[(inIx-0.5)*s.scaleX]; outThisCIx: INTEGER _ Real.RoundI[(inIx+0.5)*s.scaleX]; lb: CARDINAL _ MAX[0, outPrevCIx]; ub: CARDINAL _ MIN[outThisCIx, s.copyW]; inIxM1: CARDINAL = IF inIx = 0 THEN 0 ELSE inIx - 1; FOR i: CARDINAL IN [lb..ub) DO f: REAL _ (i - outPrevCIx) / Real.Float[(outThisCIx - outPrevCIx)]; r: REAL _ inBuf[inIxM1] + (inBuf[MIN[inIx, s.imageW-1]] - inBuf[inIxM1]) * f; outBuf[i] _ Real.RoundC[r]; ENDLOOP; ENDLOOP; }; ShrinkNoOfPixels: PROC[s: AISCopy.State, outBuf: IOBuffer, inBuf: IOBuffer] = { k: CARDINAL _ 0; FOR i: CARDINAL IN [0..s.copyW) DO noOfPixels: CARDINAL _ 0; -- counts number of pixels to be averaged sum: LONG CARDINAL _ 0; -- where pixel sum is accumulated for averaging DO sum _ sum + inBuf[k]; -- pick up an input pixel k _ k + 1; noOfPixels _ noOfPixels + 1; -- keep score of no. of inputs needed for this output IF i+1 < k*s.scaleX THEN { outBuf[i] _ Real.RoundC[sum / Real.Float[noOfPixels]]; EXIT; }; ENDLOOP; ENDLOOP; }; TRUSTED { ExtraAIS.UnsafeReadLine[v: wIn, buffer: [length: s.imageW, addr: LOOPHOLE[inBuffer]], line: 0]; IF s.scaleX<=1.0 THEN ShrinkNoOfPixels[s, oNextBuffer, inBuffer] ELSE ExpandNoOfPixels[s, oNextBuffer, inBuffer]; FOR iLineIx: CARDINAL IN [0..s.imageH] DO oPrevCIx: INTEGER _ Real.FixI[(iLineIx-0.5)*s.scaleY]; oNextCIx: INTEGER _ Real.FixI[(iLineIx+0.5)*s.scaleY]; lb: CARDINAL _ MAX[0, oPrevCIx]; ub: CARDINAL _ MIN[oNextCIx, s.copyH]; inIxM1: CARDINAL = IF iLineIx = 0 THEN 0 ELSE iLineIx - 1; temp _ oPrevBuffer; oPrevBuffer _ oNextBuffer; oNextBuffer _ temp; ExtraAIS.UnsafeReadLine[v: wIn, buffer: [length: s.imageW, addr: LOOPHOLE[inBuffer]], line: MIN[iLineIx, s.imageH-1]]; IF s.scaleX<=1.0 THEN ShrinkNoOfPixels[s, oNextBuffer, inBuffer] ELSE ExpandNoOfPixels[s, oNextBuffer, inBuffer]; FOR i: CARDINAL IN [lb..ub) DO f: REAL _ (i-oPrevCIx) / Real.Float[(oNextCIx - oPrevCIx)]; FOR j: CARDINAL IN [0..s.copyW) DO outBuffer[j] _ Real.RoundC[oPrevBuffer[j] + (oNextBuffer[j] - oPrevBuffer[j]) * f]; ENDLOOP; AIS.UnsafeWriteLine[w: wOut, buffer: [length: s.copyW, addr: LOOPHOLE[outBuffer]], line: i]; PieViewers.Set[s.pie, ((s.imageH-iLineIx)*100.0)/s.imageH]; ENDLOOP; ENDLOOP; }; }; GetNumberFromViewer: PUBLIC PROC[s: AISCopy.State, v: ViewerClasses.Viewer, lb,ub: INTEGER, er: Rope.ROPE] RETURNS[i: INTEGER] = { in: IO.STREAM _ IO.RIS[ViewerTools.GetContents[v]]; i _ lb; i _ IO.GetInt[in ! IO.EndOfStream => { IO.PutF[s.out, "\nSpecify %g please (%g..%g)", IO.rope[er], IO.card[lb], IO.card[ub]]; s.parameterError _ TRUE; GOTO Croak; }]; IF NOT (i IN [lb..ub]) THEN { s.parameterError _ TRUE; IO.PutF[s.out, "\n%g is not in the range %g..%g", IO.rope[er], IO.card[lb], IO.card[ub]]; }; EXITS Croak => NULL; }; GetRealFromViewer: PUBLIC PROC[s: AISCopy.State, v: ViewerClasses.Viewer, lb,ub: REAL, er: Rope.ROPE] RETURNS[r: REAL] = { in: IO.STREAM _ IO.RIS[ViewerTools.GetContents[v]]; r _ lb; r _ IO.GetReal[in ! IO.EndOfStream => { IO.PutF[s.out, "\nSpecify %g please (%g..%g)", IO.rope[er], IO.real[lb], IO.real[ub]]; s.parameterError _ TRUE; GOTO Croak; }]; IF NOT (r IN [lb..ub]) THEN { s.parameterError _ TRUE; IO.PutF[s.out, "\n%g is not in the range %g..%g", IO.rope[er], IO.real[lb], IO.real[ub]]; }; EXITS Croak => NULL; }; GetFileName: PUBLIC PROC[s: AISCopy.State, v: ViewerClasses.Viewer] RETURNS[fileName: Rope.ROPE] = { cp: FS.ComponentPositions; [fileName, cp] _ FS.ExpandName[name: ViewerTools.GetContents[v], wDir: ViewerTools.GetContents[s.wdViewer] ! FS.Error => {IO.PutF[s.out, "\nFS Error: %g", IO.rope[error.explanation]]; s.parameterError _ TRUE; fileName _ NIL; GOTO Out; }]; IF cp.base.length = 0 THEN { IO.PutF[s.out, "\nSpecify a filename please"]; s.parameterError _ TRUE; fileName _ NIL; } ELSE IF cp.ext.length # 3 OR NOT Rope.Equal["ais", Rope.Substr[fileName, cp.ext.start, cp.ext.start+cp.ext.length], FALSE] THEN { IO.PutF[s.out, "\nSpecify a filename with an ais extension please"]; s.parameterError _ TRUE; fileName _ NIL; } ELSE IF cp.ext.length = 0 THEN fileName _ Rope.Concat[fileName, ".ais"]; EXITS Out => RETURN [NIL]; }; FeedbackParams: PROC[s: AISCopy.State] = { ViewerTools.SetContents[s.widthViewer, IO.PutFR["%g", IO.card[s.imageW]]]; ViewerTools.SetContents[s.heightViewer, IO.PutFR["%g", IO.card[s.imageH]]]; ViewerTools.SetContents[s.oPixelsViewer, IO.PutFR["%g", IO.card[s.imageW]]]; ViewerTools.SetContents[s.oScansViewer, IO.PutFR["%g", IO.card[s.imageH]]]; }; AISNotify: ViewerClasses.NotifyProc = TRUSTED { s: AISCopy.State _ NARROW[self.data]; SELECT input.first FROM $SetTopLeft => WITH input.rest.first SELECT FROM xy: TIPUser.TIPScreenCoords => { s.imageX _ Real.RoundC[MAX[MIN[(s.x1 _ xy.mouseX) / s.scale, 2047], 0]]; s.imageY _ Real.RoundC[MAX[MIN[s.sourceH - (s.y1 _ xy.mouseY) / s.scale, 2047], 0]]; -- scan 0 is at the top s.imageW _ s.imageH _ 0; s.x1 _ MAX[MIN[s.x1, (2047-s.imageX)*s.scale], 0]; s.y1 _ MAX[MIN[s.y1, (2047-s.imageY)*s.scale], 0]; ViewerTools.SetContents[s.topViewer, IO.PutFR["%g", IO.card[s.imageY]]]; ViewerTools.SetContents[s.leftViewer, IO.PutFR["%g", IO.card[s.imageX]]]; s.x2 _ s.x1+1; s.y2 _ s.y1+1; FeedbackParams[s]; ViewerOps.PaintViewer[s.AISViewer, client, FALSE, $XORBOX]; }; ENDCASE; $Adjust => WITH input.rest.first SELECT FROM xy: TIPUser.TIPScreenCoords => { ViewerOps.PaintViewer[s.AISViewer, client, FALSE, $XORBOX]; s.x2 _ xy.mouseX; s.y2 _ xy.mouseY; s.x2 _ MAX[MIN[s.x2, (2047-s.imageX)*s.scale], 0]; s.y2 _ MAX[MIN[s.y2, (2047-s.imageY)*s.scale], 0]; s.imageW _ Real.RoundC[ABS[(s.x2+1-s.x1)] / s.scale]; s.imageW _ MIN[MAX[2048-s.imageX, 0], s.imageW]; s.imageH _ Real.RoundC[ABS[(s.y1+1-s.y2)] / s.scale]; s.imageH _ MIN[MAX[2048-s.imageY, 0], s.imageH]; FeedbackParams[s]; ViewerOps.PaintViewer[s.AISViewer, client, FALSE, $XORBOX]; }; ENDCASE; $SetBottomRight => WITH input.rest.first SELECT FROM xy: TIPUser.TIPScreenCoords => { ViewerOps.PaintViewer[s.AISViewer, client, FALSE, $XORBOX]; s.x2 _ xy.mouseX; s.y2 _ xy.mouseY; s.x2 _ MAX[MIN[s.x2, (2047-s.imageX)*s.scale], 0]; s.y2 _ MAX[MIN[s.y2, (2047-s.imageY)*s.scale], 0]; s.imageW _ Real.RoundC[ABS[(s.x2+1-s.x1)] / s.scale]; s.imageW _ MIN[MAX[2048-s.imageX, 0], s.imageW]; s.imageH _ Real.RoundC[ABS[(s.y1+1-s.y2)] / s.scale]; s.imageH _ MIN[MAX[2048-s.imageY, 0], s.imageH]; FeedbackParams[s]; IF s.x2s.y1 THEN { s.imageY _ s.imageY + s.imageH; ViewerTools.SetContents[s.topViewer, IO.PutFR["%g", IO.card[s.imageY]]]; } }; ENDCASE; ENDCASE => ERROR; }; AISPaint: ViewerClasses.PaintProc = TRUSTED { s: AISCopy.State _ NARROW[self.data]; IF whatChanged=$XORBOX THEN { Imager.SetColor[context, ImagerBackdoor.invert]; Imager.MaskBox[context, [s.x1, s.y1, s.x2, s.y2]]; } ELSE { sx,sy: REAL; box: Imager.Rectangle _ ImagerBackdoor.GetBounds[context]; fileExists: BOOLEAN _ TRUE; pixelArray: ImagerPixelArray.PixelArray; sx _ box.w / s.sourceW; sy _ box.h / s.sourceH; s.scale _ MIN[sx,sy]; pixelArray _ ImagerPixelArray.FromAIS[s.showFilename ! FS.Error => { fileExists _ FALSE; CONTINUE; }]; IF fileExists THEN{ Imager.Scale2T[context, [s.scale, s.scale]]; Imager.SetSampledColor[context: context, m: ImagerTransformation.Scale[1.0], pa: pixelArray, colorOperator: ImagerColorOperator.GrayLinearColorModel[sWhite~255, sBlack~0]]; Imager.MaskBox[context, [0,0, s.sourceW, s.sourceH]]; } }; }; Init: PROCEDURE [f: Rope.ROPE, wd: Rope.ROPE _ NIL] = { Rule: PROC [wx, wy, ww, wh: INTEGER] ~ { [] _ Rules.Create[info: [wx: wx, wy: wy, ww: ww, wh: wh, parent: s.container]]; }; Button: PROC [name: Rope.ROPE, wx, wy: INTEGER, proc: Buttons.ButtonProc, clientData: REF] ~ { [] _ Buttons.Create[info: [name: name, wx: wx, wy: wy, parent: s.container], proc: proc, clientData: clientData]; }; SelectButton: PROC [name: Rope.ROPE, wx, wy: INTEGER, v: ViewerClasses.Viewer] ~ { [] _ Buttons.Create[info: [name: name, wx: wx, wy: wy, parent: s.container], proc: Select, clientData: LIST[s, v]]; }; SelectViewer: PROC [wx, wy, ww, wh: INTEGER, data: Rope.ROPE _ NIL] RETURNS [ViewerClasses.Viewer] ~ { RETURN [ViewerTools.MakeNewTextViewer[info: [wx: wx, wy: wy, ww: ww, wh: wh, parent: s.container, data: data, border: FALSE, scrollable: TRUE]]] }; s: AISCopy.State _ NEW[AISCopy.StateRec]; s.container _ ViewerOps.CreateViewer[flavor: $Container, info: [name: "Copy", scrollable: FALSE, icon: icon]]; Rule[wx: 0, wy: 112, ww: 1000, wh: 2]; Rule[wx: 255, wy: 22, ww: 2, wh: 68]; Rule[wx: 505, wy: 22, ww: 2, wh: 68]; Rule[wx: 0, wy: 90, ww: 1000, wh: 2]; Rule[wx: 0, wy: 22, ww: 1000, wh: 2]; s.AISViewer _ ViewerOps.CreateViewer[flavor: $AISCopy, info: [name: "AIS file", wx: 0, wy: 114, ww: 0, wh: 0, parent: s.container, data: s]]; Containers.ChildYBound[s.container, s.AISViewer]; Containers.ChildXBound[s.container, s.AISViewer]; IF wd.IsEmpty AND NOT f.IsEmpty THEN { fullFName: Rope.ROPE; cp: FS.ComponentPositions; [fullFName, cp] _ FS.ExpandName[f]; wd _ Rope.Substr[fullFName, 0, cp.base.start]; f _ Rope.Substr[fullFName, cp.base.start, cp.ver.start+cp.ver.length]; }; s.wdViewer _ ViewerTools.MakeNewTextViewer[info: [wx: 53, wy: 3, ww: 544, wh: 15, parent: s.container, border: FALSE, scrollable: TRUE, data: wd]]; Button[name: "WD: ", wx: 10, wy: 3, proc: SelectWD, clientData: s.wdViewer]; s.inFnViewer _ SelectViewer[wx: 112, wy: 32, ww: 130, wh: 15]; SelectButton[name: "Input Filename: ", wx: 10, wy: 32, v: s.inFnViewer]; s.topViewer _ SelectViewer[wx: 42, wy: 52, ww: 50, wh: 15, data: "0"]; SelectButton[name: "Top:", wx: 10, wy: 52, v: s.topViewer]; s.leftViewer _ SelectViewer[wx: 42, wy: 72, ww: 50, wh: 15, data: "0"]; SelectButton[name: "Left:", wx: 10, wy: 72, v: s.leftViewer]; s.heightViewer _ SelectViewer[wx: 135, wy: 52, ww: 50, wh: 15, data: "2048"]; SelectButton[name: "Scans:", wx: 94, wy: 52, v: s.heightViewer]; s.widthViewer _ SelectViewer[wx: 135, wy: 72, ww: 50, wh: 15, data: "2048"]; SelectButton[name: "Pixels:", wx: 94, wy: 72, v: s.widthViewer]; Button[name: "PEEK", wx: 205, wy: 52, proc: Peek, clientData: s]; s.emptyViewer _ SelectViewer[wx: 201, wy: 72, ww: 54, wh: 15, data: "0"]; SelectButton[name: "e:", wx: 185, wy: 72, v: s.emptyViewer]; s.outFnViewer _ SelectViewer[wx: 371, wy: 32, ww: 130, wh: 15]; SelectButton[name: "Output Filename: ", wx: 260, wy: 32, v: s.outFnViewer]; s.oScansViewer _ SelectViewer[wx: 302, wy: 52, ww: 50, wh: 15, data: "2048"]; SelectButton[name: "Scans:", wx: 260, wy: 52, v: s.oScansViewer]; s.oPixelsViewer _ SelectViewer[wx: 302, wy: 72, ww: 50, wh: 15, data: "2048"]; SelectButton[name: "Pixels:", wx: 260, wy: 72, v: s.oPixelsViewer]; s.oScaleS _ SelectViewer[wx: 400, wy: 52, ww: 50, wh: 15, data: "1.0"]; SelectButton[name: "Scale:", wx: 360, wy: 52, v: s.oScaleS]; s.oScaleP _ SelectViewer[wx: 400, wy: 72, ww: 50, wh: 15, data: "1.0"]; SelectButton[name: "Scale:", wx: 360, wy: 72, v: s.oScaleP]; Button[name: "GO", wx: 520, wy: 32, proc: Go, clientData: s]; Button[name: "ABORT", wx: 520, wy: 52, proc: Abort, clientData: s]; s.logViewer _ ViewerOps.CreateViewer[flavor: $TypeScript, info: [wx: 30, wy: 94, ww: 560, wh: 15, parent: s.container]]; [ , s.out] _ ViewerIO.CreateViewerStreams[viewer: s.logViewer, name: NIL]; s.pie _ PieViewers.Create[parent: s.container, x: 10, y: 94]; IF f#NIL THEN { ViewerTools.SetContents[s.inFnViewer, f]; Show[s]; }; }; SelectWD: Buttons.ButtonProc ~ { wdViewer: ViewerClasses.Viewer _ NARROW[clientData]; SELECT mouseButton FROM red => { selectedViewer: ViewerClasses.Viewer _ ViewerTools.GetSelectedViewer[]; newWD: Rope.ROPE _ NIL; IF selectedViewer # NIL THEN newWD _ ViewerTools.GetSelectionContents[]; IF Rope.Size[newWD] <= 1 THEN { SELECT selectedViewer.class.flavor FROM $Text => { IF NOT Rope.IsEmpty[selectedViewer.file] THEN { fullFName: Rope.ROPE; cp: FS.ComponentPositions; [fullFName, cp] _ FS.ExpandName[selectedViewer.file]; newWD _ Rope.Substr[fullFName, 0, cp.base.start]; } ELSE newWD _ NIL; }; $Typescript => { IF Rope.Equal["CommandTool", Rope.Substr[selectedViewer.name, 0, 11]] THEN newWD _ Rope.Substr[selectedViewer.name, 18] ELSE newWD _ NIL; }; ENDCASE => newWD _ NIL; }; IF NOT newWD.IsEmpty THEN ViewerTools.SetContents[wdViewer, newWD]; }; yellow => NULL; blue => ViewerTools.SetContents[wdViewer, ""]; ENDCASE; ViewerTools.SetSelection[wdViewer]; }; StartNewCopyProcess: Commander.CommandProc = { f: Rope.ROPE; empty: BOOLEAN _ FALSE; p: PROCESS; wd: Rope.ROPE _ Commander.PrependWorkingDir["a"]; wd _ Rope.Substr[wd, 0, Rope.Size[wd]-1]; f _ IO.GetTokenRope[IO.RIS[cmd.commandLine], IO.IDProc ! IO.EndOfStream => { empty _ TRUE; CONTINUE; }].token; p _ FORK Init[IF empty OR Rope.Length[f]<1 THEN NIL ELSE f, wd]; }; AISCopyClass: ViewerClasses.ViewerClass _ NEW[ViewerClasses.ViewerClassRec]; AISCopyClass.paint _ AISPaint; AISCopyClass.notify _ AISNotify; AISCopyClass.tipTable _ TIPUser.InstantiateNewTIPTable["AISCopy.tip"]; ViewerOps.RegisterViewerClass[$AISCopy, AISCopyClass]; Commander.Register[key: "AISCopy", proc: StartNewCopyProcess, doc: "AIS copying program"]; END. AISCopyImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Mik Lamming - January 30, 1984 11: 58: 25 am PST Last Edited by: Spreitzer, July 21, 1984 5: 28: 59 pm PDT Tim Diebert: October 25, 1985 10:58:30 am PDT Rick Beach, May 29, 1985 6:25:07 pm PDT (CedarChest6.0) Parameter gathering and checking routines Sets a flag so scanning loops will terminate early Loads a file into the AIS viewer - filename is expected to be correct! Red bug: pending-delete select Blue bug: make this parameter consistent with others Scale Manipulation Linearly interpolates pixels between pairs. -- compress the next few pixels into one -- stop pixel averaging when next input would contribute to next output pixel -- add the average of these pixels into line buffer -- read a line from input file -- stop line averaging when next input would contribute to next output line -- "OR iLineIx=s.imageH" - avoids F.P. fuzz problems -- generate the 'average' as the working buffer is copied to the output buffer -- write out the output buffer -- update the pie chart to show that another output line has been generated -- move to the next output line Linearly interpolates pixels between pairs. -- compress the next few pixels into one -- stop pixel averaging when next input would contribute to next output pixel -- read in the first input line and scale it -- calculate indices of first and last output lines -- swap the buffers -- read the next line into the buffer and process it -- interpolate output lines -- write out the new line -- update the pie chart to show that another output line has been generated AIS displayer Reads in a number from a text viewer and does a range check. Reports errors in the log viewer. Reads in a number from a text viewer and does a range check. Reports errors in the log viewer. -- Handle mouse inputs for creating cropping box -- if the user creates the box in the wrong direction then fix up the numbers Provide interactive feed back for cropping process Copy the image for the available space Initialization -- Divide image from controls -- Divide Input parameters from Output parameters -- Divide Output parameters from Command buttons -- Divide parameters from feedback -- Divide working directory from parameters -- Image viewer -- working directory button -- Input controls -- Output parameters -- Command buttons -- Feedback instruments get wd from working directory of name of viewer newWD from file name of viewer newWD from CommandTool; lots of heuristics here my friend!!! -- creates a new incarnation of the scanner program Κ‘˜code™Kšœ Οmœ1™˜>KšœH˜HK˜KšœF˜FKšœ;˜;K˜KšœG˜GKšœ=˜=K˜KšœM˜MKšœ@˜@K˜KšœL˜LKšœ@˜@K˜KšœA˜AK˜KšœI˜IKšœ<˜