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.