PROCEDURE FromMaps(a, b: REF Map; score: LONG; sign: SIGN): T = BEGIN WITH NX = NUMBER(a^[0]), NY = NUMBER(a^) DO <* ASSERT NUMBER(b^[0]) = NX *> <* ASSERT NUMBER(b^) = NY *> RETURN T{ score := score, a := a, b := b, sign := sign } END END FromMaps; PROCEDURE GetPixels( READONLY im: T; READONLY p: Points; noPixel: Pixel; VAR v: Pixels; ); (* Stores in "v[k]" the value of image "im" at point "p[k]". Uses "NoPoint" if "p[k]" is out-of-bounds. *) READONLY imNew: MSImage.T; (* Target image, at finer scale. *) noPixel: NAT; (* "Null" pixel color. *) PROCEDURE FloatAndFilterRow(yp: NAT) = (* If scanline "yp" exists, stores its horizontally filtered and sampled version in "loHor[]", "hiHor[]". *) BEGIN IF yp < NYI THEN WITH k = yp MOD NW DO FloatRow(im[yp], loFlt, hiFlt); FilterRow(loFlt, hiFlt, w, loHor[k], hiHor[k]) END END END FloatAndFilterRow; PROCEDURE FloatRow(READONLY im: Pixels; VAR loFlt, hiFlt: Longs) = (* Given a row "im" of the input image, converts each pixel "im[k]" into a floating-point interval "[loFlt[k], hiFlt[k]]". *) VAR p: NAT; BEGIN FOR xp := 0 TO NXI-1 DO p := im[xp]; IF p = noPixel THEN loFlt[xp] := 0.0d0; hiFlt[xp] := 1.0d0 ELSE IF p > noPixel THEN DEC(p) END; WITH s = FLOAT(p, LONG) * inScale DO loFlt[xp] := s; hiFlt[xp] := s END; END END; END FloatRow; PROCEDURE FilterRow( READONLY loFlt, hiFlt: Longs; READONLY w: Weights; VAR loHor, hiHor: Longs; ) = (* Horizonally filters and samples a scanline of the image. Takes the lower and upper bounds "loFlt[k]" and "hiFlt[k]" to the input image pixels. Stores in "loHor[i]" and "hiHor[i]" the upper and lower bound to the filtered image pixels. Assumes that the weights "w" add to one. *) VAR wloSum, whiSum, wSum: LONG := 0.0d0; BEGIN <* ASSERT NUMBER(w) MOD 2 = 1 *> FOR xf := 0 TO LAST(loHor) DO WITH xp = 2*xf DO FOR r := -MIN(HW, LAST(loFlt)-xp) TO MIN(HW, xp) DO WITH W = w[r + HW] DO wloSum := wloSum + W * loFlt[xp - r]; whiSum := whiSum + W * hiFlt[xp - r]; wSum := wSum + W END END END; loHor[xf] := wloSum; hiHor[xf] := whiSum + (1.0d0 - wSum); END END FilterRow; PROCEDURE FilterColumns( yp: NAT; READONLY loHor, hiHor: ARRAY OF Longs; VAR loFil, hiFil: Longs; ) = (* Given a set of "NW" consecutive scanlines, already fitered and sampled in the horizontal direction, filters and samples them in the vertical direction. Assumes that input scanline "y" is stored in "loHor[y MOD NW]", "hiHor[y MOD NW]". Returns the result in "loFil", "hiFil". *) VAR wSum, wloSum, whiSum: LONG; BEGIN FOR xf := 0 TO NXO-1 DO wSum := 0.0d0; wloSum := 0.0d0; whiSum := 0.0d0; FOR r := -MIN(yp, HW) TO MIN(NYI-1-yp, HW) DO WITH W = w[r + HW], k = (yp + r) MOD NW DO wloSum := wloSum + W * loHor[k, xf]; whiSum := whiSum + W * hiHor[k, xf]; wSum := wSum + W END END; loFil[xf] := wloSum; hiFil[xf] := whiSum + (1.0d0 - wSum); END END FilterColumns; PROCEDURE FixRow(READONLY loFil, hiFil: Longs; VAR ot: Pixels) = (* Converts each pixel from a floating-point interval "[loFil[xp],hiFil[xp]]" to a pixel value. If the interval is too wide, outputs "noPixel", else quantizes the interval's center value (skipping the "noPixel" value). *) VAR p: NAT; BEGIN WITH scale = 0.5d0 * otScale DO FOR xp := 0 TO LAST(im) DO WITH lo = loFil[xp], hi = hiFil[xp] DO IF noPixel <= LAST(Pixel) AND hi - lo > eps THEN p := noPixel ELSE p := ROUND((hi + lo) * scale); IF p >= noPixel THEN INC(p) END; END; ot[xp] := p END END END END FixRow;