DynamicBitsImpl.mesa
Copyright (C) 1984, 1985, Xerox Corporation. All rights reserved.
Michael Plass, November 6, 1985 11:25:49 am PST
DIRECTORY Basics, DynamicBits, ImagerPixelMap, ImagerSample, PixelMapOps, PrincOps, PrincOpsUtils, Random;
DynamicBitsImpl: CEDAR PROGRAM
IMPORTS ImagerPixelMap, ImagerSample, PixelMapOps, PrincOpsUtils, Basics, Random
EXPORTS DynamicBits
~ BEGIN OPEN DynamicBits;
SampleBuffer: TYPE ~ ImagerSample.SampleBuffer;
ModelParameterFault: PUBLIC ERROR [data: REF] ~ CODE;
MakePixelMapFromBits: PUBLIC PROC [
bitPointer: LONG POINTER,
bitsPerLine: NAT,
window: DeviceRectangle,
scratch: REF ImagerPixelMap.PixelMapRep
] RETURNS [pixelMap: PixelMap] = TRUSTED {
bbTableSpace: PrincOps.BBTableSpace;
bb: PrincOps.BBptr ~ PrincOpsUtils.AlignedBBTable[@bbTableSpace];
pixelMap ← scratch.Reshape[0, window];
bb^ ← [
dst: [word: pixelMap.refRep.pointer, bit: 0],
dstBpl: pixelMap.refRep.rast*Basics.bitsPerWord,
src: [word: bitPointer, bit: 0],
srcDesc: [srcBpl[bitsPerLine]],
height: window.sSize,
width: window.fSize,
flags: [direction: forward, disjoint: TRUE, disjointItems: TRUE, gray: FALSE, srcFunc: null, dstFunc: null]
];
PrincOpsUtils.BITBLT[bb];
};
CreatePrinterModel: PUBLIC PROC [neighborhood: DeviceRectangle, printerModel: PrinterModel, kernel: PixelMap] RETURNS [model: Model] ~ {
model ← FindClass[neighborhood, kernel.Window].CreatePrinterModel[neighborhood, printerModel, kernel];
};
RotatePixelMap: PROC [pm: PixelMap, scratch: REF ImagerPixelMap.PixelMapRep ← NIL] RETURNS [PixelMap] ~ {
Rotates counterclockwise about the point s=1/2, f=1/2;
RETURN [ImagerPixelMap.ShiftMap[ImagerPixelMap.Rotate[pm, scratch], 0, 1]];
};
RotateModel: PUBLIC PROC [model: Model] RETURNS [new: Model] ~ {
kernel: PixelMap ~ RotatePixelMap[model.kernel];
t: PixelMap ~ ImagerPixelMap.Create[0, model.neighborhood];
neighborhood: DeviceRectangle ~ ImagerPixelMap.Window[RotatePixelMap[t]];
action: PROC [oldPrinterModel: PrinterModel] ~ {
printerModel: PROC [bitmap: PixelMap, encoding: CARDINAL] RETURNS [i: Intensity, n: NoisePenalty] ~ {
b: PixelMap ~ RotatePixelMap[bitmap, t.refRep];
w: DeviceRectangle ~ ImagerPixelMap.Window[b];
e: CARDINAL ← 0;
FOR s: INTEGER IN [w.sMin..w.sMin+w.sSize) DO
FOR f: INTEGER IN [w.fMin..w.fMin+w.fSize) DO
e ← 2*e + ImagerPixelMap.GetPixel[b, s, f];
ENDLOOP;
ENDLOOP;
[i,n] ← oldPrinterModel[b, e];
};
new ← CreatePrinterModel[neighborhood, printerModel, kernel];
};
FindClass[model.neighborhood, model.kernel.Window].DoWithPrinterModel[model, action];
};
Convolve: PUBLIC PROC [pixelMap: PixelMap, kernel: Kernel, unitIntensity: CARDINAL] ~ {
FindClass[[0,0,1,1], kernel.Window].Convolve[pixelMap, kernel, unitIntensity];
};
Run: TYPE ~ RECORD [s: INTEGER, f: INTEGER, count: NAT];
GetRow: PROC [row: SampleBuffer, pixelMap: PixelMap, run: Run] ~ INLINE {
PixelMapOps.GetF[pixelMap: pixelMap, s: run.s, f: run.f, buffer: row, bi: 0, bj: 0, count: run.count];
};
PutRow: PROC [row: SampleBuffer, pixelMap: PixelMap, run: Run] ~ INLINE {
PixelMapOps.PutF[pixelMap: pixelMap, s: run.s, f: run.f, buffer: row, bi: 0, bj: 0, count: run.count];
};
KernelWeight: PUBLIC PROC [kernel: Kernel] RETURNS [weight: INT ← 0] ~ {
w: DeviceRectangle ← kernel.BoundedWindow;
row: SampleBuffer ← ImagerSample.NewBuffer[iSize: 1, jSize: w.fSize];
FOR s: INTEGER IN [w.sMin..w.sMin+w.sSize) DO
GetRow[row, kernel, [s, w.fMin, w.fSize]];
FOR j: NAT IN [0..w.fSize) DO
weight ← weight + LOOPHOLE[row[j], INTEGER];
ENDLOOP;
ENDLOOP;
};
AddBorder: PUBLIC PROC [pixelMap: PixelMap, borderSize: NAT, borderValue: CARDINAL] RETURNS [bordered: PixelMap] ~ {
w: DeviceRectangle ← pixelMap.Window;
w.sMin ← w.sMin - borderSize;
w.fMin ← w.fMin - borderSize;
w.sSize ← w.sSize + 2*borderSize;
w.fSize ← w.fSize + 2*borderSize;
bordered ← ImagerPixelMap.Create[pixelMap.refRep.lgBitsPerPixel, w];
bordered.Fill[w, borderValue];
bordered.Transfer[pixelMap];
};
ErrorOf: PUBLIC PROC [gray: PixelMap, bitmap: PixelMap, model: Model] RETURNS [INT] ~ {
t: PixelMap ← ApplyModel[bitmap, model];
Convolve[t, model.kernel, 255];
RETURN [AbsDiff[gray, t]];
};
debug: BOOLEANTRUE;
ApplyModel: PUBLIC PROC [bitmap: PixelMap, model: Model] RETURNS [PixelMap] ~ {
RETURN [FindClass[model.neighborhood, model.kernel.Window].ApplyModel[bitmap, model]];
};
AbsDiff: PUBLIC PROC [a, b: PixelMap] RETURNS [error: INT ← 0] ~ {
w: DeviceRectangle ← ImagerPixelMap.Intersect[a.BoundedWindow, b.BoundedWindow];
ar: SampleBuffer ← ImagerSample.NewBuffer[iSize: 1, jSize: w.fSize];
br: SampleBuffer ← ImagerSample.NewBuffer[iSize: 1, jSize: w.fSize];
FOR s: INTEGER IN [w.sMin..w.sMin+w.sSize) DO
GetRow[ar, a, [s, w.fMin, w.fSize]];
GetRow[br, b, [s, w.fMin, w.fSize]];
FOR j: NAT IN [0..w.fSize) DO
error ← error + ABS[LOOPHOLE[ar[j], INTEGER]-LOOPHOLE[br[j], INTEGER]];
ENDLOOP;
ENDLOOP;
};
RandomDither: PUBLIC PROC [gray: PixelMap] RETURNS [bitmap: PixelMap] ~ {
w: DeviceRectangle ← gray.Window;
row: SampleBuffer ← ImagerSample.NewBuffer[iSize: 1, jSize: w.fSize];
maxPixel: CARDINAL ← Basics.BITSHIFT[1, Basics.BITSHIFT[1, gray.refRep.lgBitsPerPixel]]-1;
random: Random.RandomStream ← Random.Create[seed: 283745734];
bitmap ← ImagerPixelMap.Create[0, w];
FOR s: INTEGER IN [w.sMin..w.sMin+w.sSize) DO
GetRow[row, gray, [s, w.fMin, w.fSize]];
FOR j: NAT IN [0..w.fSize) DO
row[j] ← IF Random.ChooseInt[random, 1, maxPixel] > row[j] THEN 0 ELSE 1;
ENDLOOP;
PutRow[row, bitmap, [s, w.fMin, w.fSize]];
ENDLOOP;
};
FindFixedBits: PUBLIC PROC [gray: PixelMap, radius: NAT] RETURNS [fixedBits: PixelMap] ~ {
w: DeviceRectangle ← gray.Window;
row: SampleBuffer ← ImagerSample.NewBuffer[iSize: 1, jSize: w.fSize];
maxPixel: CARDINAL ← Basics.BITSHIFT[1, Basics.BITSHIFT[1, gray.refRep.lgBitsPerPixel]]-1;
zeros: PixelMap ← ImagerPixelMap.Create[0, w];
ones: PixelMap ← ImagerPixelMap.Create[0, w];
FOR s: INTEGER IN [w.sMin..w.sMin+w.sSize) DO
GetRow[row, gray, [s, w.fMin, w.fSize]];
FOR j: NAT IN [0..w.fSize) DO
pix: CARDINAL ← row[j];
row[j] ← IF pix = 255 THEN 1 ELSE 0;
ENDLOOP;
PutRow[row, ones, [s, w.fMin, w.fSize]];
ENDLOOP;
FOR s: INTEGER IN [w.sMin..w.sMin+w.sSize) DO
GetRow[row, gray, [s, w.fMin, w.fSize]];
FOR j: NAT IN [0..w.fSize) DO
pix: CARDINAL ← row[j];
row[j] ← IF pix = 0 THEN 1 ELSE 0;
ENDLOOP;
PutRow[row, zeros, [s, w.fMin, w.fSize]];
ENDLOOP;
FOR i: NAT IN [0..radius) DO
ones.Transfer[ones.ShiftMap[-1, 0], [and, null]];
ones.Transfer[ones.ShiftMap[1, 0], [and, null]];
ones.Transfer[ones.ShiftMap[0, 1], [and, null]];
ones.Transfer[ones.ShiftMap[0, -1], [and, null]];
ENDLOOP;
FOR i: NAT IN [0..radius) DO
zeros.Transfer[zeros.ShiftMap[-1, 0], [and, null]];
zeros.Transfer[zeros.ShiftMap[1, 0], [and, null]];
zeros.Transfer[zeros.ShiftMap[0, 1], [and, null]];
zeros.Transfer[zeros.ShiftMap[0, -1], [and, null]];
ENDLOOP;
fixedBits ← zeros;
fixedBits.Transfer[ones, [or, null]];
};
TuneSwath: PUBLIC PROC [gray: PixelMap, bitmap: PixelMap, fixedBits: PixelMap, swath: DeviceRectangle, model: Model, scratch: REF] RETURNS [newScratch: REF] ~ {
newScratch ← FindClass[model.neighborhood, model.kernel.Window, swath.fSize].TuneSwath[gray, bitmap, fixedBits, swath, model, scratch];
};
registeredClasses: LIST OF Class ← NIL;
FindClass: PROC [neighborhood, kernelBounds: DeviceRectangle, swathSize: NAT ← 1] RETURNS [Class] ~ {
sModelRadius: NAT ← -neighborhood.sMin;
fModelRadius: NAT ← -neighborhood.fMin;
sKernelRadius: NAT ← -kernelBounds.sMin;
fKernelRadius: NAT ← -kernelBounds.fMin;
FOR p: LIST OF Class ← registeredClasses, p.rest UNTIL p=NIL DO
IF p.first.sKernelRadius = sKernelRadius
AND p.first.fKernelRadius = fKernelRadius
AND p.first.sModelRadius = sModelRadius
AND p.first.fModelRadius = fModelRadius
AND p.first.swathSize = swathSize
THEN RETURN [p.first]
ENDLOOP;
ModelParameterFault[$UnsupportedParameterCombination];
};
RegisterImpl: PUBLIC PROC [class: Class] ~ {
registeredClasses ← CONS[class, registeredClasses];
};
END.