aboutsummaryrefslogtreecommitdiff
path: root/pkg/images/imgeom/src/blkav.gx
blob: 9c83ebab2af9eaec26159ecf94a8af1f351a36f9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.

include	<imhdr.h>
include	<error.h>

define	AVG		1	# operation = arithmetic average
define	SUM		2	# operation = arithmetic sum

# change to (lrdx) in future
$for (lrd)

# BLKAVG -- Block average or sum on n-dimensional images.
# For example, block averaging by a factor of 2 means that pixels 1 and 2
# are averaged to produce the first output pixel, 3 and 4 are averaged to
# produce the second output pixel, and so on.  Remainder pixels at the end
# of a line, col, etc. are averaged correctly.

procedure blkav$t (im1, im2, blkfac, option)

pointer	im1			# input image
pointer im2			# output image
int	blkfac[IM_MAXDIM]	# blocking factors
int	option			# block operation (average, sum, ...)

int	num_oblks[IM_MAXDIM], i, count, ndim, dim, nlines_in_sum, nfull_blkx
int	junk, num_ilines, num_olines, oline
long	blkin_s[IM_MAXDIM], blkin_e[IM_MAXDIM]
long	vin_s[IM_MAXDIM], vin_e[IM_MAXDIM], vout[IM_MAXDIM]
$if (datatype != l)
PIXEL	sum
$else
real	sum
$endif
pointer	sp, accum_ptr, iline_ptr, oline_ptr

int	blkcomp(), imggs$t(), impnl$t() 
errchk	imggs$t(), impnl$t()

begin
	call smark (sp)
	call salloc (accum_ptr, IM_LEN(im1, 1), TY_PIXEL)

	# Initialize; input and output vectors, block counters.
	ndim = IM_NDIM(im1)
	nfull_blkx = IM_LEN(im1, 1) / blkfac[1]
	blkin_s[1] = long(1)
	blkin_e[1] = long(IM_LEN(im1, 1))
	vin_s[1]   = blkin_s[1]
	vin_e[1]   = blkin_e[1]

	do i = 1, ndim {
	    num_oblks[i] = (IM_LEN(im1,i) + blkfac[i] - 1) / blkfac[i]
	    IM_LEN(im2, i) = num_oblks[i]
	}
	num_olines = 1
	do i = 2, ndim
	    num_olines = num_olines * num_oblks[i]
	call amovkl (long(1), vout, IM_MAXDIM)

	# For each sequential output-image line, ...
	do oline = 1, num_olines {

	    call aclr$t (Mem$t[accum_ptr], IM_LEN(im1, 1))
	    nlines_in_sum = 0

	    # Compute block vector; initialize dim>1 input vector.
	    num_ilines = blkcomp (im1, blkfac, vout, blkin_s, blkin_e,
		vin_s, vin_e)

	    # Output pointer; note impnl$t returns vout for NEXT output line.
	    junk = impnl$t (im2, oline_ptr, vout)

	    # For all input lines mapping to current output line, ...
	    do i = 1, num_ilines {
		# Get line from input image.
		iline_ptr = imggs$t (im1, vin_s, vin_e, ndim)

		# Increment general section input vector between block bounds.
		do dim = 2, ndim {
		    if (vin_s[dim] < blkin_e[dim]) {
			vin_s[dim] = vin_s[dim] + 1
			vin_e[dim] = vin_s[dim]
			break
		    } else {
			vin_s[dim] = blkin_s[dim]
			vin_e[dim] = vin_s[dim]
		    }
		}

		# Accumulate line into block sum.  Keep track of no. of 
		# lines in sum so that we can compute block average later.

		call aadd$t (Mem$t[iline_ptr], Mem$t[accum_ptr],
		    Mem$t[accum_ptr], IM_LEN(im1,1))
		nlines_in_sum = nlines_in_sum + 1
	    }

	    # We now have a templine of sums; average/sum into output buffer
	    # first the full blocks using a vop.
	    if (option == AVG)
		call abav$t (Mem$t[accum_ptr], Mem$t[oline_ptr], nfull_blkx,
		    blkfac[1])
	    else
		call absu$t (Mem$t[accum_ptr], Mem$t[oline_ptr], nfull_blkx,
		    blkfac[1])

	    # Now average/sum the final partial block in x, if any.
	    if (nfull_blkx < num_oblks[1]) {
		sum = 0$f
		count = 0
		do i = nfull_blkx * blkfac[1] + 1, IM_LEN(im1,1) {
		    sum = sum + Mem$t[accum_ptr+i-1]
		    count = count + 1
		}
		if (option == AVG)
		    Mem$t[oline_ptr+num_oblks[1]-1] = sum / count
		else
		    Mem$t[oline_ptr+num_oblks[1]-1] = sum
	    }
		
	    # Block average into output line from the sum of all lines block
	    # averaged in X.
	    if (option == AVG)
		call adivk$t (Mem$t[oline_ptr], PIXEL(nlines_in_sum),
		    Mem$t[oline_ptr], num_oblks[1])
	}
	
	call sfree (sp)
end

$endfor