ColorTrixMiscCommandsImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Bloomenthal, February 17, 1987 11:00:12 pm PST
DIRECTORY AIS, Args, CedarProcess, ColorTrixBasics, ColorTrixDispatch, Commander, FileNames, ImagerPixelMap, ImagerSample, IO, PixelMapOps, Process, Real, Rope;
ColorTrixMiscCommandsImpl: CEDAR PROGRAM
IMPORTS AIS, Args, CedarProcess, ColorTrixBasics, ColorTrixDispatch, FileNames, ImagerPixelMap, ImagerSample, IO, PixelMapOps, Process, Real, Rope
~ BEGIN
ROPE:     TYPE ~ Rope.ROPE;
PixelMap:    TYPE ~ ImagerPixelMap.PixelMap;
DeviceRectangle: TYPE ~ ImagerPixelMap.DeviceRectangle;
PixelProc:    TYPE ~ PROC [x, y: NAT] RETURNS [CARDINAL];
PixelArray:   TYPE ~ REF PixelArrayRep;
Elements are stored by row, then column; that is, pixelArray[y][x].
PixelArrayRep:  TYPE ~ RECORD [
x, y, dx, dy:     NAT ← 0,
element:      SEQUENCE length: NAT OF ImagerSample.SampleBuffer
];
nullPm:    PixelMap ← [0, 0, 0, 0, 0, 0, NIL];
InitializePixelArray: PUBLIC PROC [w: DeviceRectangle] RETURNS [pa: PixelArray] ~ {
pa ← NEW[PixelArrayRep[w.sMin+w.sSize]];
pa.x ← w.fMin;
pa.y ← w.sMin;
pa.dx ← w.fSize;
pa.dy ← w.sSize;
};
CreatePixelArray: PUBLIC PROC [w: DeviceRectangle] RETURNS [pa: PixelArray] ~ {
pa ← InitializePixelArray[w];
FOR y: INT IN [pa.y..pa.y+pa.dy) DO
pa[y] ← ImagerSample.NewBuffer[iSize: 1, jSize: pa.dx];
ENDLOOP;
};
PixelArrayFromPixelMap: PUBLIC PROC [pm: PixelMap] RETURNS [pa: PixelArray] ~ {
pa ← InitializePixelArray[ImagerPixelMap.BoundedWindow[pm]];
FOR y: INT IN [pa.y..pa.y+pa.dy) DO
pa[y] ← ImagerSample.NewBuffer[iSize: 1, jSize: pa.dx];
PixelMapOps.GetF[pm, y, pa.x, pa[y], 0, 0, pa.dx];
ENDLOOP;
};
PixelArrayFromAIS: PUBLIC PROC [fileName: ROPE] RETURNS [pa: PixelArray] ~ {
ais: AIS.FRef ← AIS.OpenFile[fileName];
wRef: AIS.WRef ← AIS.OpenWindow[ais];
w: INTEGER ← wRef.lastPixel-wRef.firstPixel+1;
h: INTEGER ← wRef.lastScan-wRef.firstScan+1;
linePm: PixelMap ← ImagerPixelMap.Create[3, [0, 0, 1, w]];
lineBuf: AIS.Buffer ← [linePm.refRep.words, linePm.refRep.pointer];
pa ← CreatePixelArray[[0, 0, h, w]];
FOR y: NAT IN [0..h) DO
TRUSTED {AIS.UnsafeReadLine[wRef, lineBuf, y]};
PixelMapOps.GetF[linePm, 0, pa.x, pa[y], 0, 0, pa.dx];
Process.CheckForAbort[];
ENDLOOP;
AIS.CloseWindow[wRef];
};
PixelMapFromPixelArray: PUBLIC PROC [pa: PixelArray] RETURNS [pm: PixelMap] ~ {
pm ← ImagerPixelMap.Create[3, [0, 0, pa.dy, pa.dx]];
FOR y: NAT IN [pa.y..pa.y+pa.dy) DO
PixelMapOps.PutF[pixelMap: pm, s: y, f: pa.x, buffer: pa[y], bi: 0, bj: 0, count: pa.dx];
ENDLOOP;
};
PixelArrayFromColorDisplay: PUBLIC PROC RETURNS [PixelArray] ~ {
RETURN[PixelArrayFromPixelMap[ColorTrixBasics.GetColorDisplayPm[]]];
};
PixelArrayFromWindowedColorDisplay: PUBLIC PROC [cmd: Commander.Handle]
RETURNS [PixelArray] ~ {
RETURN[PixelArrayFromPixelMap[ColorTrixDispatch.GetWindowedPm[cmd]]];
};
ShowPixelArray: PUBLIC PROC [pa: PixelArray] ~ {
ColorTrixBasics.ShowPm[PixelMapFromPixelArray[pa]];
};
DoToPixelArray: PUBLIC PROC [pa: PixelArray, proc: PixelProc, pm: PixelMap ← nullPm] ~ {
FOR y: NAT IN [pa.y..pa.y+pa.dy) DO
Process.CheckForAbort[];
FOR x: NAT IN [pa.x..pa.x+pa.dx) DO
pa[y][x] ← proc[x, y];
ENDLOOP;
IF pm # nullPm THEN PixelMapOps.PutF[pm, y, pa.x, pa[y], 0, 0, pa.dx];
ENDLOOP;
};
CtBlur: PUBLIC Commander.CommandProc ~ {
Blur: ColorTrixBasics.ValueProc ~ {
sum: CARDINAL ← 0;
IF x IN [x0..x1] AND y IN [y0..y1]
THEN {
FOR yy: INTEGER IN [y-radius..y+radius] DO
FOR xx: INTEGER IN [x-radius..x+radius] DO
sum ← sum+image[yy][xx];
ENDLOOP;
ENDLOOP;
RETURN[sum/denom];
}
ELSE {
n: NAT ← 0;
FOR yy: INTEGER IN [y-radius..y+radius] DO
IF yy IN [y0..y1] THEN FOR xx: INTEGER IN [x-radius..x+radius] DO
IF xx IN [x0..x1] THEN {sum ← sum+image[yy][xx]; n ← n+1;}
ENDLOOP;
ENDLOOP;
RETURN[IF n = 0 THEN 0 ELSE sum/n];
};
};
image: PixelArray ← PixelArrayFromColorDisplay[];
radius: NAT ~ IF Args.NArgs[cmd] = 1 THEN Args.ArgInt[cmd].int ELSE 1;
denom: NAT ~ (2*radius+1)*(2*radius+1);
x0: INTEGER ~ image.x+radius;
y0: INTEGER ~ image.y+radius;
x1: INTEGER ~ image.x+image.dx-1-radius;
y1: INTEGER ~ image.y+image.dy-1-radius;
ColorTrixBasics.PutFrame[ColorTrixDispatch.GetWindowedPm[cmd], Blur];
};
FullName: PROC [baseName: ROPE] RETURNS [ROPE] ~ {
RETURN[FileNames.StripVersionNumber[FileNames.ResolveRelativePath[baseName]]];
};
CtMatte: PUBLIC Commander.CommandProc ~ {
IF Args.NArgs[cmd] # 2
THEN RETURN[$Failure]
ELSE {
Matte: PixelProc ~ {RETURN[image[y][x]*matte[y][x]/255]};
Overlay: PixelProc ~ {
a: REAL ~ (1.0/255.0)*REAL[matte[y][x]];
RETURN[Real.RoundI[REAL[bgrnd[y][x]]+a*(REAL[image[y][x]]-REAL[bgrnd[y][x]])]];
};
matting: BOOL ← Rope.Equal[cmd.command, "Matte", FALSE];
display: PixelMap ← ColorTrixDispatch.GetWindowedPm[cmd];
bgrnd: PixelArray ← IF matting THEN NIL ELSE PixelArrayFromColorDisplay[];
image: PixelArray ← PixelArrayFromAIS[FullName[Args.GetRope[cmd, 0]]];
matte: PixelArray ← PixelArrayFromAIS[FullName[Args.GetRope[cmd, 1]]];
DoToPixelArray[image, IF matting THEN Matte ELSE Overlay, display];
};
};
CtMedial: PUBLIC Commander.CommandProc ~ {
v0, v1, count: CARDINAL;
SetUp: PROC [x, y: CARDINAL] ~ {
Process.CheckForAbort[];
v0 ← in[y][x];
count ← 0;
};
Test: PROC [x, y, xx, yy: CARDINAL, noCompare: BOOL] ~ INLINE {
val: CARDINAL;
v1 ← in[y][x];
IF v0 # v1
THEN {count ← 0; v0 ← v1}
ELSE IF count < 255 THEN count ← count+1;
val ← MIN[count, out[yy][xx]+1];
IF noCompare
THEN out[y][x] ← val
ELSE IF val < out[y][x] THEN out[y][x] ← val;
};
pm: PixelMap ← ColorTrixDispatch.GetWindowedPm[cmd];
w: ColorTrixBasics.DeviceRectangle ~ ImagerPixelMap.BoundedWindow[pm];
in: PixelArray ~ PixelArrayFromPixelMap[pm];
out: PixelArray ~ CreatePixelArray[w];
x0: CARDINAL ~ w.fMin;
y0: CARDINAL ~ w.sMin;
x1: CARDINAL ~ w.fMin+w.fSize-1;
y1: CARDINAL ~ w.sMin+w.sSize-1;
CedarProcess.SetPriority[background];
FOR x: NAT IN [x0..x1] DO out[y0][x] ← out[y1][x] ← 0; ENDLOOP;
FOR y: NAT IN [y0..y1] DO out[y][x0] ← out[y][x1] ← 0; ENDLOOP;
IO.PutRope[cmd.out, "Doing left to right, "];
FOR y: NAT IN (y0..y1) DO   -- downwards, left to right
SetUp[x0, y];
FOR x: NAT IN (x0..x1) DO
Test[x, y, x, y-1, TRUE];
ENDLOOP;
ENDLOOP;
IO.PutRope[cmd.out, "right to left, "];
FOR y: NAT DECREASING IN (y0..y1) DO  -- upwards, right to left
SetUp[x1, y];
FOR x: NAT DECREASING IN (x0..x1) DO
Test[x, y, x, y+1, FALSE];
ENDLOOP;
ENDLOOP;
IO.PutRope[cmd.out, "up to down, "];
FOR x: NAT IN (x0..x1) DO   -- rightwards, up to down
SetUp[x, y0];
FOR y: NAT IN (y0..y1) DO
Test[x, y, x-1, y, FALSE];
ENDLOOP;
ENDLOOP;
IO.PutRope[cmd.out, "and down to up\n"];
FOR x: NAT DECREASING IN (x0..x1) DO  -- leftwards, down to up
SetUp[x, y1];
FOR y: NAT DECREASING IN (y0..y1) DO
Test[x, y, x+1, y, FALSE];
ENDLOOP;
ENDLOOP;
ShowPixelArray[out];
};
Start Code
ColorTrixDispatch.RegisterCtOp["Medial", CtMedial,
"Ct Medial: pixel values increase towards medial axis of regions."];
ColorTrixDispatch.RegisterCtOp["Matte", CtMatte, "Ct Matte <image ais> <matte ais>."];
ColorTrixDispatch.RegisterCtOp["Overlay", CtMatte, "Ct Overlay <image ais> <matte ais>."];
ColorTrixDispatch.RegisterCtOp["Blur", CtBlur, "Ct Blur [radius, default = 1]."];
END.