DIRECTORY ConvertToRasters, CrosfieldTape, OptronicsTape, Interpress, Imager, Rope, InterpressToTape, ImagerPixel, ImagerSample, ImagerTransformation, ImagerMaskCapture, PrintColor, Real, AIS, FS, IO, MessageWindow, PrintColorTransformations, TapesCommon, UnixTapeOps, SF, ImagerBox; InterpressToTapeImpl: CEDAR PROGRAM IMPORTS ConvertToRasters, CrosfieldTape, Interpress, Real, AIS, Rope, Imager, FS, IO, MessageWindow, PrintColorTransformations, OptronicsTape, UnixTapeOps, ImagerTransformation, ImagerMaskCapture, ImagerBox EXPORTS InterpressToTape ~ BEGIN OPEN InterpressToTape; ROPE: TYPE ~ Rope.ROPE; ColorCorrection: TYPE ~ PrintColor.ColorCorrection; PixelBuffer: TYPE ~ ImagerPixel.PixelBuffer; ColorType: TYPE ~ OptronicsTape.ColorType; DefaultTapeSpec: PUBLIC PROC [name: ROPE, tapeNumber: NAT] RETURNS[TapeSpec] = { spec: TapeSpec _ NEW[TapeSpecRep _ [ note: name, tapeNumber: tapeNumber, serverName: "Chroma", drive: 0, density: GCR6250, tapeSize: 2400 ]]; RETURN[spec]; }; DefaultIPSize: PUBLIC PROC [name: ROPE, page: NAT _ 1, tol: REAL _ 0.02] RETURNS [fOrg, sOrg, fDim, sDim: REAL] = { m: Imager.Transformation _ ImagerTransformation.Scale[1/tol/0.0254]; -- ~1/tol pixels/inch n: Imager.Transformation _ ImagerTransformation.PostScale[m, 0.0254]; -- back to inches master: Interpress.Master _ Interpress.Open[name, NIL]; Operator: PROC [context: Imager.Context] ~ { Imager.SetColor[context, Imager.black]; Imager.SetStrokeEnd[context, square]; Imager.SetStrokeWidth[context, 0.0]; Imager.SetAmplifySpace[context, 1.0]; Interpress.DoPage[master, page, context, NIL]; }; b: SF.Box _ ImagerMaskCapture.CaptureBounds[Operator, m ! ImagerMaskCapture.Cant => RESUME]; r: ImagerBox.Rectangle _ ImagerTransformation.InverseTransformRectangle[ n, ImagerBox.RectangleFromBox[[b.min.s, b.min.f, b.max.s, b.max.f]]]; RETURN[fOrg: r.x, sOrg: r.y, fDim: r.w, sDim: r.h]; }; SizeFromIPSpecs: PUBLIC PROC[files: LIST OF IPSpec, format: Format, tapeSpec: TapeSpec] RETURNS[sizes: LIST OF Sizes, total: REAL] = { crosfield: FileAction = { fileSpec: CrosfieldTape.FileSpec _ NEW[CrosfieldTape.FileSpecRep _ [ pixelsPerInch: CrosfieldValToPPI[pixelsPerInch], nLines: nLines, nPixels: nPixels, note: name, mapPixel: CrosfieldTape.ByteToCrosfield ]]; size: REAL _ CrosfieldTape.SizeOfFile[fileSpec, tapeSpec.density]; sizes _ CONS[[name, size], sizes]; total _ total+size; }; optronics: FileAction = { fileSpec: OptronicsTape.FileSpec _ NEW[OptronicsTape.FileSpecRep _ [ pixelsPerInch: OptronicsValToPPI[pixelsPerInch], nLines: nLines, nPixels: nPixels, rgbInterleaved: NOT achromatic ]]; size: REAL _ OptronicsTape.SizeOfFile[fileSpec, tapeSpec.density]; sizes _ CONS[[name, size], sizes]; total _ total+size; }; SELECT format FROM optronics => { total _ OptronicsTape.SizeOfHeader[tapeSpec.density]; DoFileList[files: files, fileAction: optronics, reduceResolution: 1, format: format]; }; crosfield => { total _ CrosfieldTape.SizeOfHeader[tapeSpec.density]; DoFileList[files: files, fileAction: crosfield, reduceResolution: 1, format: format]; }; ENDCASE => ERROR; }; WillNotFit: PUBLIC SIGNAL = CODE; WriteTape: PUBLIC PROC [files: LIST OF IPSpec, format: Format, tapeSpec: TapeSpec] = { SELECT format FROM crosfield => WriteCrosfieldTape[files, tapeSpec]; optronics => WriteOptronicsTape[files, tapeSpec]; ENDCASE; }; Preview: PUBLIC PROC [files: LIST OF IPSpec, wd: ROPE _ NIL, reduceResolution: REAL _ 0.25] = { WriteRGBAIS[files: files, wd: wd, reduceResolution: reduceResolution, preview: TRUE]; }; WriteAIS: PUBLIC PROC [files: LIST OF IPSpec, format: Format, wd: ROPE _ NIL, reduceResolution: REAL _ 0.25] = { SELECT format FROM crosfield => WriteCrosfieldAIS[files: files, wd: wd, reduceResolution: reduceResolution]; optronics => WriteRGBAIS[files: files, wd: wd, reduceResolution: reduceResolution, preview: FALSE]; ENDCASE; }; InitCrosfieldTape: PUBLIC PROC [files: LIST OF IPSpec, tapeSpec: TapeSpec, rewindOnClose: BOOLEAN] = { tape: UnixTapeOps.TapeHandle _ UnixTapeOps.OpenDrive[tapeSpec.serverName, tapeSpec.drive, tapeSpec.density]; fileSpecList: CrosfieldTape.FileSpecList _ CrosfieldFromIPSpec[files]; size: REAL _ 0; size _ CrosfieldTape.SizeOfList[fileSpecList, tapeSpec.density]; IF size > tapeSpec.tapeSize THEN SIGNAL WillNotFit; CrosfieldTape.InitializeTape[tapeHandle: tape, files: fileSpecList, tapeNumber: tapeSpec.tapeNumber, name: tapeSpec.note]; IF rewindOnClose THEN UnixTapeOps.WriteEOT[tape]; UnixTapeOps.CloseDrive[tape, rewindOnClose]; }; AddToCrosfieldTape: PUBLIC PROC[tapeSpec: TapeSpec, fileNumber: NAT, file: IPSpec, inPosition, rewindOnClose: BOOLEAN] = { fileSpecList: CrosfieldTape.FileSpecList _ CrosfieldFromIPSpec[LIST[file]]; fileSpec: CrosfieldTape.FileSpec _ fileSpecList.first; --special case of a general procedure tape: UnixTapeOps.TapeHandle; tapeNotOpen: BOOLEAN _ TRUE; rasterize: FileAction ~ { crosfield: TapesCommon.FileHandle; rasterProc: ConvertToRasters.RasterProc = { --Callback from ConvertToRasters IF tapeNotOpen THEN { --wait to open the tape until rasters start coming tape _ UnixTapeOps.OpenDrive[serverName: tapeSpec.serverName, driveNumber: tapeSpec.drive,density: tapeSpec.density, rewind: FALSE]; crosfield _ CrosfieldTape.AddFileToTape[tape, fileSpec, fileNumber, tapeSpec.tapeNumber, inPosition]; tapeNotOpen _ FALSE; }; [] _ crosfield.newLine[crosfield, raster]; --send one raster to tape }; convert[rasterProc]; --images the InterpressMaster. May take a long time }; DoFileList[files: LIST[file], fileAction: rasterize, reduceResolution: 1, format: crosfield]; IF rewindOnClose THEN UnixTapeOps.WriteEOT[tape]; UnixTapeOps.CloseDrive[tape, rewindOnClose]; }; CrosfieldFromIPSpec: PROC[files: LIST OF IPSpec] RETURNS [fileSpecList: CrosfieldTape.FileSpecList] = { buildFileSpecs: FileAction ~ { fileSpec: CrosfieldTape.FileSpec _ NEW[CrosfieldTape.FileSpecRep _ [ pixelsPerInch: CrosfieldValToPPI[pixelsPerInch], nLines: nLines, nPixels: nPixels, note: name, mapPixel: CrosfieldTape.ByteToCrosfield ]]; fileSpecList _ CONS[fileSpec, fileSpecList]; }; reverseList: PROC[list: CrosfieldTape.FileSpecList] RETURNS [new: CrosfieldTape.FileSpecList] = { FOR l: CrosfieldTape.FileSpecList _ list, l.rest UNTIL l=NIL DO new _ CONS[l.first, new]; ENDLOOP; }; DoFileList[files: files, fileAction: buildFileSpecs, reduceResolution: 1, format: crosfield]; fileSpecList _ reverseList[fileSpecList]; --aesthetics }; WriteCrosfieldTape: PROC [files: LIST OF IPSpec, tapeSpec: TapeSpec] = { tape: UnixTapeOps.TapeHandle _ UnixTapeOps.OpenDrive[tapeSpec.serverName, tapeSpec.drive, tapeSpec.density]; fileSpecList: CrosfieldTape.FileSpecList _ CrosfieldFromIPSpec[files]; handleList, currentFile: TapesCommon.FileHandleList; size: REAL _ 0; rasterize: FileAction ~ { crosfield: TapesCommon.FileHandle _ currentFile.first; rasterProc: ConvertToRasters.RasterProc = { --Callback from ConvertToRasters [] _ crosfield.newLine[crosfield, raster]; --send one raster to tape }; currentFile _ currentFile.rest; convert[rasterProc]; --images the InterpressMaster }; size _ CrosfieldTape.SizeOfList[fileSpecList, tapeSpec.density]; IF size > tapeSpec.tapeSize THEN SIGNAL WillNotFit; handleList _ CrosfieldTape.WriteTape[tapeHandle: tape, files: fileSpecList, tapeNumber: tapeSpec.tapeNumber, name: tapeSpec.note]; currentFile _ handleList; --will be enumerated by rasterize DoFileList[files: files, fileAction: rasterize, reduceResolution: 1, format: crosfield]; UnixTapeOps.WriteEOT[tape]; UnixTapeOps.CloseDrive[tape]; }; WriteOptronicsTape: PROC [files: LIST OF IPSpec, tapeSpec: TapeSpec] = { tape: UnixTapeOps.TapeHandle _ UnixTapeOps.OpenDrive[tapeSpec.serverName, tapeSpec.drive, tapeSpec.density]; fileSpecList: OptronicsTape.FileSpecList; handleList, currentFile: TapesCommon.FileHandleList; size: REAL _ 0; buildFileSpecs: FileAction ~ { fileSpec: OptronicsTape.FileSpec _ NEW[OptronicsTape.FileSpecRep _ [ pixelsPerInch: OptronicsValToPPI[pixelsPerInch], nLines: nLines, nPixels: nPixels, rgbInterleaved: NOT achromatic, maxD: DefaultMaxD[achromatic] ]]; fileSpecList _ CONS[fileSpec, fileSpecList]; }; reverseList: PROC[list: OptronicsTape.FileSpecList] RETURNS [new: OptronicsTape.FileSpecList] = { FOR l: OptronicsTape.FileSpecList _ list, l.rest UNTIL l=NIL DO new _ CONS[l.first, new]; ENDLOOP; }; rasterize: FileAction ~ { fileHandle: TapesCommon.FileHandle _ currentFile.first; rasterProc: ConvertToRasters.RasterProc = { --Callback from ConvertToRasters [] _ fileHandle.newLine[fileHandle, raster]; --send one raster to tape }; currentFile _ currentFile.rest; convert[rasterProc]; --images the InterpressMaster }; DoFileList[files: files, fileAction: buildFileSpecs, reduceResolution: 1, format: optronics]; fileSpecList _ reverseList[fileSpecList]; --aesthetics size _ OptronicsTape.SizeOfList[fileSpecList, tapeSpec.density]; IF size > tapeSpec.tapeSize THEN SIGNAL WillNotFit; handleList _ OptronicsTape.WriteTape[tapeHandle: tape, header: tapeSpec.note, files: fileSpecList]; currentFile _ handleList; --will be enumerated by rasterize DoFileList[files: files, fileAction: rasterize, reduceResolution: 1, format: optronics]; UnixTapeOps.WriteEOT[tape]; UnixTapeOps.CloseDrive[tape]; }; AISInfo: TYPE ~ RECORD [fileName: ROPE, raster: AIS.Raster, fRef: AIS.FRef, wRef: AIS.WRef]; WriteRGBAIS: PROC [files: LIST OF IPSpec, wd: ROPE _ NIL, reduceResolution: REAL _ 0.25, preview: BOOLEAN] ~ { Color: TYPE ~ MACHINE DEPENDENT {red(0), green(1), blue(2), gray(3)}; colorSuffix: ARRAY Color OF ROPE = ["red", "grn", "blu", NIL]; fileAction: FileAction ~ { currentLine: NAT _ 0; ais: ARRAY Color OF AISInfo; rgbToDensity: OptronicsTape.TRCTable _ NIL; SetUp: PROC [c: Color] = { ais[c].raster _ NEW[AIS.RasterPart _ [scanCount: nLines, scanLength: nPixels, scanMode: rd, bitsPerPixel: 8, linesPerBlock: -1, paddingPerBlock: 0]]; IF colorSuffix[c] = NIL THEN ais[c].fileName _ IO.PutFR["%g%g.ais", [rope[wd]], [rope[name]]] ELSE ais[c].fileName _ IO.PutFR["%g%g-%g.ais", [rope[wd]], [rope[name]], [rope[colorSuffix[c]]]]; ais[c].fRef _ AIS.CreateFile[name: ais[c].fileName, raster: ais[c].raster]; ais[c].wRef _ AIS.OpenWindow[f: ais[c].fRef]; }; Done: PROC [c: Color] = { AIS.CloseWindow[w: ais[c].wRef]; AIS.CloseFile[f: ais[c].fRef]; }; rasterProc: ConvertToRasters.RasterProc = { -- Callback from convert length: NAT ~ raster.length; writeLine: PROC[c: Color] = { wRef: AIS.WRef ~ ais[c].wRef; buf: ImagerSample.SampleBuffer ~ raster[ORD[c]]; -- the order better be right! FOR pixel: NAT IN [0..length) DO AIS.WriteSample[w: wRef, value: buf[pixel], line: currentLine, pixel: pixel]; ENDLOOP; }; IF NOT preview THEN OptronicsTape.RGBToDensity[raster, rgbToDensity]; IF achromatic THEN writeLine[gray] ELSE FOR c: Color IN [red..blue] DO writeLine[c]; ENDLOOP; currentLine _ currentLine+1; }; IF achromatic THEN SetUp[gray] ELSE {SetUp[red]; SetUp[green]; SetUp[blue]}; IF NOT preview THEN rgbToDensity _ OptronicsTape.MakeDensityToRGB[255,255, DefaultMaxD[achromatic]]; convert[rasterProc]; -- call to image the Interpress Master IF achromatic THEN Done[gray] ELSE {Done[red]; Done[green]; Done[blue]}; }; DoFileList[files: files, fileAction: fileAction, reduceResolution: reduceResolution, format: optronics] }; WriteCrosfieldAIS: PROC [files: LIST OF IPSpec, wd: ROPE _ NIL, reduceResolution: REAL _ 0.25] ~ { Color: TYPE ~ MACHINE DEPENDENT {cyan(0), magenta(1), yellow(2), black(3)}; colorSuffix: ARRAY Color OF ROPE = ["cyan", "magenta", "yellow", "black"]; fileAction: FileAction ~ { currentLine: NAT _ 0; ais: ARRAY Color OF AISInfo; SetUp: PROC [c: Color] = { ais[c].raster _ NEW[AIS.RasterPart _ [scanCount: nLines, scanLength: nPixels, scanMode: rd, bitsPerPixel: 8, linesPerBlock: -1, paddingPerBlock: 0]]; ais[c].fileName _ IO.PutFR["%g%g-%g.ais", [rope[wd]], [rope[name]], [rope[colorSuffix[c]]]]; ais[c].fRef _ AIS.CreateFile[name: ais[c].fileName, raster: ais[c].raster]; ais[c].wRef _ AIS.OpenWindow[f: ais[c].fRef]; }; Done: PROC [c: Color] = { AIS.CloseWindow[w: ais[c].wRef]; AIS.CloseFile[f: ais[c].fRef]; }; rasterProc: ConvertToRasters.RasterProc = { -- Callback from convert length: NAT ~ raster.length; FOR c: Color IN Color DO wRef: AIS.WRef ~ ais[c].wRef; buf: ImagerSample.SampleBuffer ~ raster[ORD[c]]; -- the order better be right! FOR pixel: NAT IN [0..length) DO AIS.WriteSample[w: wRef, value: buf[pixel], line: currentLine, pixel: pixel]; ENDLOOP; ENDLOOP; currentLine _ currentLine+1; }; SetUp[cyan]; SetUp[magenta]; SetUp[yellow]; SetUp[black]; convert[rasterProc]; -- call to image the Interpress Master Done[cyan]; Done[magenta]; Done[yellow]; Done[black]; }; DoFileList[files: files, fileAction: fileAction, reduceResolution: reduceResolution, format: crosfield]; }; FileAction: TYPE ~ PROC [ name: ROPE, nLines, nPixels: NAT, pixelsPerInch: NAT, convert: PROC [ConvertToRasters.RasterProc], achromatic: BOOLEAN ] RETURNS [stop: BOOL _ FALSE]; metersPerInch: REAL = 0.0254; defaultCC: ColorCorrection _ PrintColorTransformations.SWOPWithGCLinearLStar[]; DoFileList: PROC [files: LIST OF IPSpec, fileAction: FileAction, reduceResolution: REAL _ 1, format: Format] ~ { log: Interpress.LogProc ~ {}; FOR list: LIST OF IPSpec _ files, list.rest UNTIL list=NIL DO ip: IPSpec _ list.first; IF ip=NIL THEN EXIT ELSE { name: ROPE ~ FileNameBase[ip.name]; comp: REAL _ Compensate[ip.pixelsPerInch, format]; --crosfield pixels aren't square nLines: NAT ~ Real.Round[0.5+ip.sDim*ip.pixelsPerInch*reduceResolution*comp]; nPixels: NAT ~ Real.Round[0.5+ip.fDim*ip.pixelsPerInch*reduceResolution]; rasterType: PROC RETURNS[ConvertToRasters.RasterType] = { IF format=crosfield THEN RETURN[cmyk] ELSE IF ip.achromatic THEN RETURN[gray] ELSE RETURN[rgb]; }; cc: PROC RETURNS[ColorCorrection] = { IF format=optronics THEN RETURN[NIL]; IF ip.colorCorrection=NIL THEN RETURN[defaultCC] ELSE RETURN[ip.colorCorrection]; }; rasterSpec: ConvertToRasters.RasterSpec _ [ type: rasterType[], fSize: nPixels, sSize: nLines, surfaceUnitsPerPixel: ip.surfaceUnitsPerPixel, colorCorrection: cc[] ]; convert: PROC [rasterProc: ConvertToRasters.RasterProc] ~ { [] _ ConvertToRasters.FromIP[ip: ip.name, ppiF: ip.pixelsPerInch*reduceResolution, ppiS: ip.pixelsPerInch*reduceResolution*comp, page: ip.page, rasterSpec: rasterSpec, proc: rasterProc, x: ip.fOrg, y: ip.sOrg, w: ip.fDim, h: ip.sDim]; }; MessageWindow.Append[IO.PutFR["Starting on %g, %g lines by %g pixels at %g", IO.rope[name], IO.int[nLines], IO.int[nPixels],IO.time[]], TRUE]; IF fileAction[name: name, nLines: nLines, nPixels: nPixels, pixelsPerInch: ip.pixelsPerInch, convert: convert, achromatic: ip.achromatic].stop THEN EXIT; } ENDLOOP; }; FileNameBase: PROC [name: ROPE] RETURNS [ROPE] ~ { fullFName: ROPE; cp: FS.ComponentPositions; [fullFName: fullFName, cp: cp] _ FS.ExpandName[name]; RETURN[Rope.Substr[fullFName, cp.base.start, cp.base.length]]; }; Compensate: PROC [ppi: REAL, format: Format] RETURNS [yScale: REAL] ~ { IF format=crosfield THEN yScale _ SELECT ppi FROM 300 => 304.8/300, 450 => 406.4/450, 600 => 609.6/600, ENDCASE => ERROR ELSE yScale _ 1; }; OptronicsValToPPI: PROC [val: NAT] RETURNS [ppi: OptronicsTape.PixelsPerInch] ~ { ppi _ SELECT val FROM 63 => ppi63, 127 => ppi127, 254 => ppi254, 508 => ppi508, 1015 => ppi1015, 2030 => ppi2030, ENDCASE => ERROR; }; CrosfieldValToPPI: PROC [val: NAT] RETURNS [ppi: CrosfieldTape.PixelsPerInch] ~ { ppi _ SELECT val FROM 300 => ppi300, 450 => ppi450, 600 => ppi600, ENDCASE => ERROR; }; DefaultMaxD: PROC [achromatic: BOOLEAN] RETURNS [REAL] ~ { RETURN[IF achromatic THEN 2.0 ELSE 1.4]; }; END.  InterpressToTapeImpl.mesa Copyright Σ 1987, 1988 by Xerox Corporation. All rights reserved. Maureen Stone, July 24, 1989 12:35:12 pm PDT Doug Wyatt, April 12, 1988 6:38:07 pm PDT Writes an Interpress master onto in raster form on a tape. Formats supported are Crosfield (for making color separations at Kedie Orent) Common Types and Utilities Convenience procedure Renders the IP file through ImagerMaskCapture and returns the size to within a tolerance specified in inches. The bigger the tolerance the faster this will run. The returned box is guaranteed to be big enough. It's good to leave a little extra space around these images. Converters Writes the files specified on the tape in specified format format. List cannot be longer than 80, a generous limit given the typical file size. As generating tapes and getting them processed takes a long time, it is important to be sure the correct bits are being written. Preview is used for checking position and windowing only. WriteAIS allows the more experience user to examine the CMYK or RGB density bytes produced by the different formats. For both routines, the the AIS files names will be generated by concatinating the wd with the root of the file name in the IPSpec. Typical use is to put all the AIS files in the same working directory. It is inconvenient to examine AIS files at the high resolutions used by the tape formats. reduceResolution reduces the resolution in the IPSpec by the indicated fraction. This routine previews the IPSpec to be sure it is accurately windowed by making three RGB intensity files. The colorCorrection field of the IPSpec is ignored. Uses exactly the same code for rasterization as WriteTape but puts the bytes in 3 or 4 AIS files. This is CMYK negative files for Crosfield format, and RGB density files (will look negative) for Optronics. Use Preview to produce files easily viewed for proofing. Internal Procedures Must include correct FileSpecs for every file that may appear on the tape. Check the size and write the master directory. File numbers start at 1. Files must be added in the order specified in the master directory. tapeSpec should match the one used in the call to InitCrosfieldTape. Check the size and write the master directory. Build the fileSpecs Check the size. *** for more speed, consider using AIS.UnsafeWriteLine here *** *** for more speed, consider using AIS.UnsafeWriteLine here *** call to image the Interpress Master Compensates for the non-square Crosfield pixels Debugging Procs MakeIPSpec: PROC [name: ROPE, page: NAT, pixelsPerInch: NAT, fDim: REAL, sDim: REAL, surfaceUnitsPerPixel: NAT _ 5, colorCorrection: ColorCorrection _ NIL, gray: BOOLEAN _ FALSE] RETURNS [IPSpec] ~ { RETURN[NEW[InterpressToTape.IPSpecRep _ [name: name, page: page, pixelsPerInch: pixelsPerInch, fDim: fDim, sDim: sDim, surfaceUnitsPerPixel: surfaceUnitsPerPixel, colorCorrection: colorCorrection, gray: gray]]]; }; Sizes: TYPE = RECORD[name: ROPE, size: REAL]; ToTape: PROC [name: ROPE, page: NAT, pixelsPerInch: NAT, fDim, sDim: REAL, surfaceUnitsPerPixel: NAT _ 1, drive: NAT _ 1, nBands: NAT _ 1] ~ { ipSpec: IPSpec _NEW[InterpressToTape.IPSpecRep _ [name: Rope.Cat[name, ".ip"], page: page, pixelsPerInch: pixelsPerInch, fDim: fDim, sDim: sDim, surfaceUnitsPerPixel: surfaceUnitsPerPixel, nBands: nBands]]; InterpressToCrosfield[LIST[ipSpec], drive, name, 102]; }; ToAIS: PROC [name: ROPE, page: NAT, pixelsPerInch: NAT, fDim, sDim: REAL, surfaceUnitsPerPixel: NAT _ 1, nBands: NAT _ 1, pixelProc: CrosfieldTape.PixelProc, suffix: ROPE _ NIL] ~ { ipSpec: IPSpec _NEW[InterpressToTape.IPSpecRep _ [name: Rope.Cat[name, ".ip"], page: page, pixelsPerInch: pixelsPerInch, fDim: fDim, sDim: sDim, surfaceUnitsPerPixel: surfaceUnitsPerPixel, nBands: nBands]]; InterpressToAIS[LIST[ipSpec], suffix, pixelProc]; }; Κ˜code•Mark outsideHeaderšœ™KšœB™BKšœ,™,K™)—K™K™K™:K™MK™K™šΟk ˜ Kšœ²œœœT˜‘—K˜KšΠblœœ˜#KšœΗ˜ΞKšœ˜šœ œ˜K˜Kšœœœ˜Kšœœ˜3Kšœ œ˜,Kšœ œ˜*—head™š Οnœ œœœœ˜PK™šœœ˜$Kšœ ˜ Kšœ˜Kšœ˜Kšœ ˜ Kšœ œ˜Kšœ˜K˜—Kšœ˜ K˜—šŸ œ œœœ œ œœ˜sKšœ‘™‘JšœEΟc˜ZJšœF ˜WJšœ2œ˜7šŸœœ˜,J˜'J˜%J˜$J˜%Jšœ)œ˜.Jšœ˜—šœœ2˜7Jšœœ˜$—šœH˜HJšœE˜E—Jšœ-˜3K˜—šŸœ œœœ-œœœœ˜†šœ˜šœ#œ˜DKšœR˜RKšœ3˜3K˜—Kšœœ8˜BKšœœ˜"K˜K˜—šœ˜šœ#œ˜DKšœR˜RKšœœ ˜K˜—Kšœœ8˜BKšœœ˜"K˜K˜—šœ˜šœ˜Kšœ5˜5KšœU˜UK˜—šœ˜Kšœ5˜5KšœU˜UK˜—Kšœœ˜—K˜——K˜KšŸ œ œœ˜!™ K™Kšœ‘™‘šŸ œ œ œœ0˜Všœ˜Kšœ1˜1Kšœ1˜1Kšœ˜—K˜—K˜Kšœ‚Οbœ4‘œΉ™ώK™KšœY™YKšœP™PK™šŸœ œ œœ œœœ ˜_KšœŸ™ŸKšœOœ˜UKšœ˜—šŸœ œ œœœœœ ˜pKšœˆ™ˆšœ˜KšœY˜YKšœ\œ˜cKšœ˜—K˜——™Kš Ÿœœœ œœ,œ˜f™JKšœl˜lKšœF˜FKšœœ˜K™.Kšœ@˜@Kšœœœ ˜3Kšœz˜zKšœœ˜1Kšœ,˜,K˜—Kš Ÿœœœ!œ+œ˜zK™]šœ2Ÿœ™DKšœ?œ˜KKšœ9 %˜^Kšœ˜Kšœ œœ˜šœ˜Kšœ"˜"šœ,  ˜Lšœ œ 2˜HKšœ}œ˜„Kšœe˜eKšœœ˜Kšœ˜—Kšœ+ ˜DK˜—Kšœ 4˜IKšœ˜—KšœœG˜]Kšœœ˜1Kšœ,˜,K˜—š Ÿœœœœ œ/˜gšœ˜šœ#œ˜DKšœR˜RKšœ3˜3K˜—Kšœœ˜,Kšœ˜—šœ œ#œ&˜ašœ.œœ˜?Jšœœ˜Kšœ˜—K˜—Kšœ]˜]Kšœ*  ˜6K˜—š‘œœ œœ ˜HKšœl˜lKšœF˜FKšœ4˜4Kšœœ˜šœ˜Kšœ6˜6šœ,  ˜LKšœ+ ˜DK˜—Kšœ˜Kšœ ˜2Kšœ˜—K™.Kšœ@˜@Kšœœœ ˜3Kšœ‚˜‚Kšœ !˜;KšœX˜XKšœ˜K˜Kšœ˜—š‘œœ œœ ˜HKšœl˜lKšœ)˜)Kšœ4˜4Kšœœ˜šœ˜šœ#œ˜DKšœR˜RKšœœ*˜=K˜—Kšœ œ˜,Kšœ˜—šœ œ#œ&˜ašœ.œœ˜?Jšœœ˜Kšœ˜—K˜—šœ˜Kšœ7˜7šœ,  ˜LKšœ- ˜FK˜—Kšœ˜Kšœ ˜2Kšœ˜—Kšœ™Kšœ]˜]Kšœ*  ˜6K™Kšœ@˜@Kšœœœ ˜3Kšœc˜cKšœ !˜;KšœX˜XKšœ˜K˜Kšœ˜—K˜Kš œ œœ œ œœ œ˜\unitšΠbn œœ œœ œœœœ˜nKšœœœ œ&˜EKš œ œœœœ˜>šœ˜Kšœ œ˜Kšœœœ ˜Kšœ'œ˜+šŸœœ˜Kšœœœ~˜••StartOfExpansionZ[r1: ROPE _ NIL, r2: ROPE _ NIL, r3: ROPE _ NIL, r4: ROPE _ NIL, r5: ROPE _ NIL]šœœœœ˜CKšœ˜—šœœ˜.Kšœ2˜2—K–J[name: ROPE, raster: AIS.Raster, attributeLength: CARDINAL _ 0B (0)]šœœ:˜KK–‘[f: AIS.FRef, firstScan: CARDINAL _ 0B (0), lastScan: CARDINAL _ 177777B (65535), firstPixel: CARDINAL _ 0B (0), lastPixel: CARDINAL _ 177777B (65535)]šœœ˜-Kšœ˜—–E[tapeHandle: TapeOps.TapeHandle, waitForCompletion: BOOL _ FALSE]šŸœœ˜K–[w: AIS.WRef]šœ˜ K–[f: AIS.FRef]šœ˜Kšœ˜—š‘ œ" ˜DKšœœ˜šœ œ˜Kšœœ˜Kšœ(œ ˜NKšœ#œ™?šœœœ ˜ KšœJ˜MKšœ˜—K˜—Kšœœ œ2˜EKšœ œ˜#Kš œœ œ œœ˜:Kšœ˜K˜—Kšœ œ œ)˜LKšœœ œQ˜dKšœ &˜;Kšœ œ œ&˜HKšœ˜—Kšœg˜gKšœ˜K™K™—š‘œœ œœ œœœ ˜bKšœœœ œ,˜KKšœ œœœ*˜Jšœ˜Kšœ œ˜Kšœœœ ˜šŸœœ˜Kšœœœ~˜•–Z[r1: ROPE _ NIL, r2: ROPE _ NIL, r3: ROPE _ NIL, r4: ROPE _ NIL, r5: ROPE _ NIL]šœœ˜)Kšœ2˜2—K–J[name: ROPE, raster: AIS.Raster, attributeLength: CARDINAL _ 0B (0)]šœœ:˜KK–‘[f: AIS.FRef, firstScan: CARDINAL _ 0B (0), lastScan: CARDINAL _ 177777B (65535), firstPixel: CARDINAL _ 0B (0), lastPixel: CARDINAL _ 177777B (65535)]šœœ˜-Kšœ˜—–E[tapeHandle: TapeOps.TapeHandle, waitForCompletion: BOOL _ FALSE]šŸœœ˜K–[w: AIS.WRef]šœ˜ K–[f: AIS.FRef]šœ˜Kšœ˜—š‘ œ" ˜DKšœœ˜šœ œ˜Kšœœ˜Kšœ(œ ˜NK™?šœœœ ˜ KšœJ˜MKšœ˜—Kšœ˜—Kšœ˜K˜—Kšœ9˜9Kšœ &˜;Kšœ5˜5Kšœ˜—Kšœh˜hKšœ˜K™K™—K˜šœ œœ˜Kšœœ˜ Kšœœ˜Kšœœ˜Kšœ œ˜,Jšœ ˜Kšœœœœ˜K˜—Kšœœ ˜KšœO˜Oš Ÿ œœ œœ3œ˜pKšœ˜š œœœœœ˜=K˜š œœœœœ˜Kšœœ˜#Kšœœ*  ˜TKšœœB˜MKšœ œ=˜Išœ œœ!˜9Kšœœœ˜%Kšœœœœ˜'Kšœœ˜K˜—šœœœ˜%Kšœœœœ˜%Kšœœœœ ˜0Kšœœ˜ K˜—˜+Kšœ2˜2Kšœ.˜.Kšœ˜K˜—šœ œ.˜;Kšœ#™#Kšœκ˜κK˜—Kš œœ6œ œœœ œ˜ŽKšœœœ˜™K˜—Kšœ˜—K˜K˜—š Ÿ œœœœœ˜2Kšœ œœ˜+Kšœ!œ˜5Kšœ8˜>K˜K˜—š Ÿ œœœœ œ˜GJ™/šœœ œ˜1Jšœ6œ˜F—Jšœ ˜K˜K˜—š’œœœœ'˜Qšœœ˜Jšœ\œœ˜m—K˜—š’œœœœ'˜Qšœœ˜Jšœ-œœ˜>—K˜—š Ÿ œœœœœ˜:Kšœœ œœ˜(K˜——™K™K™šŸ œœœœœœœœ*œœœœ ™ΘKšœœΙ™ΣK™—Kš œœœœœ™.š’œœœœœœœ œœ ™ŽKšœœ»™ΞJšœœ™6K™—š’œœœœœœœœ2œœ™΅Kšœœ»™ΞJšœœ™1K™——Kšœ˜—…—<¦_?