DynamicBitsXXXImpl.meta
Copyright (C) 1984, 1985, Xerox Corporation. All rights reserved.
Michael Plass, November 6, 1985 9:52:38 am PST
PARAMETERS sKernelRadius, fKernelRadius, sModelRadius, fModelRadius, swathSize
DIRECTORY DynamicBits, Basics, ImagerPixelMap, ImagerSample, PixelMapOps;
ModuleName[];: CEDAR PROGRAM
IMPORTS Basics, ImagerPixelMap, ImagerSample, PixelMapOps, DynamicBits
~ BEGIN OPEN DynamicBits;
 {
sMinKernel: INT ← -sKernelRadius;
sSizeKernel: INT ← 2*sKernelRadius+1;
sMaxKernel: INT ← sMinKernel + sSizeKernel;
fMinKernel: INT ← -fKernelRadius;
fSizeKernel: INT ← 2*fKernelRadius+1;
fMaxKernel: INT ← fMinKernel + fSizeKernel;
sMinModel: INT ← -sModelRadius;
sSizeModel: INT ← 2*sModelRadius+1;
sMaxModel: INT ← sMinModel + sSizeModel;
fMinModel: INT ← -fModelRadius;
fSizeModel: INT ← 2*fModelRadius+1;
fMaxModel: INT ← fMinModel + fSizeModel;
sTotalRadius: INT ← sKernelRadius+sModelRadius;
modelIndexBits: INT ← sSizeModel*fSizeModel;
modelDataSize: INT ← TwoToThe[modelIndexBits];
twoToTheModelFSize: INT ← TwoToThe[fSizeModel];
SF: TYPE ~ RECORD [s, f: INT];
PackBits: PROC [list: LIST OF SF] ~ {
IF list = NIL THEN {0}
ELSE IF list.rest = NIL THEN {
s: INT ← list.first.s;
f: INT ← list.first.f;
bit[&s][&f]
}
ELSE {
s: INT ← list.first.s;
f: INT ← list.first.f;
( PackBits[list.rest]; *2 + bit[&s][&f])
};
};

KernelArray: TYPE ~ ARRAY [&sMinKernel..&sMaxKernel) OF ARRAY [&fMinKernel..&fMaxKernel) OF INTEGER;
SampleBuffer: TYPE ~ ImagerSample.SampleBuffer;
PixelRow: TYPE ~ RECORD[sOrigin, fOrigin: INTEGER, sample: SampleBuffer];
CreatePixelRow: PROC [s, f: INTEGER, size: NAT] RETURNS [PixelRow] ~ {
buffer: SampleBuffer ~ ImagerSample.NewBuffer[iSize: 1, jSize: size];
RETURN [[sOrigin: s, fOrigin: f, sample: buffer]]
};
CopyPixelRow: PROC [old: PixelRow] RETURNS [PixelRow] ~ {
new: PixelRow ~ CreatePixelRow[old.sOrigin, old.fOrigin, old.sample.jSize];
PixelMapOps.CopySamples[buffer: new.sample, bi: 0, bj: 0, count: old.sample.jSize, source: old.sample, si: 0, sj: 0];
RETURN [new]
};
ModelData: TYPE ~ REF ModelDataRep;
ModelDataRep: TYPE ~ ARRAY [0..&modelDataSize) OF REF ModelDataItem;
ModelDataItem: TYPE ~ RECORD [
intensity: Intensity,
noisePenalty: NoisePenalty,
a: KernelArray
];
ModelParameterFault: PUBLIC ERROR [data: REF] ~ CODE;
neighborhoodBounds: DeviceRectangle ~ [&sMinModel, &fMinModel, &sSizeModel, &fSizeModel];
CheckNeighborhood: PROC [neighborhood: DeviceRectangle] ~ {
IF neighborhood # neighborhoodBounds THEN ModelParameterFault[$neighborhood];
};
kernelBounds: DeviceRectangle ~ [&sMinKernel, &fMinKernel, &sSizeKernel, &fSizeKernel];
CheckKernel: PROC [bounds: DeviceRectangle] ~ {
IF bounds # kernelBounds THEN ModelParameterFault[$kernel];
};
ArrayFromKernel: PROC [kernel: Kernel] RETURNS [kernelArray: KernelArray] ~ {
CheckKernel[kernel.Window];
FOR s: INTEGER IN [&sMinKernel..&sMaxKernel) DO
FOR f: INTEGER IN [&fMinKernel..&fMaxKernel) DO
kernelArray[s][f] ← LOOPHOLE[kernel.GetPixel[s, f], INTEGER];
ENDLOOP;
ENDLOOP;
};
CreatePrinterModel: PROC [neighborhood: DeviceRectangle, printerModel: PrinterModel, kernel: PixelMap] RETURNS [model: Model] ~ {
bitmap: PixelMap ← ImagerPixelMap.Create[0, neighborhood];
data: ModelData ← NEW[ModelDataRep];
kernelArray: KernelArray ← ArrayFromKernel[kernel];
CheckNeighborhood[neighborhood];
model ← NEW[ModelRep];
FOR encoding: CARDINAL IN [0..&modelDataSize) DO
intensity: Intensity;
noisePenalty: NoisePenalty;
scaledArray: KernelArray;
TRUSTED {
t: CARDINAL ← Basics.BITSHIFT[encoding, Basics.bitsPerWord-&modelIndexBits];
bitmap ← MakePixelMapFromBits[@t, &fSizeModel, neighborhoodBounds, bitmap.refRep];
};
[intensity, noisePenalty] ← printerModel[bitmap, encoding];
FOR s: INTEGER IN [&sMinKernel..&sMaxKernel) DO
FOR f: INTEGER IN [&fMinKernel..&fMaxKernel) DO
k: INTEGER ← kernelArray[s][f];
scaledArray[s][f] ←
IF k>=0 THEN (Basics.LongMult[k, intensity]+127)/255
ELSE -((Basics.LongMult[-k, intensity]+127)/255);
ENDLOOP;
ENDLOOP;
data[encoding] ← NEW[ModelDataItem ← [intensity, noisePenalty, scaledArray]];
ENDLOOP;
model.neighborhood ← neighborhood;
model.kernel ← kernel.Copy;
model.data ← data;
};
DoWithPrinterModel: PROC [model: Model, action: PROC[PrinterModel]] ~ {
data: ModelData ~ NARROW[model.data];
printerModel: PROC [bitmap: PixelMap, encoding: CARDINAL] RETURNS [Intensity, NoisePenalty] ~ {
item: REF ModelDataItem ~ data^[encoding];
RETURN [item.intensity, item.noisePenalty];
};
action[printerModel];
};
StorePixelRow: PROC [p: PixelRow, pixelMap: PixelMap] ~ {
fMin: INTEGERMAX[p.fOrigin, pixelMap.fOrigin+pixelMap.fMin];
fMax: INTEGERMIN[p.fOrigin+p.sample.jSize, pixelMap.fOrigin+pixelMap.fMin+pixelMap.fSize];
IF fMax<=fMin THEN RETURN;
PixelMapOps.PutF[pixelMap: pixelMap, s: p.sOrigin, f: fMin, buffer: p.sample, bi: 0, bj: fMin-p.fOrigin, count: fMax-fMin];
};
Load: PROC [p: PixelRow, pixelMap: PixelMap] ~ {
Takes care of boundary conditions
fMin: INTEGERMAX[p.fOrigin, pixelMap.fOrigin+pixelMap.fMin];
fMax: INTEGERMIN[p.fOrigin+p.sample.jSize, pixelMap.fOrigin+pixelMap.fMin+pixelMap.fSize];
sMin: INTEGERMIN[MAX[p.sOrigin, pixelMap.sOrigin+pixelMap.sMin], pixelMap.sOrigin+pixelMap.sMin+pixelMap.sSize-1];
IF fMax<=fMin THEN {PixelMapOps.ClearSamples[buffer: p.sample, count: p.sample.jSize]; RETURN};
PixelMapOps.GetF[pixelMap: pixelMap, s: sMin, f: fMin, buffer: p.sample, bi: 0, bj: fMin-p.fOrigin, count: fMax-fMin];
FOR i: INTEGER IN [0..fMin-p.fOrigin) DO
p.sample[i] ← p.sample[fMin-p.fOrigin];
ENDLOOP;
FOR i: INTEGER IN [fMax-p.fOrigin..p.sample.jSize) DO
p.sample[i] ← p.sample[fMax-1-p.fOrigin];
ENDLOOP;
};
Convolve: PROC [pixelMap: PixelMap, kernel: Kernel, unitIntensity: CARDINAL] ~ {
bounds: DeviceRectangle ← pixelMap.BoundedWindow;
kernelArray: KernelArray ← ArrayFromKernel[kernel];
p: ARRAY [&sMinKernel..&sMaxKernel) OF PixelRow ← CreatePixelRows[];
CreatePixelRows: PROC RETURNS[p: ARRAY[&sMinKernel..&sMaxKernel) OF PixelRow]~{
FOR i: INTEGER IN [&sMinKernel..&sMaxKernel) DO
p[i] ← CreatePixelRow[bounds.sMin+i, bounds.fMin+&fMinKernel, bounds.fSize+&fSizeKernel-1];
ENDLOOP;
};
q: PixelRow ← CopyPixelRow[p[0]];
kernelMag: INTEGER ← KernelWeight[kernel];
halfUnit: CARDINAL ← unitIntensity/2;
maxMag: INT ← Basics.LongMult[ABS[kernelMag], INT[unitIntensity]]+halfUnit;
Cd: PROC [i: INTEGER] RETURNS [CARDINAL] ~ INLINE {RETURN [LOOPHOLE[i]]};
short: BOOLEAN ← maxMag < CARDINAL.LAST;
FOR ss: INT IN [&sMinKernel..&sMaxKernel) DO
FOR ff: INT IN [&fMinKernel..&fMaxKernel) DO
short ← short AND kernelArray[ss][ff] >= 0;
ENDLOOP;
ENDLOOP;
FOR i: INTEGER IN [&sMinKernel..&sMaxKernel) DO Load[p[i], pixelMap] ENDLOOP;
THROUGH [0..bounds.sSize) DO
IF short THEN {
Use 16-bit arithemetic for greater speed.
FOR f: NAT IN [-&fMinKernel..bounds.fSize-&fMinKernel) DO
pix: CARDINAL ← 
FOR ss: INT IN [sMinKernel..sMaxKernel) DO
FOR ff: INT IN [fMinKernel..fMaxKernel) DO
p[-&ss].sample[f-&ff]*Cd[kernelArray[&ss][&ff]] + 
ENDLOOP;
ENDLOOP;
 0;
q.sample[f] ← (pix+halfUnit)/unitIntensity;
ENDLOOP;
}
ELSE {
FOR f: NAT IN [-&fMinKernel..bounds.fSize-&fMinKernel) DO
pix: INT ← 0;
FOR ss: INT IN [&sMinKernel..&sMaxKernel) DO
FOR ff: INT IN [&fMinKernel..&fMaxKernel) DO
pix ← pix + p[-ss].sample[f-ff]*INT[kernelArray[ss][ff]];
ENDLOOP;
ENDLOOP;
q.sample[f] ← (pix+halfUnit)/unitIntensity;
ENDLOOP;
};
StorePixelRow[q, pixelMap];
{t: PixelRow ← p[&sMinKernel]; 
FOR i: INT IN (sMinKernel..sMaxKernel) DO
ii: INT ← i-1;
p[&ii] ← p[&i]; 
ENDLOOP;
p[&sMaxKernel-1] ← t};
p[&sMaxKernel-1].sOrigin ← p[&sMaxKernel-1].sOrigin + (&sMaxKernel-&sMinKernel);
Load[p[&sMaxKernel-1], pixelMap];
q.sOrigin ← p[0].sOrigin;
ENDLOOP;
};
ApplyModel: PROC [bitmap: PixelMap, model: Model] RETURNS [PixelMap] ~ {
w: DeviceRectangle ← bitmap.Window;
gray: PixelMap ← ImagerPixelMap.Create[3, w];
bitRow: PixelRow ← CreatePixelRow[w.sMin+&sMinModel, w.fMin+&fMinModel, w.fSize+&fSizeModel];
indexRow: PixelRow ← CreatePixelRow[w.sMin, w.fMin, w.fSize];
destRow: PixelRow ← CopyPixelRow[indexRow];
data: ModelData ← NARROW[model.data];
MergeBits: PROC ~ {
FOR f: NAT IN [0..indexRow.sample.jSize) DO
k: CARDINAL ← 0;
FOR ff: NAT IN [f..f+&fSizeModel) DO
k ← k*2+bitRow.sample[ff];
ENDLOOP;
indexRow.sample[f] ← (indexRow.sample[f] * &twoToTheModelFSize + k) MOD &modelDataSize;
ENDLOOP;
};
PixelMapOps.ClearSamples[buffer: bitRow.sample, count: bitRow.sample.jSize];
PixelMapOps.ClearSamples[buffer: indexRow.sample, count: indexRow.sample.jSize];
PixelMapOps.ClearSamples[buffer: destRow.sample, count: destRow.sample.jSize];
FOR i: NAT IN [0..&sSizeModel) DO
Load[bitRow, bitmap];
MergeBits[];
bitRow.sOrigin ← bitRow.sOrigin + 1;
ENDLOOP;
FOR s: NAT IN [0..w.sSize) DO
FOR f: NAT IN [0..destRow.sample.jSize) DO
destRow.sample[f] ← data[indexRow.sample[f]].intensity;
ENDLOOP;
StorePixelRow[destRow, gray];
destRow.sOrigin ← destRow.sOrigin + 1;
Load[bitRow, bitmap];
MergeBits[];
bitRow.sOrigin ← bitRow.sOrigin + 1;
ENDLOOP;
RETURN [gray]
};
TuneSwath: PROC [gray: PixelMap, bitmap: PixelMap, fixedBits: PixelMap, swath: DeviceRectangle, model: Model, scratch: REF] RETURNS [newScratch: REF] ~ {
{GenTuneSwath: PROC = BEGIN
Area 0 is the portion of the local swatch over which we must calculate the penalty.
sMin0: INT ~ 0;
sMax0: INT ~ 1;
fMin0: INT ~ -(fModelRadius+fKernelRadius);
fMax0: INT ~ fModelRadius+fKernelRadius+swathSize;
Area 1 is the area over which we must calculate the model indices.
sMin1: INT ~ sMin0-sKernelRadius;
sMax1: INT ~ sMax0+sKernelRadius;
fMin1: INT ~ fMin0-fKernelRadius;
fMax1: INT ~ fMax0+fKernelRadius;
Area 2 is the portion of the bitmap we need locally
sMin2: INT ~ sMin1-sModelRadius;
sMax2: INT ~ sMax1+sModelRadius;
fMin2: INT ~ fMin1-fModelRadius;
fMax2: INT ~ fMax1+fModelRadius;
twoToTheSwathSize: INT ← TwoToThe[swathSize];
twoToTheSwathSizeTimesOneLessThanSSize: INT ← TwoToThe[swathSize*(sMax2-sMin2-1)];

Make sure the swath has the right fSize
xxx: [0..0] ← swath.fSize-&swathSize;
sOrigin and fOrigin give the position of the origin of the local swatch in the bitmap coordinate system.
sOrigin: INTEGER ← swath.sMin-1-&sTotalRadius;
fOrigin: INTEGER ← swath.fMin;
pixelRow: PixelRow ← CreatePixelRow[sOrigin, fOrigin+&fMin2, &fMax2-&fMin2];
swathRow: PixelRow ← CreatePixelRow[sOrigin, fOrigin, &swathSize];
bit: ARRAY [&sMin2..&sMax2) OF ARRAY [&fMin2..&fMax2) OF [0..1];
The current bits from the bitmap within the swatch
index: ARRAY [&sMin1..&sMax1) OF ARRAY [&fMin1..&fMax1) OF [0..&modelDataSize);
The current bits, packed up into indices into the model array
fixed: ARRAY [&sMin2..&sMax2) OF ARRAY [0..&swathSize) OF [0..1];
A local copy of a piece of fixedBits
target: ARRAY [&fMin0..&fMax0) OF INTEGER;
A local copy of a piece of gray
trial: ARRAY [&fMin0..&fMax0) OF INTEGER;
The partially computed approximation to the gray
modelData: ModelData ← NARROW[model.data];
nonFixedBitCount: NAT ← 0;
SF: TYPE ~ RECORD [s: [&sMin2..&sMax2), f: [0..&swathSize)];
nonFixedBitIndex: ARRAY [0..(&sMax2-&sMin2)*&swathSize) OF SF;
questionBits: [0..&twoToTheSwathSize);
The bits that need to be determined for a given context.
contextBits: [0..&twoToTheSwathSizeTimesOneLessThanSSize);
The context bits in the swath.
prevContextBits: [0..&twoToTheSwathSizeTimesOneLessThanSSize);
The context bits for the previous subproblem.
SubproblemSolution: TYPE ~ RECORD [
setting: [0..&twoToTheSwathSize),
The setting of questionBits that achieves the lowest total penalty for the swath so far.
minErrHighHalf: [0..CARDINAL.LAST/&twoToTheSwathSize],
minErrLowHalf: CARDINAL
The lowest total penalty for the swath so far.
Packed so the whole thing fits in two words, since there are a lot of them.
];
MakeSubproblemSolution: PROC [setting: [0..&twoToTheSwathSize), minErr: INT] RETURNS [SubproblemSolution] ~ INLINE BEGIN
long: Basics.LongNumber ← [li[minErr]];
RETURN [[setting: setting, minErrHighHalf: long.highbits, minErrLowHalf: long.lowbits]]
END;
MinErr: PROC [s: SubproblemSolution] RETURNS [INT] ~ INLINE BEGIN
long: Basics.LongNumber ← [num[lowbits: s.minErrLowHalf, highbits: s.minErrHighHalf]];
RETURN [long.li]
END;
PerSwatchTable: TYPE ~ ARRAY [0..&twoToTheSwathSizeTimesOneLessThanSSize) OF SubproblemSolution;
avail: LIST OF REF PerSwatchTable ← NARROW[scratch];
subproblemTable: LIST OF REF PerSwatchTable ← NIL;
Alloc: PROC RETURNS [new: LIST OF REF PerSwatchTable] ~ BEGIN
IF avail = NIL THEN new ← LIST[NEW[PerSwatchTable]]
ELSE {
new ← avail;
avail ← avail.rest;
new.rest ← NIL;
};
new.first^ ← ALL[[0, CARDINAL.LAST/&twoToTheSwathSize, CARDINAL.LAST]];
END;
ComputeFixedIndex: PROC ~ BEGIN
nonFixedBitCount ← 0;
FOR s: [&sMin2..&sMax2) IN [&sMin2..&sMax2) DO
FOR f: [0..&swathSize) IN [0..&swathSize) DO
IF fixed[s][f] = 0 THEN {
nonFixedBitIndex[nonFixedBitCount] ← [s,f];
nonFixedBitCount ← nonFixedBitCount + 1;
};
ENDLOOP;
ENDLOOP;
END;
Initialize: PROC ~ BEGIN
FOR s: [&sMin2..&sMax2) IN [&sMin2..&sMax2) DO
pixelRow.sOrigin ← sOrigin+s;
Load[pixelRow, bitmap];
FOR f: [&fMin2..&fMax2) IN [&fMin2..&fMax2) DO
bit[s][f] ← pixelRow.sample[f+fOrigin-pixelRow.fOrigin];
ENDLOOP;
IF s+sOrigin NOT IN [swath.sMin..swath.sMin+swath.sSize)
THEN fixed[s] ← ALL[1]
ELSE {
swathRow.sOrigin ← sOrigin+s;
Load[swathRow, fixedBits];
FOR f: [0..&swathSize) IN [0..&swathSize) DO
fixed[s][f] ← swathRow.sample[f+fOrigin-swathRow.fOrigin];
ENDLOOP;
};
ENDLOOP;
pixelRow.sOrigin ← sOrigin;
Load[pixelRow, gray];
FOR f: INTEGER IN [&fMin0..&fMax0) DO
target[f] ← pixelRow.sample[f+fOrigin-pixelRow.fOrigin];
ENDLOOP;
ComputeOuterModelIndices[];
ComputePartialTrial[];
ComputeFixedIndex[];
END;
Advance: PROC ~ BEGIN
sOrigin ← sOrigin + 1;
FOR s: [&sMin2..&sMax2) IN [&sMin2..&sMax2-1) DO
bit[s] ← bit[s+1];
fixed[s] ← fixed[s+1];
ENDLOOP;
pixelRow.sOrigin ← sOrigin+&sMax2-1;
Load[pixelRow, bitmap];
FOR f: [&fMin2..&fMax2) IN [&fMin2..&fMax2) DO
bit[&sMax2-1][f] ← pixelRow.sample[f+fOrigin-pixelRow.fOrigin];
ENDLOOP;
IF &sMax2-1+sOrigin NOT IN [swath.sMin..swath.sMin+swath.sSize)
THEN fixed[&sMax2-1] ← ALL[1]
ELSE {
swathRow.sOrigin ← sOrigin+&sMax2-1;
Load[swathRow, fixedBits];
FOR f: [0..&swathSize) IN [0..&swathSize) DO
fixed[&sMax2-1][f] ← swathRow.sample[f+fOrigin-swathRow.fOrigin];
ENDLOOP;
};
pixelRow.sOrigin ← sOrigin;
Load[pixelRow, gray];
FOR f: INTEGER IN [&fMin0..&fMax0) DO
target[f] ← pixelRow.sample[f+fOrigin-pixelRow.fOrigin];
ENDLOOP;
ComputeOuterModelIndices[];
ComputePartialTrial[];
ComputeFixedIndex[];
END;
ComputeOuterModelIndices: PROC ~ BEGIN
FOR s: INT IN [sMin1..sMax1) DO
FOR f: INT IN [fMin1..fMax1) DO
IF f NOT IN [-fModelRadius..swathSize+fModelRadius) THEN {
list: LIST OF SFNIL;
FOR ss: INT IN [sMinModel..sMaxModel) DO
FOR ff: INT IN [fMinModel..fMaxModel) DO
list ← CONS[[s+ss, f+ff], list];
ENDLOOP;
ENDLOOP;
index[&s][&f] ← PackBits[list]; ;

};
ENDLOOP;
ENDLOOP;

END;
ComputeInnerModelIndices: PROC ~ BEGIN
FOR s: INT IN [sMin1..sMax1) DO
FOR f: INT IN [-fModelRadius..swathSize+fModelRadius) DO
list: LIST OF SFNIL;
FOR ss: INT IN [sMinModel..sMaxModel) DO
FOR ff: INT IN [fMinModel..fMaxModel) DO
list ← CONS[[s+ss, f+ff], list];
ENDLOOP;
ENDLOOP;
index[&s][&f] ← PackBits[list]; ;

ENDLOOP;
ENDLOOP;

END;
ComputePartialTrial: PROC ~ BEGIN
From the index values
t: REF ModelDataItem ← NIL;
trial ← ALL[0];
FOR s: INT IN [sMin1..sMax1) DO
FOR f: INT IN [fMin1..fMax1) DO
IF f NOT IN [-fModelRadius..swathSize+fModelRadius) THEN {
t ← modelData[index[&s][&f]];

FOR ss: INT IN [sMinKernel..sMaxKernel) DO
FOR ff: INT IN [fMinKernel..fMaxKernel) DO
IF s+ss = 0 AND f+ff IN [fMin0..fMax0) THEN {
fff: INT ← f+ff;
trial[&fff] ← trial[&fff] + t.a[&ss][&ff];

};
ENDLOOP;
ENDLOOP;
};
ENDLOOP;
ENDLOOP;

END;
ComputeRowPenalty: PROC RETURNS [penalty: CARDINAL] ~ BEGIN
From the index values
t: REF ModelDataItem ← NIL;
try: ARRAY [&fMin0..&fMax0) OF INTEGER ← trial;
FOR s: INT IN [sMin1..sMax1) DO
FOR f: INT IN [0-fModelRadius..swathSize+fModelRadius) DO
t ← modelData[index[&s][&f]];

FOR ss: INT IN [sMinKernel..sMaxKernel) DO
FOR ff: INT IN [fMinKernel..fMaxKernel) DO
IF s+ss = 0 AND f+ff IN [fMin0..fMax0) THEN {
fff: INT ← f+ff;
try[&fff] ← try[&fff] + t.a[&ss][&ff];

};
ENDLOOP;
ENDLOOP;
ENDLOOP;
ENDLOOP;
penalty ← 0
FOR f: INT IN [fMin0..fMax0) DO
 + ABS[try[&f]-target[&f]] + modelData[index[0][&f]].noisePenalty
ENDLOOP;
;
END;
SetCombination: PROC [k: CARDINAL] ~ BEGIN
k is a packed version of the non-fixed bits
Sets questionBits and contextBits
FOR i: NAT IN [0..nonFixedBitCount) DO
sf: SF ← nonFixedBitIndex[i];
bit[sf.s][sf.f] ← k MOD 2;
k ← k/2;
ENDLOOP;
{
list: LIST OF SFNIL;
FOR s: INT IN [sMin2..sMin2] DO
FOR f: INT IN [0..swathSize) DO
list ← CONS[[s, f], list];
ENDLOOP;
ENDLOOP;
questionBits ← PackBits[list]; ;

list ← NIL;
FOR s: INT IN (sMin2..sMax2) DO
FOR f: INT IN [0..swathSize) DO
list ← CONS[[s, f], list];
ENDLOOP;
ENDLOOP;
contextBits ← PackBits[list]; ;

};
IF k # 0 THEN ERROR;
prevContextBits ← contextBits/&twoToTheSwathSize +
questionBits*(&twoToTheSwathSizeTimesOneLessThanSSize/&twoToTheSwathSize);
END;
UnpackBits: PROC [questionBits, contextBits: CARDINAL] ~ BEGIN
Unpacks the args into the swath portion of the bit array
k: CARDINAL ← contextBits+questionBits*&twoToTheSwathSizeTimesOneLessThanSSize;
 FOR s: INT DECREASING IN [sMin2..sMax2) DO
FOR f: INT DECREASING IN [0..swathSize) DO
bit[&s][&f] ← k MOD 2;
k ← k / 2;

ENDLOOP;
ENDLOOP;

END;
DoDynamicProgramming: PROC ~ {
If subproblemTable#NIL, subproblemTable.first gives the best ways to color the pixels up to sOrigin
UNTIL sOrigin = swath.sMin+swath.sSize DO
Initialize[];
BEGIN
nComb: NAT ← Basics.BITSHIFT[1, nonFixedBitCount];
new: LIST OF REF PerSwatchTable ← Alloc[];
pst: REF PerSwatchTable ← new.first;
prevPST: REF PerSwatchTable ← NIL;
IF subproblemTable # NIL THEN prevPST ← subproblemTable.first;
FOR k: NAT IN [0..nComb) DO
totBad: INT ← 0;
SetCombination[k];
ComputeInnerModelIndices[];
IF prevPST # NIL THEN totBad ← MinErr[prevPST[prevContextBits]];
totBad ← totBad+ComputeRowPenalty[];
IF totBad < MinErr[pst[contextBits]] THEN {
pst[contextBits] ← MakeSubproblemSolution[questionBits, totBad];
};
ENDLOOP;
new.rest ← subproblemTable;
subproblemTable ← new;
END;
sOrigin ← sOrigin + 1;
ENDLOOP;
};
Traceback: PROC ~ {
lowestPenalty: INT ← MinErr[subproblemTable.first[0]];
contextBits ← 0;
First look through the most recent subproblem to find the best entry.
FOR i: NAT IN (0..&twoToTheSwathSizeTimesOneLessThanSSize) DO
err: INT ← MinErr[subproblemTable.first[i]];
IF err < lowestPenalty THEN {
lowestPenalty ← err;
contextBits ← i;
};
ENDLOOP;
sOrigin ← swath.sMin+swath.sSize;
FOR t: LIST OF REF PerSwatchTable ← subproblemTable, t.rest WHILE sOrigin-&sTotalRadius > swath.sMin DO
questionBits ← t.first[contextBits].setting;
sOrigin ← sOrigin - 1;
UnpackBits[questionBits, contextBits];
swathRow.sOrigin ← sOrigin;
FOR j: NAT IN [0..swathRow.sample.jSize) DO
swathRow.sample[j] ← bit[0][j];
ENDLOOP;
StorePixelRow[swathRow, bitmap];
contextBits ← contextBits/&twoToTheSwathSize +
questionBits*(&twoToTheSwathSizeTimesOneLessThanSSize/&twoToTheSwathSize);
ENDLOOP;
};
DoDynamicProgramming[];
Traceback[];
newScratch ← subproblemTable;
END; GenTuneSwath[]};
};
};
DynamicBits.RegisterImpl[[
sKernelRadius: &sKernelRadius,
fKernelRadius: &fKernelRadius,
sModelRadius: &sModelRadius,
fModelRadius: &fModelRadius,
swathSize: &swathSize,
CreatePrinterModel: CreatePrinterModel,
DoWithPrinterModel: DoWithPrinterModel,
Convolve: Convolve,
ApplyModel: ApplyModel,
TuneSwath: TuneSwath
]];
END.