ImagerSamplerImpl.mesa
Copyright © 1984, 1985 by Xerox Corporation. All rights reserved.
Michael Plass, August 7, 1984 2:14:51 pm PDT
Doug Wyatt, March 9, 1985 5:35:55 pm PST
DIRECTORY
Basics USING [BITAND, BITNOT, BITOR, BITSHIFT, bitsPerWord, BITXOR, HighHalf, LongMult],
ImagerPixelMap USING [BoundedWindow, Create, DeviceRectangle, GetPixel, PixelMap, Window],
ImagerPixelRow USING [CreatePixelRow, LoadPixelRow, PixelRow, StorePixelRow],
ImagerSampler USING [Sampler, SamplerRep],
ImagerTransformation USING [InverseTransform, InverseTransformVec, Transformation],
Real USING [RoundLI],
RealFns USING [CosDeg],
Scaled USING [Floor, FromInt, FromReal, GREATER, half, LESS, MINUS, PLUS, UMINUS, Value, zero],
Vector2 USING [VEC];
ImagerSamplerImpl: CEDAR PROGRAM
IMPORTS Basics, ImagerPixelMap, ImagerPixelRow, ImagerTransformation, RealFns, Scaled
EXPORTS ImagerSampler
~ BEGIN
Sampler: TYPE ~ ImagerSampler.Sampler;
SamplerRep: TYPE ~ ImagerSampler.SamplerRep;
PixelMap: TYPE ~ ImagerPixelMap.PixelMap;
PixelRow: TYPE ~ ImagerPixelRow.PixelRow;
Transformation: TYPE ~ ImagerTransformation.Transformation;
VEC: TYPE ~ Vector2.VEC;
CreateSamplerRep:
PROC [m: Transformation, x, y:
INTEGER, sPixels, fPixels:
NAT]
RETURNS [samplerRep: SamplerRep] ~ {
deltaPixel: VEC ~ m.InverseTransformVec[[0, 1]];
deltaLine: VEC ~ m.InverseTransformVec[[1, 0]];
sourceOrigin: VEC ← m.InverseTransform[[x+0.5, y+0.5]];
IF sPixels = 0 OR fPixels = 0 THEN ERROR;
WHILE sourceOrigin.x < 0 DO sourceOrigin.x ← sourceOrigin.x + sPixels ENDLOOP;
WHILE sourceOrigin.x >= sPixels DO sourceOrigin.x ← sourceOrigin.x - sPixels ENDLOOP;
WHILE sourceOrigin.y < 0 DO sourceOrigin.y ← sourceOrigin.y + fPixels ENDLOOP;
WHILE sourceOrigin.y >= sPixels DO sourceOrigin.y ← sourceOrigin.y - fPixels ENDLOOP;
samplerRep ← [
m: m,
x: x,
y: y,
sPixels: sPixels,
fPixels: fPixels,
sStart: Scaled.FromReal[sourceOrigin.x],
fStart: Scaled.FromReal[sourceOrigin.y],
sDelta: Scaled.FromReal[deltaPixel.x],
fDelta: Scaled.FromReal[deltaPixel.y],
sDeltaLine: Scaled.FromReal[deltaLine.x],
fDeltaLine: Scaled.FromReal[deltaLine.y]
];
};
CreateSampler:
PUBLIC
PROC [m: Transformation, x, y:
INTEGER, sPixels, fPixels:
NAT]
RETURNS [sampler: Sampler] ~ {
sampler ← NEW[SamplerRep ← CreateSamplerRep[m, x, y, sPixels, fPixels]];
};
SetSamplePosition:
PUBLIC
PROC [sampler: Sampler, x, y:
INTEGER] ~ {
IF ABS[x-sampler.x] > 20 OR ABS[y-sampler.y] > 20 THEN sampler^ ← CreateSamplerRep[sampler.m, x, y, sampler.sPixels, sampler.fPixels]
ELSE {
s: Scaled.Value ← sampler.sStart;
f: Scaled.Value ← sampler.fStart;
WHILE sampler.x < x
DO
sampler.x ← sampler.x + 1;
s ← s.PLUS[sampler.sDeltaLine];
f ← f.PLUS[sampler.fDeltaLine];
ENDLOOP;
WHILE sampler.x > x
DO
sampler.x ← sampler.x - 1;
s ← s.MINUS[sampler.sDeltaLine];
f ← f.MINUS[sampler.fDeltaLine];
ENDLOOP;
WHILE sampler.y < y
DO
sampler.y ← sampler.y + 1;
s ← s.PLUS[sampler.sDelta];
f ← f.PLUS[sampler.fDelta];
ENDLOOP;
WHILE sampler.y > y
DO
sampler.y ← sampler.y - 1;
s ← s.MINUS[sampler.sDelta];
f ← f.MINUS[sampler.fDelta];
ENDLOOP;
WHILE s.Floor < 0 DO s ← s.PLUS[Scaled.FromInt[sampler.sPixels]] ENDLOOP;
WHILE s.Floor >= sampler.sPixels DO s ← s.MINUS[Scaled.FromInt[sampler.sPixels]] ENDLOOP;
WHILE f.Floor < 0 DO f ← f.PLUS[Scaled.FromInt[sampler.fPixels]] ENDLOOP;
WHILE f.Floor >= sampler.fPixels DO f ← f.MINUS[Scaled.FromInt[sampler.fPixels]] ENDLOOP;
sampler.sStart ← s;
sampler.fStart ← f;
};
};
SimpleObtainPointSamples:
PROC [pixelRow: PixelRow, source: PixelMap, sampler: Sampler, multiplier:
CARDINAL, lgScale:
INTEGER] ~ {
rect: ImagerPixelMap.DeviceRectangle ← source.BoundedWindow;
FOR j:
NAT
IN [0..pixelRow.fSize)
DO
SetSamplePosition[sampler, pixelRow.sOrigin, pixelRow.fOrigin+j];
IF sampler.sStart.Floor
IN [rect.sMin..rect.sMin+rect.sSize)
AND sampler.fStart.Floor
IN [rect.fMin..rect.fMin+rect.fSize)
THEN {
pixelRow[j] ← Basics.BITSHIFT[source.GetPixel[sampler.sStart.Floor, sampler.fStart.Floor]*multiplier, lgScale];
};
ENDLOOP;
};
TruncDiv:
PROC [a, b: Scaled.Value]
RETURNS [
INT] ~
INLINE {
RETURN [LOOPHOLE[a, INT]/LOOPHOLE[b, INT]]
};
Mod:
PROC [s: Scaled.Value, m:
NAT]
RETURNS [Scaled.Value] ~ {
WHILE s.integerPart < 0 DO s.integerPart ← s.integerPart + m ENDLOOP;
WHILE s.integerPart >= m DO s.integerPart ← s.integerPart - m ENDLOOP;
RETURN [s]
};
SimplePointSamples:
PROC [pixelRow: PixelRow, source: PixelMap, sampler: Sampler] ~
TRUSTED {
Assert [0, 0, sPixels, fPixels] INSIDE source.BoundedWindow
rast: INT ~ source.refRep.rast;
lgBitsPerPixel: NAT ~ source.refRep.lgBitsPerPixel;
sPixels: INTEGER ~ sampler.sPixels;
fPixels: INTEGER ~ sampler.fPixels;
s: Scaled.Value ← sampler.sStart;
sFloor: INTEGER ← s.Floor;
f: Scaled.Value ← sampler.fStart;
sDelta: Scaled.Value ← Mod[sampler.sDelta, sPixels];
fDelta: Scaled.Value ← Mod[sampler.fDelta, fPixels];
lineOffset: INT ← INT[s.Floor - source.sOrigin]*rast;
normalDelta: INT ← INT[sDelta.Floor]*rast;
totalDelta: INT ← INT[sPixels]*rast;
FOR j:
NAT
IN [0..pixelRow.fSize)
DO
pixelRow[j] ←
SELECT lgBitsPerPixel
FROM
0 => LOOPHOLE[source.refRep.pointer + lineOffset, LONG POINTER TO PACKED ARRAY [0..0) OF [0..2)][f.Floor - source.fOrigin],
1 => LOOPHOLE[source.refRep.pointer + lineOffset, LONG POINTER TO PACKED ARRAY [0..0) OF [0..4)][f.Floor - source.fOrigin],
2 => LOOPHOLE[source.refRep.pointer + lineOffset, LONG POINTER TO PACKED ARRAY [0..0) OF [0..16)][f.Floor - source.fOrigin],
3 => LOOPHOLE[source.refRep.pointer + lineOffset, LONG POINTER TO PACKED ARRAY [0..0) OF [0..256)][f.Floor - source.fOrigin],
4 => LOOPHOLE[source.refRep.pointer + lineOffset, LONG POINTER TO PACKED ARRAY [0..0) OF CARDINAL][f.Floor - source.fOrigin],
ENDCASE => ERROR;
s ← LOOPHOLE[LOOPHOLE[s, INT]+LOOPHOLE[sDelta, INT]];
f ← LOOPHOLE[LOOPHOLE[f, INT]+LOOPHOLE[fDelta, INT]];
lineOffset ← lineOffset + normalDelta;
sFloor ← sFloor + sDelta.Floor;
IF sFloor < s.Floor
THEN {
sFloor ← s.Floor;
lineOffset ← lineOffset + rast;
};
IF sFloor >= sPixels
THEN {
sFloor ← s.integerPart ← sFloor - sPixels;
lineOffset ← lineOffset - totalDelta;
};
IF f.Floor >= fPixels THEN f.integerPart ← f.integerPart - fPixels;
ENDLOOP;
};
ObtainPointSamples:
PUBLIC
PROC [pixelRow: PixelRow, source: PixelMap, sampler: Sampler, multiplier:
CARDINAL, lgScale:
INTEGER] ~ {
rect: ImagerPixelMap.DeviceRectangle ~ source.BoundedWindow;
sMax: INTEGER ~ rect.sMin+rect.sSize;
fMax: INTEGER ~ rect.fMin+rect.fSize;
sPixels: INTEGER ~ sampler.sPixels;
fPixels: INTEGER ~ sampler.fPixels;
rast: INT ~ source.refRep.rast;
base: LONG POINTER ~ source.refRep.pointer;
lgBitsPerPixel: NAT ~ source.refRep.lgBitsPerPixel;
SetSamplePosition[sampler, pixelRow.sOrigin, pixelRow.fOrigin];
IF rect = [0, 0, sPixels, fPixels]
AND multiplier = 1
AND lgScale = 0
THEN {
SimplePointSamples[pixelRow, source, sampler];
}
ELSE {
s: Scaled.Value ← sampler.sStart;
f: Scaled.Value ← sampler.fStart;
sDelta: Scaled.Value ← sampler.sDelta;
fDelta: Scaled.Value ← sampler.fDelta;
normalDelta: INT ← INT[sDelta.Floor]*rast;
j: CARDINAL ← 0;
WHILE j < pixelRow.fSize
DO
IF s.Floor
IN [rect.sMin..sMax)
AND f.Floor
IN [rect.fMin..fMax)
THEN
TRUSTED {
sFloor: INTEGER ← s.Floor;
lineOffset: INT ← INT[s.Floor - source.sOrigin]*rast;
toGo: INT ← pixelRow.fSize-j;
IF sDelta.
GREATER[Scaled.zero]
THEN {
toGo ← MIN[toGo, TruncDiv[Scaled.FromInt[sMax].MINUS[s], sDelta]];
};
IF sDelta.
LESS[Scaled.zero]
THEN {
toGo ← MIN[toGo, TruncDiv[s.MINUS[Scaled.FromInt[rect.sMin]], sDelta.UMINUS]];
};
IF fDelta.
GREATER[Scaled.zero]
THEN {
toGo ← MIN[toGo, TruncDiv[Scaled.FromInt[fMax].MINUS[f], fDelta]];
};
IF fDelta.
LESS[Scaled.zero]
THEN {
toGo ← MIN[toGo, TruncDiv[f.MINUS[Scaled.FromInt[rect.fMin]], fDelta.UMINUS]];
};
THROUGH [0..
INTEGER[toGo])
DO
pix:
CARDINAL ←
SELECT lgBitsPerPixel
FROM
0 => LOOPHOLE[base + lineOffset, LONG POINTER TO PACKED ARRAY [0..0) OF [0..2)][f.Floor - source.fOrigin],
1 => LOOPHOLE[base + lineOffset, LONG POINTER TO PACKED ARRAY [0..0) OF [0..4)][f.Floor - source.fOrigin],
2 => LOOPHOLE[base + lineOffset, LONG POINTER TO PACKED ARRAY [0..0) OF [0..16)][f.Floor - source.fOrigin],
3 => LOOPHOLE[base + lineOffset, LONG POINTER TO PACKED ARRAY [0..0) OF [0..256)][f.Floor - source.fOrigin],
4 => LOOPHOLE[base + lineOffset, LONG POINTER TO PACKED ARRAY [0..0) OF CARDINAL][f.Floor - source.fOrigin],
ENDCASE => ERROR;
pixelRow[j] ← Basics.BITSHIFT[pix*multiplier, lgScale];
s ← LOOPHOLE[LOOPHOLE[s, INT]+LOOPHOLE[sDelta, INT]];
f ← LOOPHOLE[LOOPHOLE[f, INT]+LOOPHOLE[fDelta, INT]];
lineOffset ← lineOffset + normalDelta;
sFloor ← sFloor + sDelta.Floor;
IF sFloor < s.Floor
THEN {
sFloor ← sFloor + 1;
lineOffset ← lineOffset + rast;
};
j ← j + 1;
ENDLOOP;
IF sFloor # s.Floor THEN ERROR;
};
IF j < pixelRow.fSize
THEN {
WHILE s.Floor < 0 DO s ← s.PLUS[Scaled.FromInt[sPixels]] ENDLOOP;
WHILE s.Floor >= sPixels DO s ← s.MINUS[Scaled.FromInt[sPixels]] ENDLOOP;
WHILE f.Floor < 0 DO f ← f.PLUS[Scaled.FromInt[fPixels]] ENDLOOP;
WHILE f.Floor >= fPixels DO f ← f.MINUS[Scaled.FromInt[fPixels]] ENDLOOP;
IF s.Floor
IN [rect.sMin..sMax)
AND f.Floor
IN [rect.fMin..fMax)
THEN {
pix: CARDINAL ← source.GetPixel[s.Floor, f.Floor];
pixelRow[j] ← Basics.BITSHIFT[pix*multiplier, lgScale];
};
s ← s.PLUS[sDelta];
f ← f.PLUS[fDelta];
j ← j + 1;
};
ENDLOOP;
};
};
ObtainInterpolatedSamples:
PUBLIC
PROC [pixelRow: PixelRow, source: PixelMap, sampler: Sampler, multiplier:
CARDINAL, lgScale:
INTEGER] ~ {
rect: ImagerPixelMap.DeviceRectangle ~ source.BoundedWindow;
sMin: Scaled.Value ~ Scaled.FromInt[rect.sMin].PLUS[Scaled.half];
fMin: Scaled.Value ~ Scaled.FromInt[rect.fMin].PLUS[Scaled.half];
sMax: Scaled.Value ~ Scaled.FromInt[rect.sMin+rect.sSize].MINUS[Scaled.half];
fMax: Scaled.Value ~ Scaled.FromInt[rect.fMin+rect.fSize].MINUS[Scaled.half];
sPixels: INTEGER ~ sampler.sPixels;
fPixels: INTEGER ~ sampler.fPixels;
rast: INT ~ source.refRep.rast;
base: LONG POINTER ~ source.refRep.pointer;
lgBitsPerPixel: NAT ~ source.refRep.lgBitsPerPixel;
SetSamplePosition[sampler, pixelRow.sOrigin, pixelRow.fOrigin];
BEGIN
s: Scaled.Value ← sampler.sStart;
f: Scaled.Value ← sampler.fStart;
sDelta: Scaled.Value ← sampler.sDelta;
fDelta: Scaled.Value ← sampler.fDelta;
normalDelta: INT ← INT[sDelta.Floor]*rast;
j: CARDINAL ← 0;
WHILE j < pixelRow.fSize
DO
IF
NOT s.
LESS[sMin]
AND s.
LESS[sMax]
AND
NOT f.
LESS[fMin]
AND f.
LESS[fMax]
THEN
TRUSTED {
ss: Scaled.Value ← s.MINUS[Scaled.half];
ff: Scaled.Value ← f.MINUS[Scaled.half];
ssFloor: INTEGER ← ss.Floor;
lineOffset: INT ← INT[ss.Floor - source.sOrigin]*rast;
toGo: INT ← pixelRow.fSize-j;
IF sDelta.
GREATER[Scaled.zero]
THEN {
toGo ← MIN[toGo, TruncDiv[sMax.MINUS[s], sDelta]];
};
IF sDelta.
LESS[Scaled.zero]
THEN {
toGo ← MIN[toGo, TruncDiv[s.MINUS[sMin], sDelta.UMINUS]];
};
IF fDelta.
GREATER[Scaled.zero]
THEN {
toGo ← MIN[toGo, TruncDiv[fMax.MINUS[f], fDelta]];
};
IF fDelta.
LESS[Scaled.zero]
THEN {
toGo ← MIN[toGo, TruncDiv[f.MINUS[fMin], fDelta.UMINUS]];
};
THROUGH [0..
INTEGER[toGo])
DO
k: INTEGER ← ff.Floor - source.fOrigin;
a: CARDINAL ← ss.fraction;
b: CARDINAL ← ff.fraction;
ab: CARDINAL ← Basics.HighHalf[Basics.LongMult[a, b]];
v00, v01, v10, v11: CARDINAL;
SELECT lgBitsPerPixel
FROM
0 => {
p: LONG POINTER TO RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF [0..2)] ← LOOPHOLE[base + lineOffset];
v00 ← p[k]; v01 ← p[k + 1];
p ← p + rast; v10 ← p[k]; v11 ← p[k + 1];
};
1 => {
p: LONG POINTER TO RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF [0..4)] ← LOOPHOLE[base + lineOffset];
v00 ← p[k]; v01 ← p[k + 1];
p ← p + rast; v10 ← p[k]; v11 ← p[k + 1];
};
2 => {
p: LONG POINTER TO RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF [0..16)] ← LOOPHOLE[base + lineOffset];
v00 ← p[k]; v01 ← p[k + 1];
p ← p + rast; v10 ← p[k]; v11 ← p[k + 1];
};
3 => {
p: LONG POINTER TO RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF [0..256)] ← LOOPHOLE[base + lineOffset];
v00 ← p[k]; v01 ← p[k + 1];
p ← p + rast; v10 ← p[k]; v11 ← p[k + 1];
};
4 => {
p: LONG POINTER TO RECORD[PACKED SEQUENCE COMPUTED CARDINAL OF CARDINAL] ← LOOPHOLE[base + lineOffset];
v00 ← p[k]; v01 ← p[k + 1];
p ← p + rast; v10 ← p[k]; v11 ← p[k + 1];
};
ENDCASE => ERROR;
IF multiplier # 1
OR lgScale # 0
THEN {
v00 ← Basics.BITSHIFT[v00*multiplier, lgScale];
v01 ← Basics.BITSHIFT[v01*multiplier, lgScale];
v10 ← Basics.BITSHIFT[v10*multiplier, lgScale];
v11 ← Basics.BITSHIFT[v11*multiplier, lgScale];
};
pixelRow[j] ←
IF a=0
AND b=0
THEN v00
ELSE Basics.HighHalf[
Basics.LongMult[CARDINAL.LAST-a+ab-b+1, v00] +
Basics.LongMult[b-ab, v01] +
Basics.LongMult[a-ab, v10] +
Basics.LongMult[ab, v11]
];
ss ← LOOPHOLE[LOOPHOLE[ss, INT]+LOOPHOLE[sDelta, INT]];
ff ← LOOPHOLE[LOOPHOLE[ff, INT]+LOOPHOLE[fDelta, INT]];
lineOffset ← lineOffset + normalDelta;
ssFloor ← ssFloor + sDelta.Floor;
IF ssFloor < ss.Floor
THEN {
ssFloor ← ssFloor + 1;
lineOffset ← lineOffset + rast;
};
j ← j + 1;
ENDLOOP;
s ← ss.PLUS[Scaled.half];
f ← ff.PLUS[Scaled.half];
IF ssFloor # ss.Floor THEN ERROR;
};
IF j < pixelRow.fSize
THEN {
WHILE s.Floor < 0 DO s ← s.PLUS[Scaled.FromInt[sPixels]] ENDLOOP;
WHILE s.Floor >= sPixels DO s ← s.MINUS[Scaled.FromInt[sPixels]] ENDLOOP;
WHILE f.Floor < 0 DO f ← f.PLUS[Scaled.FromInt[fPixels]] ENDLOOP;
WHILE f.Floor >= fPixels DO f ← f.MINUS[Scaled.FromInt[fPixels]] ENDLOOP;
IF s.Floor
IN [rect.sMin..rect.sMin+rect.sSize)
AND f.Floor
IN [rect.fMin..rect.fMin+rect.fSize)
THEN {
pix: CARDINAL ← source.GetPixel[s.Floor, f.Floor];
pixelRow[j] ← Basics.BITSHIFT[pix*multiplier, lgScale];
};
s ← s.PLUS[sDelta];
f ← f.PLUS[fDelta];
j ← j + 1;
};
ENDLOOP;
END;
};
Hi:
PROC [a:
CARDINAL]
RETURNS [
CARDINAL] ~
INLINE {RETURN[Basics.BITSHIFT[a, 1-Basics.bitsPerWord]]};
Shift:
PROC [a:
CARDINAL, amt:
INTEGER]
RETURNS [
CARDINAL] ~
INLINE {RETURN[Basics.BITSHIFT[a, amt]]};
HalftoneLine:
PUBLIC
PROC [dest: PixelMap, pixels: PixelRow, thresholds: PixelRow, invertOutput:
BOOLEAN, transparent:
BOOLEAN] ~ {
rect: ImagerPixelMap.DeviceRectangle ← dest.BoundedWindow;
fMin: INTEGER ← MAX[rect.fMin, pixels.fOrigin];
fMax: INTEGER ← MIN[rect.fMin+rect.fSize, pixels.fOrigin+pixels.fSize];
IF fMax <= fMin THEN RETURN;
IF pixels.sOrigin NOT IN [rect.sMin..rect.sMin+rect.sSize) THEN RETURN;
IF dest.refRep.lgBitsPerPixel # 0 THEN ERROR;
IF fMin < thresholds.fOrigin THEN ERROR;
IF fMax > thresholds.fOrigin + thresholds.fSize THEN ERROR;
TRUSTED {
SixteenWords:
TYPE ~
MACHINE
DEPENDENT
RECORD [
w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15: CARDINAL
];
linePointer: LONG POINTER ~ dest.refRep.pointer+Basics.LongMult[dest.refRep.rast, pixels.sOrigin-dest.sOrigin];
bitOffset: CARDINAL ~ fMin - dest.fOrigin;
p: LONG POINTER TO SixteenWords ← LOOPHOLE[@(pixels[0])];
q: LONG POINTER TO SixteenWords ← LOOPHOLE[@(thresholds[pixels.fOrigin-thresholds.fOrigin])];
allInvert: CARDINAL ← IF invertOutput THEN LAST[CARDINAL] ELSE 0;
GetN:
UNSAFE
PROC [n: [0..16)]
RETURNS [
CARDINAL] ~
UNCHECKED {
w: CARDINAL ← 0;
THROUGH [0..n)
DO
w ← w*2 + Hi[p^.w0-q^.w0];
p ← p + 1;
q ← q + 1;
ENDLOOP;
RETURN [Basics.BITXOR[w, Basics.BITSHIFT[allInvert, n-16]]];
}; -- GetFirst
Get16:
UNSAFE
PROC
RETURNS [
CARDINAL] ~
UNCHECKED {
s, h: SixteenWords;
s ← p^; p ← p + SIZE[SixteenWords];
h ← q^; q ← q + SIZE[SixteenWords];
RETURN [Basics.BITXOR[allInvert, ((((((((((((((Hi[s.w0-h.w0]*2+Hi[s.w1-h.w1])*2+Hi[s.w2-h.w2])*2+Hi[s.w3-h.w3])*2+Hi[s.w4-h.w4])*2+Hi[s.w5-h.w5])*2+Hi[s.w6-h.w6])*2+Hi[s.w7-h.w7])*2+Hi[s.w8-h.w8])*2+Hi[s.w9-h.w9])*2+Hi[s.w10-h.w10])*2+Hi[s.w11-h.w11])*2+Hi[s.w12-h.w12])*2+Hi[s.w13-h.w13])*2+Hi[s.w14-h.w14])*2+Hi[s.w15-h.w15]]]
}; -- Get16
count: CARDINAL ← fMax-fMin;
d: LONG POINTER TO CARDINAL ← LOOPHOLE[linePointer + bitOffset/16];
IF transparent
THEN {
IF bitOffset
MOD 16 # 0
THEN {
firstBits: INTEGER ← 16-(bitOffset MOD 16);
z: INTEGER ← MAX[firstBits-INTEGER[count], 0];
d^ ← Basics.BITOR[d^, Shift[GetN[firstBits-z], z]];
d ← d + 1;
count ← count - (firstBits-z);
};
WHILE count >= 16
DO
d^ ← Basics.BITOR[d^, Get16[]];
d ← d + 1;
count ← count - 16;
ENDLOOP;
IF count > 0
THEN {
d^ ← Basics.BITOR[d^, Shift[GetN[count], 16-count]];
};
}
ELSE {
IF bitOffset
MOD 16 # 0
THEN {
firstBits: INTEGER ← 16-(bitOffset MOD 16);
z: INTEGER ← MAX[firstBits-INTEGER[count], 0];
m: CARDINAL ← Shift[1, firstBits] - Shift[1, z];
d^ ← Basics.BITOR[Basics.BITAND[d^, Basics.BITNOT[m]], Shift[GetN[firstBits-z], z]];
d ← d + 1;
count ← count - (firstBits-z);
};
WHILE count >= 16
DO
d^ ← Get16[];
d ← d + 1;
count ← count - 16;
ENDLOOP;
IF count > 0
THEN {
d^ ← Basics.BITOR[Basics.BITAND[d^, Shift[1, 16-count]-1], Shift[GetN[count], 16-count]];
};
};
};
};
DotScreen:
PUBLIC
PROC [r:
REAL, sSize:
NAT, fSize:
NAT, maxPixelValue:
CARDINAL]
RETURNS [pixelMap: PixelMap] ~ {
pixelRow: PixelRow ← ImagerPixelRow.CreatePixelRow[0, 0, fSize];
pixelMap ← ImagerPixelMap.Create[4, [0, 0, sSize, fSize]];
FOR s:
NAT
IN [0..sSize)
DO
u: REAL ← RealFns.CosDeg[360.0*s/sSize+0.314159]*(1.0-r);
pixelRow.sOrigin ← s;
FOR f:
NAT
IN [0..fSize)
DO
v: REAL ← u+RealFns.CosDeg[360.0*f/fSize-0.0271828]*r;
pix: INT ← Real.RoundLI[maxPixelValue*(v+1)/2];
pixelRow[f] ← MIN[MAX[pix, 0], maxPixelValue];
ENDLOOP;
pixelRow.StorePixelRow[pixelMap];
ENDLOOP;
};
shellD: ARRAY [1..11] OF CARDINAL = [1, 4, 13, 40, 121, 364, 1093, 3280, 9841, 29524, 65535];
ShellSort:
PROCEDURE [key, data:
REF
ARRAY [0..32000)
OF
CARDINAL, length:
NAT] = {
passes: NAT ← 1;
UNTIL shellD[passes+2] >= length DO passes ← passes+1 ENDLOOP;
FOR pass:
NAT
DECREASING
IN [1..passes]
DO
h: NAT ← shellD[pass];
FOR i:
NAT
IN [0..length)
DO
aKey: CARDINAL ← key[i];
aData: CARDINAL ← data[i];
j: NAT ← i;
WHILE j>=h
AND aKey < key[j-h]
DO
key[j] ← key[j-h];
data[j] ← data[j-h];
j ← j-h;
ENDLOOP;
key[j] ← aKey;
data[j] ← aData;
ENDLOOP;
ENDLOOP;
};
ApplyTRC:
PUBLIC
PROC [thresholds: PixelMap, trc:
PROC[x:
REAL]
RETURNS [y:
REAL], maxPixelValue:
CARDINAL] ~ {
rect: ImagerPixelMap.DeviceRectangle ← thresholds.Window;
element: REF ARRAY [0..32000) OF CARDINAL ← NEW[ARRAY [0..32000) OF CARDINAL];
position: REF ARRAY [0..32000) OF CARDINAL ← NEW[ARRAY [0..32000) OF CARDINAL];
pixelRow: PixelRow ← ImagerPixelRow.CreatePixelRow[0, rect.fMin, rect.fSize];
pix: CARDINAL ← 1;
n: NAT ← 0;
FOR s:
NAT
IN [rect.sMin..rect.sMin+rect.sSize)
DO
pixelRow.sOrigin ← s;
pixelRow.LoadPixelRow[thresholds];
FOR f:
NAT
IN [0..rect.fSize)
DO
element[n] ← pixelRow[f];
position[n] ← n;
n ← n + 1;
ENDLOOP;
ENDLOOP;
ShellSort[element, position, n];
FOR i:
NAT
IN [0..n)
DO
y: REAL ← REAL[i]/n;
UNTIL trc[
REAL[pix]/maxPixelValue] >= y
DO
IF pix + 1 >= maxPixelValue THEN EXIT;
pix ← pix + 1;
ENDLOOP;
element[i] ← pix;
ENDLOOP;
ShellSort[position, element, n];
n ← 0;
FOR s:
NAT
IN [rect.sMin..rect.sMin+rect.sSize)
DO
pixelRow.sOrigin ← s;
FOR f:
NAT
IN [0..rect.fSize)
DO
pixelRow[f] ← element[n];
n ← n + 1;
ENDLOOP;
pixelRow.StorePixelRow[thresholds];
ENDLOOP;
};
Identity:
PUBLIC
PROC [x:
REAL]
RETURNS [y:
REAL] ~ {
RETURN [x]
};
END.