MODULE ImageFilePGMSpecific EXPORTS ImageFilePGM; IMPORT PGM; IMPORT Rd, Wr, Text, Thread, FileWr, FileRd, OSError; FROM Stdio IMPORT stdin, stdout; TYPE ImageParms = RECORD name: TEXT; (* File name (with extension) *) fmv: LONGREAL; (* = FLOAT(maxVal, LONGREAL) *) shift, scale: LONGREAL; (* Pixel maping: pixel = round((state + shift)*scale) *) END; REVEAL Writer = WriterPublic BRANDED OBJECT wr: Wr.T; (* The file *) Writer: PGM.Writer; (* Image writer *) h: ImageParms; (* Image parameters *) OVERRIDES open := WriterOpen; put := WriterPut; close := WriterClose; END; PROCEDURE WriterOpen( f: Writer; name: TEXT; NX, NY: CARDINAL; READONLY a, s: ChannelParms; VAR absError, relError: ChannelParms; READONLY maxVal := ChannelRanges{DefaultMaxVal, ..}; ): Writer RAISES {Wr.Failure, Thread.Alerted, OSError.E} = BEGIN IF Text.Empty(name) OR Text.Equal("-", name) THEN f.h.name := "(stdout)"; f.wr := stdout ELSE WITH wr = FileWr.Open(name) DO f.h.name := name; f.wr := wr; END END; f.Writer := NEW(PGM.Writer).init( f.wr, NX, NY, maxVal := maxVal[0], binary := TRUE ); f.h.fmv := FLOAT(maxVal[0], LONGREAL); WITH i = 0, lo = a[i] - s[i], hi = a[i] + s[i] DO <* ASSERT hi # lo *> f.h.shift := -lo; f.h.scale := f.h.fmv / (hi - lo); absError[i] := 1.0d-200 + ABS(s[i]) / f.h.fmv; relError[i] := 1.0d-10; END; RETURN f END WriterOpen; PROCEDURE WriterPut(f: Writer; READONLY s: LongRealPixel) RAISES {Wr.Failure, Thread.Alerted} = BEGIN WITH ss = s[0], fv = MAX(0.0d0, MIN(f.h.fmv, (ss + f.h.shift) * f.h.scale)), v = ROUND(fv) DO f.Writer.put(v) END END WriterPut; PROCEDURE WriterClose(f: Writer) RAISES {Wr.Failure, Thread.Alerted} = BEGIN f.Writer.finish(); Wr.Close(f.wr); END WriterClose; REVEAL Reader = ReaderPublic BRANDED OBJECT rd: Rd.T; (* The file *) Reader: PGM.Reader; (* Image reader *) h: ImageParms; (* Image parameters *) OVERRIDES open := ReaderOpen; get := ReaderGet; close := ReaderClose; END; PROCEDURE ReaderOpen( f: Reader; name: TEXT; VAR NX, NY: CARDINAL; READONLY a, s: ChannelParms; VAR absError, relError: ChannelParms; ): Reader RAISES {Rd.Failure, Thread.Alerted, OSError.E} = VAR maxVal: CARDINAL; BEGIN IF Text.Empty(name) OR Text.Equal("-", name) THEN f.rd := stdin; f.h.name := "(stdin)" ELSE WITH rd = FileRd.Open(name) DO f.rd := rd; f.h.name := name; END END; f.Reader := NEW(PGM.Reader).init(f.rd, NX, NY, maxVal := maxVal); f.h.fmv := FLOAT(maxVal, LONGREAL); WITH lo = a[0] - s[0], hi = a[0] + s[0] DO <* ASSERT hi # lo *> f.h.scale := f.h.fmv / (hi - lo); f.h.shift := - lo; absError[0] := 1.0d-200 + ABS(s[0]) / f.h.fmv; relError[0] := 1.0d-14; END; RETURN f END ReaderOpen; PROCEDURE ReaderGet(f: Reader; VAR s: LongRealPixel) RAISES {Rd.Failure, Thread.Alerted} = VAR v: CARDINAL; BEGIN f.Reader.get(v); s[0] := FLOAT(v, LONGREAL)/f.h.scale - f.h.shift; END ReaderGet; PROCEDURE ReaderClose(f: Reader) RAISES {Rd.Failure, Thread.Alerted} = BEGIN f.Reader.finish(); Rd.Close(f.rd); END ReaderClose; BEGIN END ImageFilePGMSpecific.