~
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: BOOLEAN ← TRUE;
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.