ConvolutionFilterImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Tim Diebert: July 30, 1985 12:23:47 pm PDT
DIRECTORY
AIS,
Ascii,
Commander USING [CommandProc, Register],
CommandTool USING [FileWithSearchRules],
FS USING [StreamOpen],
IO,
Process USING [CheckForAbort, GetPriority, Priority, priorityBackground, SetPriority],
Real USING [RoundI],
Rope USING [Equal, Concat, ROPE];
ConvolutionFilterImpl: CEDAR PROGRAM
IMPORTS AIS, Commander, CommandTool, FS, IO, Process, Real, Rope
EXPORTS
~ BEGIN OPEN Ascii;
ROPE: TYPE ~ Rope.ROPE;
STREAM: TYPE ~ IO.STREAM;
FilterSpec: TYPE ~ REF FilterSpecRep;
FilterSpecRep: TYPE ~ RECORD [
x, y: CARDINAL,
seq: SEQUENCE cnt: CARDINAL OF ZEROREAL
];
ZEROREAL: TYPE ~ REAL← 0.0;
ApplyFilterSpec: PROC [inFile, outFile: ROPE, filter: FilterSpec] = BEGIN
inF: AIS.FRef = AIS.OpenFile[inFile];
inR: AIS.Raster = AIS.ReadRaster[inF];
outR: AIS.Raster = NEW [AIS.RasterPart ← inR^];
outF: AIS.FRef = AIS.CreateFile[outFile, outR];
inW: AIS.WRef = AIS.OpenWindow[inF];
outW: AIS.WRef;
firstScan, lastScan, firstPixel, lastPixel: CARDINAL;
[firstScan, lastScan, firstPixel, lastPixel] ← AIS.GetWindowParams[inW];
outW ← AIS.OpenWindow[outF, firstScan, lastScan, firstPixel, lastPixel];
AIS.WriteComment[outF, AIS.ReadComment[inF]];
FOR line: CARDINAL IN [firstScan .. lastScan] DO
FOR pixel: CARDINAL IN [firstPixel .. lastPixel] DO
ENABLE UNWIND => {AIS.CloseWindow[inW]; AIS.CloseWindow[outW]; AIS.CloseFile[inF]; AIS.CloseFile[outF]};
np: CARDINAL;
x: INT = filter.x/2;
y: INT = filter.y/2;
sum: REAL ← 0.0;
FOR i: INT IN [-y .. y] DO
IF i+line NOT IN [firstScan .. lastScan] THEN LOOP;
FOR j: INT IN [-x .. x] DO
fi: CARDINAL ← (i+y)*filter.x + (j+x);
IF j+pixel NOT IN [firstPixel .. lastPixel] THEN LOOP;
sum← sum + AIS.ReadSample[inW, i+line, j+pixel] * filter.seq[fi];
Process.CheckForAbort[];
ENDLOOP;
ENDLOOP;
np← MIN[MAX[Real.RoundI[sum], 0], 255];
AIS.WriteSample[outW, np, line, pixel];
ENDLOOP;
ENDLOOP;
AIS.CloseWindow[inW];
AIS.CloseWindow[outW];
AIS.CloseFile[inF];
AIS.CloseFile[outF];
END;
ParseFilterSpec: PROC [filterName: ROPE, fileName: ROPE] RETURNS [filter: FilterSpec] = BEGIN
name: ROPE = Rope.Concat[filterName, ":"];
s: STREAM = FS.StreamOpen[fileName];
token: ROPE; x, y: CARDINAL;
BEGIN ENABLE UNWIND => IF s # NIL THEN IO.Close[s];
DO
IF IO.EndOf[s] THEN EXIT;
token← IO.GetTokenRope[s, Break ! IO.EndOfStream => EXIT].token;
IF NOT Rope.Equal[token, name, FALSE] THEN LOOP;
x← IO.GetCard[s ! IO.EndOfStream => ERROR];
token← IO.GetTokenRope[s, Break ! IO.EndOfStream => ERROR].token;
IF NOT Rope.Equal[token, "by", FALSE] THEN ERROR;
y← IO.GetCard[s ! IO.EndOfStream => ERROR];
IF y MOD 2 # 1 THEN ERROR;
IF x MOD 2 # 1 THEN ERROR;
filter← NEW [FilterSpecRep[x*y]];
filter.x← x; filter.y← y;
FOR i: CARDINAL IN [0 .. y) DO
FOR j: CARDINAL IN [0 .. x) DO
filter.seq[i*x+j] ← IO.GetReal[s ! IO.EndOfStream => ERROR];
ENDLOOP;
ENDLOOP;
ENDLOOP;
END; -- of enable
IO.Close[s];
END;
Break: IO.BreakProc =
{RETURN [SELECT char FROM
CR, SP, TAB, ',, '{, '} => sepr,
ENDCASE => other]};
GetToken: PROC [stream: IO.STREAM] RETURNS [rope: ROPENIL] = {
Break: PROC [char: CHAR] RETURNS [IO.CharClass] ~ {
IF char = '← OR char = '; THEN RETURN [break];
IF char = ' OR char = '  OR char = ', OR char = '\n THEN RETURN [sepr];
RETURN [other];
};
rope ← stream.GetTokenRope[Break ! IO.EndOfStream => CONTINUE].token;
};
ConvolutionFilterCommand: Commander.CommandProc ~ {
stream: IO.STREAMIO.RIS[cmd.commandLine];
outputName: ROPE ← GetToken[stream];
gets: ROPE ← GetToken[stream];
inputName: ROPE ← GetToken[stream];
oldPriority: Process.Priority ← Process.GetPriority[];
filter: ROPE ← GetToken[stream];
filterSpec: FilterSpec;
IF NOT gets.Equal["←"] THEN {
cmd.out.PutRope["Specify output ← input <filterspec>, please.\n"];
RETURN;
};
filterSpec ← ParseFilterSpec[filter, CommandTool.FileWithSearchRules["Filter", "txt", cmd]];
Process.SetPriority[Process.priorityBackground];
ApplyFilterSpec[inputName, outputName, filterSpec ! UNWIND => Process.SetPriority[oldPriority]];
Process.SetPriority[oldPriority];
cmd.out.PutRope["Done.\n"];
};
Commander.Register["ConvolutionFilter", ConvolutionFilterCommand, "Apply convolution filter to (output ← input filter"];
END.