IF
NOT ImagerTransformation.Singular[m]
THEN {
samplesPerPixel: NAT ~ self.samplesPerPixel;
sSize: NAT15 ~ self.box.max.s-self.box.min.s; -- source size in slow (scan line) direction
fSize: NAT15 ~ self.box.max.f-self.box.min.f; -- source size in fast (pixel) direction
ssDelta: Basics.LongNumber; -- source delta s for destination s increment
fsDelta: Basics.LongNumber; -- source delta f for destination s increment
sfDelta: Basics.LongNumber; -- source delta s for destination f increment
ffDelta: Basics.LongNumber; -- source delta f for destination f increment
d0: SF.Vec ¬ bounds.min; -- initial destination position
s0: Basics.LongNumber; -- initial source s (corresponding to d0)
f0: Basics.LongNumber; -- initial source f (corresponding to d0)
pixels: PixelBuffer ~ ObtainScratchPixels[samplesPerPixel, SF.SizeF[bounds]];
rs, rf: REAL ¬ 0.0;
boxActionPointSamples:
SF.BoxAction ~ {
count: NAT ~ SF.SizeF[box];
smax: Basics.LongNumber ~ [pair[hi: sSize, lo: 0]];
fmax: Basics.LongNumber ~ [pair[hi: fSize, lo: 0]];
ssup: Basics.LongNumber ~ ssDelta;
fsup: Basics.LongNumber ~ fsDelta;
ssdn: Basics.LongNumber ~ [lc[smax.lc-ssup.lc]];
fsdn: Basics.LongNumber ~ [lc[fmax.lc-fsup.lc]];
sfup: Basics.LongNumber ~ sfDelta;
ffup: Basics.LongNumber ~ ffDelta;
sfdn: Basics.LongNumber ~ [lc[smax.lc-sfup.lc]];
ffdn: Basics.LongNumber ~ [lc[fmax.lc-ffup.lc]];
d1s, d1f: INTEGER; -- destination position at start of scan line
s1: Basics.LongNumber ¬ s0; -- source s corresponding to [d1s, d1f]
f1: Basics.LongNumber ¬ f0; -- source f corresponding to [d1s, d1f]
[d1s, d1f] ¬ d0;
WHILE d1s<box.min.s
DO
d1s ¬ d1s+1;
IF s1.lc<ssdn.lc THEN s1.lc ¬ s1.lc+ssup.lc ELSE s1.lc ¬ s1.lc-ssdn.lc;
IF f1.lc<fsdn.lc THEN f1.lc ¬ f1.lc+fsup.lc ELSE f1.lc ¬ f1.lc-fsdn.lc;
ENDLOOP;
WHILE d1s>box.min.s
DO
d1s ¬ d1s-1;
IF s1.lc>=ssup.lc THEN s1.lc ¬ s1.lc-ssup.lc ELSE s1.lc ¬ s1.lc+ssdn.lc;
IF f1.lc>=fsup.lc THEN f1.lc ¬ f1.lc-fsup.lc ELSE f1.lc ¬ f1.lc+fsdn.lc;
ENDLOOP;
d0 ¬ [d1s, d1f];
s0.lc ¬ s1.lc;
f0.lc ¬ f1.lc;
WHILE d1f<box.min.f
DO
d1f ¬ d1f+1;
IF s1.lc<sfdn.lc THEN s1.lc ¬ s1.lc+sfup.lc ELSE s1.lc ¬ s1.lc-sfdn.lc;
IF f1.lc<ffdn.lc THEN f1.lc ¬ f1.lc+ffup.lc ELSE f1.lc ¬ f1.lc-ffdn.lc;
ENDLOOP;
WHILE d1f>box.min.f
DO
d1f ¬ d1f-1;
IF s1.lc>=sfup.lc THEN s1.lc ¬ s1.lc-sfup.lc ELSE s1.lc ¬ s1.lc+sfdn.lc;
IF f1.lc>=ffup.lc THEN f1.lc ¬ f1.lc-ffup.lc ELSE f1.lc ¬ f1.lc+ffdn.lc;
ENDLOOP;
pixels.length ¬ count;
DO
--For each scan line of box--
FOR i:
NAT
IN [0..samplesPerPixel)
DO
map: ImagerSample.SampleMap ~ self[i];
rasterMap: ImagerSample.RasterSampleMap ~ WITH map SELECT FROM r: ImagerSample.RasterSampleMap => r ENDCASE => NIL;
easyLineCalc: BOOL ~ rasterMap # NIL AND rasterMap.base.bit=0 AND (rasterMap.bitsPerLine MOD bitsPerWord)=0;
samples: ImagerSample.SampleBuffer ~ pixels[i];
s: Basics.LongNumber ¬ s1;
f: Basics.LongNumber ¬ f1;
SELECT
TRUE
FROM
sfDelta.li = 0
AND ffDelta = [pair[hi: 1, lo: 0]] => {
count1: NAT ~ MIN [count, fSize-f.hi];
count2: NAT ~ MIN [count-count1, f.hi];
count3: NAT ~ count-count1-count2;
ImagerSample.GetSamples[map: map, initIndex: [s: s.hi+self.box.min.s, f: f.hi+self.box.min.f], buffer: samples, start: 0, count: count1];
IF count2 # 0
THEN
ImagerSample.GetSamples[map: map, initIndex: [s: s.hi+self.box.min.s, f: self.box.min.f], buffer: samples, start: count1, count: count2];
IF count3 # 0
THEN
ImagerSample.CopySamples[dst: samples, src: samples, dstStart: count1+count2, srcStart: 0, count: count3];
};
easyLineCalc
AND rasterMap.bitsPerSample=1 => {
base: Pointer1 ~ LOOPHOLE[rasterMap.base.word];
upl: NAT ~ rasterMap.bitsPerLine/bitsPerUnit;
result: RawSamplesPtr ~ InlinePointerToSamples[samples, 0, count];
lastSHi: CARDINAL ¬ s.hi;
line: Pointer1 ¬ base+lastSHi*upl;
FOR k:
NAT
IN [0..count)
DO
IF lastSHi # s.hi THEN {lastSHi ¬ s.hi; line ¬ base+lastSHi*upl};
TRUSTED { result[k] ¬ line[f.hi] };
IF s.lc<sfdn.lc THEN s.lc ¬ s.lc+sfup.lc ELSE s.lc ¬ s.lc-sfdn.lc;
IF f.lc<ffdn.lc THEN f.lc ¬ f.lc+ffup.lc ELSE f.lc ¬ f.lc-ffdn.lc;
ENDLOOP;
};
easyLineCalc
AND rasterMap.bitsPerSample=8 => {
base: Pointer8 ~ LOOPHOLE[rasterMap.base.word];
upl: NAT ~ rasterMap.bitsPerLine/bitsPerUnit;
result: RawSamplesPtr ~ InlinePointerToSamples[samples, 0, count];
IF sfup.lc=0
THEN {
line: Pointer8 ~ base+LONG[s.hi]*upl;
FOR k:
NAT
IN [0..count)
DO
TRUSTED { result[k] ¬ line[f.hi] };
IF f.lc<ffdn.lc THEN f.lc ¬ f.lc+ffup.lc ELSE f.lc ¬ f.lc-ffdn.lc;
ENDLOOP;
}
ELSE {
lastSHi: CARDINAL ¬ s.hi;
line: Pointer8 ¬ base+LONG[lastSHi]*upl;
FOR k:
NAT
IN [0..count)
DO
IF lastSHi # s.hi THEN {lastSHi ¬ s.hi; line ¬ base+lastSHi*upl};
TRUSTED { result[k] ¬ line[f.hi] };
IF s.lc<sfdn.lc THEN s.lc ¬ s.lc+sfup.lc ELSE s.lc ¬ s.lc-sfdn.lc;
IF f.lc<ffdn.lc THEN f.lc ¬ f.lc+ffup.lc ELSE f.lc ¬ f.lc-ffdn.lc;
ENDLOOP;
};
};
easyLineCalc
AND rasterMap.bitsPerSample=16 => {
base: Pointer16 ~ LOOPHOLE[rasterMap.base.word];
upl: NAT ~ rasterMap.bitsPerLine/bitsPerUnit;
result: RawSamplesPtr ~ InlinePointerToSamples[samples, 0, count];
lastSHi: CARDINAL ¬ s.hi;
line: Pointer16 ¬ base+LONG[lastSHi]*upl;
FOR k:
NAT
IN [0..count)
DO
IF lastSHi # s.hi THEN {lastSHi ¬ s.hi; line ¬ base+lastSHi*upl};
TRUSTED { result[k] ¬ line[f.hi] };
IF s.lc<sfdn.lc THEN s.lc ¬ s.lc+sfup.lc ELSE s.lc ¬ s.lc-sfdn.lc;
IF f.lc<ffdn.lc THEN f.lc ¬ f.lc+ffup.lc ELSE f.lc ¬ f.lc-ffdn.lc;
ENDLOOP;
};
ENDCASE => {
-- the slow but general way
FOR k:
NAT
IN [0..count)
DO
samples[k] ¬ ImagerSample.Get[map, [s: s.hi+self.box.min.s, f: f.hi+self.box.min.f]];
IF s.lc<sfdn.lc THEN s.lc ¬ s.lc+sfup.lc ELSE s.lc ¬ s.lc-sfdn.lc;
IF f.lc<ffdn.lc THEN f.lc ¬ f.lc+ffup.lc ELSE f.lc ¬ f.lc-ffdn.lc;
ENDLOOP;
};
ENDLOOP;
action[pixels, [d1s, d1f]];
d1s ¬ d1s+1; IF NOT d1s<box.max.s THEN EXIT;
IF s1.lc<ssdn.lc THEN s1.lc ¬ s1.lc+ssup.lc ELSE s1.lc ¬ s1.lc-ssdn.lc;
IF f1.lc<fsdn.lc THEN f1.lc ¬ f1.lc+fsup.lc ELSE f1.lc ¬ f1.lc-fsdn.lc;
ENDLOOP;
};
boxActionInterpolatedSamples:
SF.BoxAction ~ {
count: NAT ~ SF.SizeF[box];
smax: Basics.LongNumber ~ [pair[hi: sSize, lo: 0]];
fmax: Basics.LongNumber ~ [pair[hi: fSize, lo: 0]];
ssup: Basics.LongNumber ~ ssDelta;
fsup: Basics.LongNumber ~ fsDelta;
ssdn: Basics.LongNumber ~ [lc[smax.lc-ssup.lc]];
fsdn: Basics.LongNumber ~ [lc[fmax.lc-fsup.lc]];
sfup: Basics.LongNumber ~ sfDelta;
ffup: Basics.LongNumber ~ ffDelta;
sfdn: Basics.LongNumber ~ [lc[smax.lc-sfup.lc]];
ffdn: Basics.LongNumber ~ [lc[fmax.lc-ffup.lc]];
isup: CARDINAL ~ 1;
ifup: CARDINAL ~ 1;
isdn: CARDINAL ~ smax.hi-isup;
ifdn: CARDINAL ~ fmax.hi-ifup;
d1s, d1f: INTEGER; -- destination position at start of scan line
s1: Basics.LongNumber ¬ s0; -- source s corresponding to [d1s, d1f]
f1: Basics.LongNumber ¬ f0; -- source f corresponding to [d1s, d1f]
[d1s, d1f] ¬ d0;
WHILE d1s<box.min.s
DO
d1s ¬ d1s+1;
IF s1.lc<ssdn.lc THEN s1.lc ¬ s1.lc+ssup.lc ELSE s1.lc ¬ s1.lc-ssdn.lc;
IF f1.lc<fsdn.lc THEN f1.lc ¬ f1.lc+fsup.lc ELSE f1.lc ¬ f1.lc-fsdn.lc;
ENDLOOP;
WHILE d1s>box.min.s
DO
d1s ¬ d1s-1;
IF s1.lc>=ssup.lc THEN s1.lc ¬ s1.lc-ssup.lc ELSE s1.lc ¬ s1.lc+ssdn.lc;
IF f1.lc>=fsup.lc THEN f1.lc ¬ f1.lc-fsup.lc ELSE f1.lc ¬ f1.lc+fsdn.lc;
ENDLOOP;
d0 ¬ [d1s, d1f];
s0.lc ¬ s1.lc;
f0.lc ¬ f1.lc;
WHILE d1f<box.min.f
DO
d1f ¬ d1f+1;
IF s1.lc<sfdn.lc THEN s1.lc ¬ s1.lc+sfup.lc ELSE s1.lc ¬ s1.lc-sfdn.lc;
IF f1.lc<ffdn.lc THEN f1.lc ¬ f1.lc+ffup.lc ELSE f1.lc ¬ f1.lc-ffdn.lc;
ENDLOOP;
WHILE d1f>box.min.f
DO
d1f ¬ d1f-1;
IF s1.lc>=sfup.lc THEN s1.lc ¬ s1.lc-sfup.lc ELSE s1.lc ¬ s1.lc+sfdn.lc;
IF f1.lc>=ffup.lc THEN f1.lc ¬ f1.lc-ffup.lc ELSE f1.lc ¬ f1.lc+ffdn.lc;
ENDLOOP;
pixels.length ¬ count;
DO
--For each scan line of box--
FOR i:
NAT
IN [0..samplesPerPixel)
DO
map: ImagerSample.SampleMap ~ self[i];
rasterMap: ImagerSample.RasterSampleMap ~ WITH map SELECT FROM r: ImagerSample.RasterSampleMap => r ENDCASE => NIL;
samples: ImagerSample.SampleBuffer ~ pixels[i];
s: Basics.LongNumber ¬ s1;
f: Basics.LongNumber ¬ f1;
IF rasterMap#
NIL
AND rasterMap.base.bit=0
AND (rasterMap.bitsPerLine
MOD bitsPerWord)=0
AND rasterMap.bitsPerSample=8
THEN {
base: Pointer8 ~ LOOPHOLE[rasterMap.base.word];
unitsPerLine: NAT ~ rasterMap.bitsPerLine/bitsPerUnit;
result: LONG POINTER TO RawSamples ~ InlinePointerToSamples[samples, 0, count];
FOR k:
NAT
IN [0..count)
DO
-- Calculate i*
is0: CARDINAL ~ s.hi;
is1: CARDINAL ~ IF is0<isdn THEN is0+isup ELSE is0-isdn;
if0: CARDINAL ~ f.hi;
if1: CARDINAL ~ IF if0<ifdn THEN if0+ifup ELSE if0-ifdn;
-- Calculate w*
w11: CARDINAL ~ Basics.HighHalf[(LONG[s.lo]*f.lo)+LAST[CARD16]];
w10: CARDINAL ~ s.lo-w11;
w01: CARDINAL ~ f.lo-w11;
w00: CARDINAL ~ LAST[CARD16]-w01-w10-w11;
-- Calculate line*
line0: Pointer8 ~ base+LONG[is0]*unitsPerLine;
line1: Pointer8 ~ base+LONG[is1]*unitsPerLine;
TRUSTED {
-- Fetch v*
v00: CARDINAL ~ line0[if0];
v01: CARDINAL ~ line0[if1];
v10: CARDINAL ~ line1[if0];
v11: CARDINAL ~ line1[if1];
-- Calculate value
value:
CARDINAL ~ Basics.HighHalf[
(LONG[w00]*v00) + (LONG[w01]*v01) +
(LONG[w10]*v10) + (LONG[w11]*v11) + LAST[CARD16]
];
-- Store result
result[k] ¬ value;
};
-- Bump s and f
IF s.lc<sfdn.lc THEN s.lc ¬ s.lc+sfup.lc ELSE s.lc ¬ s.lc-sfdn.lc;
IF f.lc<ffdn.lc THEN f.lc ¬ f.lc+ffup.lc ELSE f.lc ¬ f.lc-ffdn.lc;
ENDLOOP;
}
ELSE {
-- the slow but general way
FOR k:
NAT
IN [0..count)
DO
is0: CARDINAL ~ s.hi;
is1: CARDINAL ~ IF is0<isdn THEN is0+isup ELSE is0-isdn;
if0: CARDINAL ~ f.hi;
if1: CARDINAL ~ IF if0<ifdn THEN if0+ifup ELSE if0-ifdn;
w11: CARDINAL ~ Basics.HighHalf[(LONG[s.lo]*f.lo)+LAST[CARD16]];
w10: CARDINAL ~ s.lo-w11;
w01: CARDINAL ~ f.lo-w11;
w00: CARDINAL ~ LAST[CARD16]-w01-w10-w11;
v00, v01, v10, v11, value: CARDINAL;
v00 ¬ ImagerSample.Get[map, [s: is0+self.box.min.s, f: if0+self.box.min.f]];
v01 ¬ ImagerSample.Get[map, [s: is0+self.box.min.s, f: if1+self.box.min.f]];
v10 ¬ ImagerSample.Get[map, [s: is1+self.box.min.s, f: if0+self.box.min.f]];
v11 ¬ ImagerSample.Get[map, [s: is1+self.box.min.s, f: if1+self.box.min.f]];
value ¬ Basics.HighHalf[
(LONG[w00]*v00) + (LONG[w01]*v01) +
(LONG[w10]*v10) + (LONG[w11]*v11) + LAST[CARD16]
];
samples[k] ¬ value;
IF s.lc<sfdn.lc THEN s.lc ¬ s.lc+sfup.lc ELSE s.lc ¬ s.lc-sfdn.lc;
IF f.lc<ffdn.lc THEN f.lc ¬ f.lc+ffup.lc ELSE f.lc ¬ f.lc-ffdn.lc;
ENDLOOP;
};
ENDLOOP;
action[pixels, [d1s, d1f]];
d1s ¬ d1s+1; IF NOT d1s<box.max.s THEN EXIT;
IF s1.lc<ssdn.lc THEN s1.lc ¬ s1.lc+ssup.lc ELSE s1.lc ¬ s1.lc-ssdn.lc;
IF f1.lc<fsdn.lc THEN f1.lc ¬ f1.lc+fsup.lc ELSE f1.lc ¬ f1.lc-fsdn.lc;
ENDLOOP;
};
-- Set increments --
[[rs, rf]] ¬ ImagerTransformation.InverseTransformVec[m, [0, 1]];
sfDelta.li ¬ ScaledFromRealMod[rs, sSize];
ffDelta.li ¬ ScaledFromRealMod[rf, fSize];
[[rs, rf]] ¬ ImagerTransformation.InverseTransformVec[m, [1, 0]];
ssDelta.li ¬ ScaledFromRealMod[rs, sSize];
fsDelta.li ¬ ScaledFromRealMod[rf, fSize];
-- Set initial position --
[[rs, rf]] ¬ ImagerTransformation.InverseTransform[m, [d0.s+0.5, d0.f+0.5]];
IF interpolate
AND HalfInteger[rs]
AND HalfInteger[rf]
AND sfDelta.lo = 0
AND ffDelta.lo = 0
AND ssDelta.lo = 0
AND fsDelta.lo = 0
THEN {
-- No need to interpolate, since all sampling points fall on pixel centers anyway --
interpolate ¬ FALSE;
};
IF interpolate THEN { rs ¬ rs-0.5; rf ¬ rf-0.5 };
s0.li ¬ ScaledFromRealMod[rs-self.box.min.s, sSize];
f0.li ¬ ScaledFromRealMod[rf-self.box.min.f, fSize];
boxes[IF interpolate THEN boxActionInterpolatedSamples ELSE boxActionPointSamples];
ReleaseScratchPixels[pixels];
};