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]."];