aboutsummaryrefslogtreecommitdiff
path: root/pkg/xtools/cogetr.x
blob: 823d54f3ba4beee45e6a8a787855dd31391fff01 (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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.

include	<imhdr.h>
include	"cogetr.h"

# COGETR -- Get a real column vector from a 2D image.
#
# This procedure is designed to be efficient when:
#	1.  The columns are accessed sequentially.
#	2.  The number of lines does not change.
#	3.  The first and last lines change slowly with column.
# One such case is when the entire column of an image is required.  Then
# the first and last lines do not change at all.  Another type of use
# occurs when dealing with features which are aligned nearly
# with the image lines.  For example objects in a long slit spectrum or
# Echelle orders.
#
# As the columns are accessed sequentially new lines are added to a
# scrolled buffer only when the first and last lines fall outside the
# buffer.  If the buffer size is insufficient to hold the all the columns
# then the buffer is set to contain a block of columns.  When the desired
# column is outside the block of columns then a new block is read.
# The buffer is created and initialized when the buffer pointer
# is null or when the number of lines requested is changed.  Both the
# buffer and the column data pointer are allocated in this procedure.
# The user must free the buffers with the procedure COUNMAP.

pointer procedure cogetr (co, col, line1, line2)

pointer	co		# COIO pointer
int	col		# Column
int	line1		# First image line of column vector
int	line2		# Last image line of column vector

int	ncols, nlines, lastc1, lastl1, lastl2
int	i, imlen1, imlen2, col1, nc
pointer	im, coldata, buffer, buf, data

pointer	imgl2r()

begin
	# Dereference the structure elements to improve the readability of
	# the code and reduce the Mem index arithmetic.

	im = CO_IM(co)
	coldata = CO_DATA(co)
	buffer = CO_BUF(co)
	ncols = CO_NCOLS(co)
	nlines = CO_NLINES(co)
	lastc1 = CO_COL1(co)
	lastl1 = CO_LINE1(co)
	lastl2 = CO_LINE2(co)
	imlen1 = IM_LEN (im, 1)
	imlen2 = IM_LEN (im, 2)

	# If memory has not been allocated then allocate it.
	# If the number of lines changes reallocate the buffer and
	# initialize lastc1 to zero to force a full buffer read.

	i = min (imlen2, (line2 - line1 + 1) + 2 * EXTRA)

	if ((buffer == NULL) || (nlines != i)) {
	    nlines = i
	    ncols = min (imlen1, CO_MAXBUF(co) / nlines)
	    lastc1 = 0

	    call mfree (coldata, TY_REAL)
	    call mfree (buffer, TY_REAL)
	    call malloc (coldata, line2 - line1 + 1, TY_REAL)
	    call malloc (buffer, ncols * nlines, TY_REAL)

	    CO_DATA(co) = coldata
	    CO_BUF(co) = buffer
	    CO_NCOLS(co) = ncols
	    CO_NLINES(co) = nlines
	}

	# Determine the starting column and the number of columns per line.

	col1 = ((col - 1) / ncols) * ncols + 1
	nc = min (ncols, imlen1 - col1 + 1)

	# If there is no overlap with the last buffer then read all the
	# requested lines.  Otherwise read only the image lines with are
	# different from the last buffer.

	if ((col1 != lastc1) || (line1 > lastl2) || (line2 < lastl1)) {
	    lastc1 = col1
	    lastl1 = max (1, line1 - EXTRA)
	    lastl2 = min (imlen2, line2 + EXTRA)
	    do i = lastl1, lastl2 {
	        buf = buffer + mod (i, nlines) * ncols
		call amovr (Memr[imgl2r(im, i)+col1-1], Memr[buf], nc)
	    }
	    CO_COL1(co) = lastc1
	    CO_LINE1(co) = lastl1
	    CO_LINE2(co) = lastl2

	} else if (line1 < lastl1) {
	    do i = max (1, line1 - EXTRA), min (imlen2, lastl1 - 1) {
	        buf = buffer + mod (i, nlines) * ncols
		call amovr (Memr[imgl2r(im, i)+col1-1], Memr[buf], nc)
	    }
	    lastl1 = max (1, line1 - EXTRA)
	    lastl2 = min (imlen2, line2 + EXTRA)
	    CO_LINE1(co) = lastl1
	    CO_LINE2(co) = lastl2

	} else if (line2 > lastl2) {
	    do i = max (1, lastl2 + 1), min (imlen2, line2 + EXTRA) {
	        buf = buffer + mod (i, nlines) * ncols
		call amovr (Memr[imgl2r(im, i)+col1-1], Memr[buf], nc)
	    }
	    lastl1 = max (1, line1 - EXTRA)
	    lastl2 = min (imlen2, line2 + EXTRA)
	    CO_LINE1(co) = lastl1
	    CO_LINE2(co) = lastl2
	}

	# Set the column data vector.

	data = coldata
	do i = line1, line2 {
	    buf = buffer + mod (i, nlines) * ncols
	    Memr[data] = Memr[buf+col-col1]
	    data = data + 1
	}

	return (coldata)
end


# COMAP -- Map the column access

pointer procedure comap (im, maxbuf)

pointer	im		# IMIO pointer
int	maxbuf		# Maximum buffer size
pointer	co		# Returned pointer

begin
	call malloc (co, LEN_CO, TY_LONG)
	CO_IM(co) = im
	CO_MAXBUF(co) = maxbuf
	CO_DATA(co) = NULL
	CO_BUF(co) = NULL

	return (co)
end


# COUMAP -- Unmap the column access

procedure counmap (co)

pointer	co			# Pointer to buffer structure

begin
	call mfree (CO_DATA(co), TY_REAL)
	call mfree (CO_BUF(co), TY_REAL)
	call mfree (co, TY_LONG)
end