CoonsWarpInner:
PROC ~ {
Highly optimized version (incremental and INT32)
640x480 timing tests:
b&w without pointers: 22 sec pointsamp, 80 sec filtered
b&w with pointers: 16 sec pointsamp, 77 sec filtered
rgb with pointers: 32 sec pointsamp, 304 sec filtered
rgb: BOOL ¬ pa2 # NIL AND pa3 # NIL; -- rgb or b&w?
line1: SampleBuffer ¬ ImagerSample.ObtainScratchSamples[du+1]; -- bw or r
line2: SampleBuffer ¬ ImagerSample.ObtainScratchSamples[du+1]; -- g or unused
line3: SampleBuffer ¬ ImagerSample.ObtainScratchSamples[du+1]; -- b or unused
Resample the outline curves with equal spacing at dest resolution
qu0: PairSequence ¬ G2dContour.ResamplePairs[curves[0], du+1];
q1v: PairSequence ¬ G2dContour.ResamplePairs[curves[1], dv+1];
qu1: PairSequence ¬ G2dContour.ResamplePairs[curves[2], du+1];
q0v: PairSequence ¬ G2dContour.ResamplePairs[curves[3], dv+1];
pu0: Int32PairSequence ¬ NEW[Int32PairSequenceRep[du+1]];
pu1: Int32PairSequence ¬ NEW[Int32PairSequenceRep[du+1]];
p0v: Int32PairSequence ¬ NEW[Int32PairSequenceRep[dv+1]];
p1v: Int32PairSequence ¬ NEW[Int32PairSequenceRep[dv+1]];
buv: Int32PairSequence ¬ NEW[Int32PairSequenceRep[du+1]];
dbuv: Int32PairSequence ¬ NEW[Int32PairSequenceRep[du+1]];
c00, c10, c11, c01, c0v, c1v, dc0v, dc1v: Int32Pair;
shift: NAT ~ 20; -- number of fractional bits
scale: REAL ~ LOOPHOLE[Basics.BITLSHIFT[LOOPHOLE[INT32[1]], shift], INT32];
recipscale: REAL ~ 1./scale;
Reverse the last two curves
[] ¬ G2dVector.ReverseSequence[qu1, qu1];
[] ¬ G2dVector.ReverseSequence[q0v, q0v];
Quantize the real curves to integer curves
FOR u:
NAT
IN [0..du]
DO
pu0[u] ¬ Int32ize[qu0[u], scale];
pu1[u] ¬ Int32ize[qu1[u], scale];
ENDLOOP;
FOR v:
NAT
IN [0..dv]
DO
p0v[v] ¬ Int32ize[q0v[v], scale];
p1v[v] ¬ Int32ize[q1v[v], scale];
ENDLOOP;
Infer the four corner points (somewhat arbitrary since curves don't necessarily join)
c00 ¬ Int32PairMidpoint[pu0[0], p0v[0]];
c10 ¬ Int32PairMidpoint[pu0[du], p1v[0]];
c11 ¬ Int32PairMidpoint[pu1[du], p1v[dv]];
c01 ¬ Int32PairMidpoint[pu1[0], p0v[dv]];
Setup for incremental inner loops
c0v ¬ c00; dc0v ¬ [(c01.x-c00.x)/dv, (c01.y-c00.y)/dv];
c1v ¬ c10; dc1v ¬ [(c11.x-c10.x)/dv, (c11.y-c10.y)/dv];
FOR u:
NAT
IN [0..du]
DO
buv[u] ¬ pu0[u];
dbuv[u] ¬ [(pu1[u].x-pu0[u].x)/dv, (pu1[u].y-pu0[u].y)/dv];
ENDLOOP;
buv.length ¬ dbuv.length ¬ du+1;
Warp!
FOR v:
NAT
IN [0..dv]
WHILE
NOT control.abort
DO
TRUSTED {
auv: Int32Pair ¬ [p0v[v].x-c0v.x, p0v[v].y-c0v.y];
dauv: Int32Pair ¬ [(p1v[v].x-c1v.x-auv.x)/du, (p1v[v].y-c1v.y-auv.y)/du];
buvp: LONG POINTER TO Int32Pair ¬ @buv[0];
dbuvp: LONG POINTER TO Int32Pair ¬ @dbuv[0];
lp1: LONG POINTER TO Sample ¬ @line1[0];
lp2: LONG POINTER TO Sample ¬ @line2[0];
lp3: LONG POINTER TO Sample ¬ @line3[0];
IF control.filter = point
THEN
-- point sample
FOR u:
NAT
IN [0..du]
DO
x:
INT32 ¬
LOOPHOLE[Basics.BITRSHIFT[LOOPHOLE[auv.x+buvp.x], shift]];
y:
INT32 ¬
LOOPHOLE[Basics.BITRSHIFT[LOOPHOLE[auv.y+buvp.y], shift]];
IF x >= 0
AND x < dx
AND y >= 0
AND y < dy
THEN {
lp1 ¬ pa1[y][x];
IF rgb THEN {lp2 ¬ pa2[y][x]; lp3 ¬ pa3[y][x]};
}
ELSE {
lp1 ¬ 0;
IF rgb THEN {lp2 ¬ 0; lp3 ¬ 0};
};
auv ¬ [auv.x+dauv.x, auv.y+dauv.y];
buvp ¬ [buvp.x+dbuvp.x, buvp.y+dbuvp.y];
buvp ¬ buvp+SIZE[Int32Pair];
dbuvp ¬ dbuvp+SIZE[Int32Pair];
lp1 ¬ lp1+SIZE[Sample];
IF rgb THEN {lp2 ¬ lp2+SIZE[Sample]; lp3 ¬ lp3+SIZE[Sample]};
ENDLOOP
ELSE
-- bilinear interp
FOR u:
NAT
IN [0..du]
DO
x: REAL ¬ (auv.x+buvp.x)*recipscale;
y: REAL ¬ (auv.y+buvp.y)*recipscale;
IF x >= 0
AND x < dx
AND y >= 0
AND y < dy
THEN {
lp1 ¬ BiLerp[pa1, x, y];
IF rgb THEN {lp2 ¬ BiLerp[pa2, x, y]; lp3 ¬ BiLerp[pa3, x, y]};
}
ELSE {
lp1 ¬ 0;
IF rgb THEN {lp2 ¬ 0; lp3 ¬ 0};
};
auv ¬ [auv.x+dauv.x, auv.y+dauv.y];
buvp ¬ [buvp.x+dbuvp.x, buvp.y+dbuvp.y];
buvp ¬ buvp+SIZE[Int32Pair];
dbuvp ¬ dbuvp+SIZE[Int32Pair];
lp1 ¬ lp1+SIZE[Sample];
IF rgb THEN {lp2 ¬ lp2+SIZE[Sample]; lp3 ¬ lp3+SIZE[Sample]};
ENDLOOP;
ImagerSample.PutSamples[dest[0].map, [v, u0],, line1, 0, du+1];
IF rgb
THEN {
ImagerSample.PutSamples[dest[1].map, [v, u0],, line2, 0, du+1];
ImagerSample.PutSamples[dest[2].map, [v, u0],, line3, 0, du+1];
};
c0v ¬ [c0v.x+dc0v.x, c0v.y+dc0v.y];
c1v ¬ [c1v.x+dc1v.x, c1v.y+dc1v.y];
};
ENDLOOP;
ImagerSample.ReleaseScratchSamples[line1];
ImagerSample.ReleaseScratchSamples[line2];
};