DitheredPDImpl.mesa
Michael Plass, April 20, 1984 2:53:22 pm PST
Last Edited by: Beach, July 9, 1984 4:39:08 pm PDT
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*mag+100,
imageFSize: MAX[raster.scanLength*mag, 500],
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: ROPENIL;
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: INTIF args.argc > 2 THEN Convert.IntFromRope[args[2]] ELSE 1;
pdFilename: ROPE ← LocalName[Rope.Concat[filestem, ".pd"]];
ditherFilename: ROPENIL;
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, "DitheredPD fileStem {mag} -- Take a set of color AIS files and make a dithered PD file for the Color Veratec."];
END.