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: ROPE _ NIL] = { 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.STREAM _ IO.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 , 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. ŠConvolutionFilterImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Tim Diebert: July 30, 1985 12:23:47 pm PDT ΚΎ˜™Icodešœ Οmœ1™˜HKšžœžœ˜-šžœžœžœž˜0šžœžœžœž˜3Kš žœžœžœžœžœžœ˜hKšœžœ˜ Kšœžœ˜Kšœžœ˜Kšœžœ˜šžœžœžœ ž˜Kš žœžœžœžœžœ˜3šžœžœžœ ž˜Kšœžœ˜&Kš žœ žœžœžœžœ˜6Kšœ žœ3˜AK˜Kšžœ˜—Kšžœ˜—Kšœžœžœ˜'Kšžœ$˜'Kšžœ˜—Kšžœ˜—Kšžœ˜Kšžœ˜Kšžœ˜Kšžœ˜Kšžœ˜—K˜K˜š  œžœžœ žœžœž˜]Kšœžœ ˜*Kšœžœžœ˜$Kšœžœžœ˜šžœžœžœžœžœžœžœ ˜3šž˜Kšžœžœ žœžœ˜Kšœžœžœžœ˜@Kš žœžœžœžœžœ˜0Kšœžœžœžœ˜,Kšœžœžœžœ˜AKš žœžœžœžœžœ˜1Kšœžœžœžœ˜,Kšžœžœžœžœ˜Kšžœžœžœžœ˜Kšœžœ˜!Kšœ˜šžœžœžœ ž˜šžœžœžœ ž˜Kšœžœ žœžœ˜