aboutsummaryrefslogtreecommitdiff
path: root/sys/plio/tf/plr2li.x
blob: f6fb6c79dd6f543f062e0df6e09eb1ce78fad76a (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
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.

include	<plset.h>
include	<plio.h>

# PL_R2L -- Convert a range list to a line list.  The length of the output
# line list is returned as the function value.

int procedure pl_r2li (rl_src, xs, ll_dst, npix)

int	rl_src[3,ARB]		#I input range list
int	xs			#I starting pixel index in range list
short	ll_dst[ARB]		#O destination line list
int	npix			#I number of pixels to convert

int	hi, pv
int	last, xe, x1, x2, iz, op, np, nz, nr, dv, v, i
define	done_ 91

begin
	# No input pixels?
	nr = RL_LEN(rl_src)
	if (npix <= 0 || nr <= 0)
	    return (0)

	# Initialize the linelist header.
	LL_VERSION(ll_dst) = LL_CURVERSION
	LL_HDRLEN(ll_dst) = LL_CURHDRLEN
	LL_NREFS(ll_dst) = 0
	LL_SETBLEN(ll_dst,0)

	xe = xs + npix - 1
	op = LL_CURHDRLEN + 1
	iz = xs
	hi = 1

	# Process the array of range lists.
	do i = RL_FIRST, nr + 1 {
	    if (i <= nr) {
		# Load next range.
		x1 = rl_src[1,i]
		np = rl_src[2,i]
		pv = rl_src[3,i]
		x2 = x1 + np - 1
		last = x2

		# Get an inbounds range.
		if (x1 > xe)
		    break
		else if (xs > x2)
		    next
		else if (x1 < xs)
		    x1 = xs
		else if (x2 > xe)
		    x2 = xe

		# Go again if nothing inbounds.
		nz = x1 - iz
		np = x2 - x1 + 1
		if (np <= 0)
		    next

	    } else if (iz < xe) {
		# At end of input range list, but need to output a ZN.
		nz = xe - iz + 1
		np = 0
		pv = 0
	    } else
		break

	    # Encode an instruction to regenerate the current range I0-IP
	    # of N data values of nonzero level PV.  In the most complex case
	    # we must update the high value and output a range of zeros,
	    # followed by a range of NP high values.  If NP is 1, we can
	    # probably use a PN or [ID]S instruction to save space.

	    # Change the high value?
	    if (pv > 0) {
		dv = pv - hi
		if (dv != 0) {
		    # Output IH or DH instruction?
		    hi = pv
		    if (abs(dv) > I_DATAMAX) {
			ll_dst[op] = M_SH + and (int(pv), I_DATAMAX)
			op = op + 1
			ll_dst[op] = pv / I_SHIFT
			op = op + 1
		    } else {
			if (dv < 0)
			    ll_dst[op] = M_DH + (-dv)
			else
			    ll_dst[op] = M_IH + dv
			op = op + 1

			# Convert to IS or DS if range is a single pixel.
			if (np == 1 && nz == 0) {
			    v = ll_dst[op-1]
			    ll_dst[op-1] = or (v, M_MOVE)
			    goto done_
			}
		    }
		}
	    }

	    # Output range of zeros to catch up to current range?
	    if (nz > 0) {
		# Output the ZN instruction.
		for (;  nz > 0;  nz = nz - (I_DATAMAX-1)) {
		    ll_dst[op] = M_ZN + min(I_DATAMAX-1,nz)
		    op = op + 1
		}
		# Convert to PN if range is a single pixel.
		if (np == 1 && pv > 0 && x2 == last) {
		    ll_dst[op-1] = ll_dst[op-1] + M_PN + 1
		    goto done_
		}
	    }

	    # The only thing left is the HN instruction if we get here.
	    for (;  np > 0;  np = np - I_DATAMAX) {
		ll_dst[op] = M_HN + min(I_DATAMAX,np)
		op = op + 1
	    }
done_
	    iz = x2 + 1
	}

	LL_SETLEN(ll_dst, op - 1)
	return (op - 1)
end