<> <> DIRECTORY Convert, Real, Basics, IO, FS, BasicTime, CommandTool, Commander, DitherAIS, PDFileWriter, AIS, Rope, DisplayMap, Process, FSExtras, MessageWindow; DitheredPDImpl: CEDAR MONITOR IMPORTS Convert, Real, Basics, IO, FS, BasicTime, CommandTool, Rope, Commander, DitherAIS, PDFileWriter, AIS, DisplayMap, Process, FSExtras, MessageWindow = BEGIN ROPE: TYPE ~ Rope.ROPE; FromDitheredAIS: PROC [ditherFilename, pdFilename: ROPE, mag: NAT _ 1] ~ { ais: AIS.FRef _ AIS.OpenFile[ditherFilename]; window: AIS.WRef _ AIS.OpenWindow[ais]; raster: AIS.Raster _ AIS.ReadRaster[ais]; bufferSpace: REF PACKED ARRAY [0..2048) OF [0..255] _ NEW[PACKED ARRAY [0..2048) OF [0..255]]; bits: PACKED ARRAY [0..8000) OF [0..1] _ ALL[0]; pd: PDFileWriter.PDState _ PDFileWriter.Create[ fileName: pdFilename, deviceCode: VAL[7], sResolution: 72, fResolution: 72, imageSSize: raster.scanCount+100, imageFSize: raster.scanLength, bandSSize: 64, copies: 1, leftOverMode: TRUE ]; Pass: PROC [bitNumber: INTEGER, toner: PDFileWriter.Toner] ~ { Deliver: PROC [captureScanLineProc: PDFileWriter.CaptureScanLineProc] ~ TRUSTED { FOR i: NAT IN [0..raster.scanCount) DO jj: CARDINAL _ 0; window.UnsafeReadLine[buffer: [length: SIZE[PACKED ARRAY [0..2048) OF [0..255]], addr: LOOPHOLE[bufferSpace]], line: i]; FOR j: CARDINAL IN [0..raster.scanLength) DO bit: CARDINAL _ Basics.BITAND[Basics.BITSHIFT[bufferSpace[j], -bitNumber], 1]; THROUGH [0..mag) DO bits[jj] _ bit; jj _ jj + 1; ENDLOOP; ENDLOOP; THROUGH [0..mag) DO captureScanLineProc[@bits]; ENDLOOP; ENDLOOP; }; pd.MaskRectangle[sMin: raster.scanCount*mag + 20, fMin: bitNumber*50, sSize: 50, fSize: 50]; pd.MaskRectangle[sMin: raster.scanCount*mag + 20, fMin: bitNumber*50+200, sSize: 50, fSize: 100]; IF bitNumber = 2 THEN pd.MaskRectangle[sMin: raster.scanCount*mag + 20, fMin: 200, sSize: 50, fSize: 50]; pd.ColorSamples[toner: toner, sMin: 0, fMin: 0, sSize: raster.scanCount*mag, fSize: raster.scanLength*mag, deliverProc: Deliver]; }; pd.StartImage[[TRUE, FALSE, FALSE, FALSE], TRUE, FALSE]; Pass[3, black]; pd.EndPage; pd.StartImage[[FALSE, TRUE, FALSE, FALSE], FALSE, FALSE]; Pass[2, cyan]; pd.EndPage; pd.StartImage[[FALSE, FALSE, TRUE, FALSE], FALSE, FALSE]; Pass[1, magenta]; pd.EndPage; pd.StartImage[[FALSE, FALSE, FALSE, TRUE], FALSE, TRUE]; Pass[0, yellow]; pd.EndPage; pd.Close; }; MakeDitheredAIS: ENTRY PROC [filestem: ROPE, log: IO.STREAM] RETURNS [ditherFilename: ROPE] ~ { ENABLE UNWIND => NULL; redFilename: ROPE _ Rope.Concat[filestem, "-red.ais"]; blueFilename: ROPE _ Rope.Concat[filestem, "-blu.ais"]; greenFilename: ROPE _ Rope.Concat[filestem, "-grn.ais"]; localDitherFilename: ROPE _ LocalName[ditherFilename _ Rope.Concat[filestem, "-versatec.ais"]]; fullFName, attachedTo: ROPE _ NIL; created: BasicTime.GMT; ditherCreated: BasicTime.GMT _ BasicTime.nullGMT; [fullFName: fullFName, attachedTo: attachedTo, created: created] _ FS.FileInfo[greenFilename ! FS.Error => {greenFilename _ Rope.Concat[filestem, "-green.ais"]; CONTINUE}]; [fullFName: fullFName, attachedTo: attachedTo, created: created] _ FS.FileInfo[blueFilename ! FS.Error => {blueFilename _ Rope.Concat[filestem, "-blue.ais"]; CONTINUE}]; [fullFName: fullFName, attachedTo: attachedTo, created: created] _ FS.FileInfo[redFilename]; ditherCreated _ FS.FileInfo[ditherFilename ! FS.Error => {ditherFilename _ localDitherFilename; CONTINUE}].created; IF ditherCreated = BasicTime.nullGMT THEN ditherCreated _ FS.FileInfo[ditherFilename ! FS.Error => CONTINUE].created; IF log # NIL THEN log.PutRope[ditherFilename]; IF TRUE OR ditherCreated = BasicTime.nullGMT OR NOT Later[ditherCreated, created] THEN TRUSTED { DitherAIS.Squash[redFilename, greenFilename, blueFilename, ditherFilename, MyMap]; IF log # NIL THEN log.PutRope[" written.\n"]; } ELSE {IF log # NIL THEN log.PutRope[" already exists.\n"]}; }; Later: PROC [a, b: BasicTime.GMT] RETURNS [BOOLEAN] ~ { aa: BasicTime.Unpacked _ BasicTime.Unpack[a]; bb: BasicTime.Unpacked _ BasicTime.Unpack[b]; IF aa.year < bb.year THEN RETURN [FALSE]; IF aa.year > bb.year THEN RETURN [TRUE]; IF aa.month < bb.month THEN RETURN [FALSE]; IF aa.month > bb.month THEN RETURN [TRUE]; IF aa.day < bb.day THEN RETURN [FALSE]; IF aa.day > bb.day THEN RETURN [TRUE]; IF aa.hour < bb.hour THEN RETURN [FALSE]; IF aa.hour > bb.hour THEN RETURN [TRUE]; IF aa.minute < bb.minute THEN RETURN [FALSE]; IF aa.minute > bb.minute THEN RETURN [TRUE]; RETURN [aa.second > bb.second] }; LocalName: PROC [fileName: ROPE] RETURNS [localName: ROPE] ~ { fullName: ROPE; cp: FS.ComponentPositions; [fullName, cp] _ FS.ExpandName[fileName]; localName _ fullName.Substr[cp.base.start, cp.ext.start+cp.ext.length]; }; DitheredPDCommand: Commander.CommandProc ~ { args: CommandTool.ArgumentVector _ CommandTool.Parse[cmd]; filestem: ROPE _ args[1]; mag: INT _ IF args.argc > 2 THEN Convert.IntFromRope[args[2]] ELSE 1; pdFilename: ROPE _ LocalName[Rope.Concat[filestem, ".pd"]]; ditherFilename: ROPE _ NIL; ditherFilename _ MakeDitheredAIS[filestem, cmd.out ! FS.Error => {IF error.group = user THEN {cmd.out.PutRope[error.explanation]; CONTINUE} ELSE REJECT}]; IF ditherFilename # NIL THEN FromDitheredAIS[ditherFilename, pdFilename, mag]; cmd.out.PutRope[pdFilename]; cmd.out.PutRope[" written.\n"]; }; mapTable: DisplayMap.ColorTable; mapPal: DisplayMap.PalTable; redComp: ARRAY DisplayMap.ColorMapSize OF INTEGER; greenComp: ARRAY DisplayMap.ColorMapSize OF INTEGER; blueComp: ARRAY DisplayMap.ColorMapSize OF INTEGER; MyMap: DitherAIS.UserMapProc = { palix _ DisplayMap.GetIndex[r, g, b, mapTable]; re _ r - redComp[palix]; ge _ g - greenComp[palix]; be _ b - blueComp[palix]; }; InitMap: ENTRY PROC ~ { ENABLE UNWIND => NULL; [mapTable, mapPal] _ DisplayMap.Restore["Versatec.tab"]; FOR c: DisplayMap.ColorMapSize IN [0..mapPal.size) DO t: DisplayMap.TripletRec _ mapPal[c]; redComp[c] _ Real.RoundLI[t.r*255]; greenComp[c] _ Real.RoundLI[t.g*255]; blueComp[c] _ Real.RoundLI[t.b*255]; ENDLOOP; }; WatchForNewMap: PROC ~ { createEvent: REF READONLY FSExtras.CreateEvent _ NIL; DO createEvent _ FSExtras.NextCreateEvent[createEvent]; IF Rope.Find[createEvent.fName, "versatec.tab", 0, FALSE] >= 0 THEN { InitMap[]; MessageWindow.Append[" Versatec.tab reloaded", TRUE]; }; ENDLOOP; }; InitMap[]; TRUSTED {Process.Detach[FORK WatchForNewMap[]]}; Commander.Register["DitheredPD", DitheredPDCommand, "Take a set of color ais files and make a dithered PD file for the Color Veratec."]; END.