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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
|
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
#### load2.x (from load.x) ####
include <mach.h>
include <imset.h>
include <imhdr.h>
include <error.h>
include <gki.h>
include <fio.h>
include <fset.h>
include "gwindow.h"
include "../lib/ids.h"
include "cv.h"
# DS_LOAD_DISPLAY -- Map an image into the display window. In general this
# involves independent linear transformations in the X, Y, and Z (greyscale)
# dimensions. If a spatial dimension is larger than the display window then
# the image is block averaged. If a spatial dimension or a block averaged
# dimension is smaller than the display window then linear interpolation is
# used to expand the image. Both the input image and the output device appear
# to us as images, accessed via IMIO.
#
# World coordinate system 0 (WCS 0) defines the position and size of the device
# window in NDC coordinates (0-1 in either axis). WCS 1 assigns a pixel
# coordinate system to the same window. If we convert the NDC coordinates of
# the window into device coordinates in pixels, then the ratios of the window
# coordinates in pixels to the image coordinates in pixels defines the real
# magnification factors for the two spatial axes. If the pixel coordinates
# are out of bounds then the image will be displayed centered in the window
# with zero fill at the edges. If the frame has not been erased then the fill
# areas must be explicitly zeroed.
procedure ds_load_display (im, wdes, border_erase)
pointer im # input image
pointer wdes # graphics window descriptor
bool border_erase
int wx1, wx2, wy1, wy2 # device window to be filled with image data
real px1, px2, py1, py2 # image coords in fractional image pixels
real pxsize, pysize # size of image section in fractional pixels
real wxcenter, wycenter # center of device window in frac device pixels
real xmag, ymag # x,y magnification ratios
pointer w0, w1 # world coord systems 0 (NDC) and 1 (pixel)
include "cv.com"
begin
# Compute pointers to WCS 0 and 1.
w0 = W_WC(wdes,0)
w1 = W_WC(wdes,1)
# Compute X and Y magnification ratios required to map image into
# the device window in device pixel units.
xmag = (W_XE(w0) - W_XS(w0)) * cv_xres / (W_XE(w1) - W_XS(w1))
ymag = (W_YE(w0) - W_YS(w0)) * cv_yres / (W_YE(w1) - W_YS(w1))
# Compute the coordinates of the image section to be displayed.
# This is not necessarily the same as WCS 1 since the WCS coords
# need not be inbounds.
px1 = max (1.0, W_XS(w1))
px2 = min (real (IM_LEN(im,1)), W_XE(w1))
py1 = max (1.0, W_YS(w1))
py2 = min (real (IM_LEN(im,2)), W_YE(w1))
# Now compute the coordinates of the image section to be written in
# device pixel units. This section must lie within or on the device
# window.
# This computation for I2S will give 257, which does differ by one
# for the Y center (due to inversion in I2S). This should not matter,
# but if it does, this comment will change!
pxsize = px2 - px1
pysize = py2 - py1
wxcenter = (W_XE(w0) + W_XS(w0)) / 2.0 * cv_xres + 1
wycenter = (W_YE(w0) + W_YS(w0)) / 2.0 * cv_yres + 1
wx1 = max (1, int (wxcenter - (pxsize / 2.0 * xmag)))
wx2 = max (wx1, min (cv_xres, int (wx1 + (pxsize * xmag))))
wy1 = max (1, int (wycenter - (pysize / 2.0 * ymag)))
wy2 = max (wy1, min (cv_yres, int (wy1 + (pysize * ymag))))
# Display the image data, ignoring zero filling at the boundaries.
call ds_map_image (im, px1,px2,py1,py2, wx1,wx2,wy1,wy2,
W_ZS(w1), W_ZE(w1), W_ZT(w1), W_UPTR(w1))
# Zero the border of the window if the frame has not been erased,
# and if the displayed section does not occupy the full window.
if (border_erase)
call ds_erase_border (im, wdes, wx1,wx2,wy1,wy2)
end
# DS_MAP_IMAGE -- Map an image section from the input image to a section
# (window) of the output image (the display device). All spatial scaling is
# handled by the "scaled input" package, i.e., SIGL2[SR]. Our task is to
# get lines from the scaled input image, transform the greyscale if necessary,
# and write the lines to the output device.
procedure ds_map_image (im, px1,px2,py1,py2, wx1,wx2,wy1,wy2, z1,z2,zt, uptr)
pointer im # input image
real px1,px2,py1,py2 # input section
int wx1,wx2,wy1,wy2 # output section
real z1,z2 # range of input greylevels to be mapped.
int zt # log or linear greylevel transformation
pointer uptr # pointer to user transformation table
bool unitary_greyscale_transformation
short lut1, lut2, z1_s, z2_s, dz1_s, dz2_s
real dz1, dz2
int wy, nx, ny, xblk, yblk
pointer in, out, si
pointer sigl2s(), sigl2r(), sigl2_setup()
errchk sigl2s, sigl2r, sigl2_setup
real xs, xe, y
pointer sp, outr
bool fp_equalr()
real if_elogr()
extern if_elogr
include "cv.com"
begin
call smark (sp)
# Set up for scaled image input.
nx = wx2 - wx1 + 1
ny = wy2 - wy1 + 1
xblk = INDEFI
yblk = INDEFI
si = sigl2_setup (im, px1,px2,nx,xblk, py1,py2,ny,yblk)
# Output array, and limiting x values in NDC
call salloc (out, nx, TY_SHORT)
xs = real(wx1 - 1) * cv_xcon / GKI_MAXNDC
# Don't subtract 1 from wx2 as we want it to be first one not filled
xe = real(wx2) * cv_xcon / GKI_MAXNDC
if ( xe > 1.0)
xe = 1.0
# The device ZMIN and ZMAX parameters define the acceptable range
# of greyscale values for the output device (e.g., 0-255 for most 8-bit
# display devices). For the general display, we use 0 and the
# device "z" resolution. Values Z1 and Z2 are mapped linearly or
# logarithmically into these.
dz1 = 0
dz2 = cv_zres-1
# If the user specified the transfer function, see that the
# intensity and greyscale values are in range.
if (zt == W_USER) {
call alims (Mems[uptr], SZ_BUF, lut1, lut2)
dz1_s = short (dz1)
dz2_s = short (dz2)
if (lut2 < dz1_s || lut1 > dz2_s)
call eprintf ("User specified greyscales out of range\n")
if (z2 < IM_MIN(im) || z1 > IM_MAX(im))
call eprintf ("User specified intensities out of range\n")
}
# Type short pixels are treated as a special case to minimize vector
# operations for such images (which are common). If the image pixels
# are either short or real then only the ALTR (greyscale transformation)
# vector operation is required. The ALTR operator linearly maps
# greylevels in the range Z1:Z2 to DZ1:DZ2, and does a floor ceiling
# of DZ1:DZ2 on all pixels outside the range. If unity mapping is
# employed the data is simply copied, i.e., floor ceiling constraints
# are not applied. This is very fast and will produce a contoured
# image on the display which will be adequate for some applications.
if (zt == W_UNITARY)
unitary_greyscale_transformation = true
else
unitary_greyscale_transformation =
(fp_equalr (dz1,z1) && fp_equalr (dz2,z2)) || fp_equalr (z1,z2)
if (IM_PIXTYPE(im) == TY_SHORT && zt != W_LOG) {
# Set dz1_s and dz2_s depending on transformation
if (zt != W_USER) {
dz1_s = short (dz1)
dz2_s = short (dz2)
} else {
dz1_s = short (STARTPT)
dz2_s = short (ENDPT)
}
z1_s = short (z1)
z2_s = short (z2)
for (wy=wy1; wy <= wy2; wy=wy+1) {
in = sigl2s (si, wy - wy1 + 1)
y = real(wy-1) * cv_ycon / GKI_MAXNDC
if (unitary_greyscale_transformation)
call gpcell (cv_gp, Mems[in], nx, 1, xs, y, xe, y)
else if (zt == W_USER) {
call amaps (Mems[in], Mems[out], nx, z1_s,z2_s, dz1_s,dz2_s)
call aluts (Mems[out], Mems[out], nx, Mems[uptr])
call gpcell (cv_gp, Mems[out], nx, 1, xs, y, xe, y)
} else {
call amaps (Mems[in], Mems[out], nx, z1_s,z2_s, dz1_s,dz2_s)
call gpcell (cv_gp, Mems[out], nx, 1, xs, y, xe, y)
}
}
} else {
call salloc (outr, nx, TY_REAL)
for (wy=wy1; wy <= wy2; wy=wy+1) {
in = sigl2r (si, wy - wy1 + 1)
y = real(wy - 1) * cv_ycon / GKI_MAXNDC
if (zt == W_LOG) {
call amapr (Memr[in], Memr[outr], nx,
z1, z2, 1.0, 10.0 ** MAXLOG)
call alogr (Memr[outr], Memr[outr], nx, if_elogr)
call amapr (Memr[outr], Memr[outr], nx,
1.0, real(MAXLOG), dz1, dz2)
call achtrs (Memr[outr], Mems[out], nx)
} else if (unitary_greyscale_transformation) {
call achtrs (Memr[in], Mems[out], nx)
} else if (zt == W_USER) {
call amapr (Memr[in], Memr[outr], nx, z1,z2, STARTPT,ENDPT)
call achtrs (Memr[outr], Mems[out], nx)
call aluts (Mems[out], Mems[out], nx, Mems[uptr])
} else {
call amapr (Memr[in], Memr[outr], nx, z1, z2, dz1, dz2)
call achtrs (Memr[outr], Mems[out], nx)
}
call gpcell (cv_gp, Mems[out], nx, 1, xs, y, xe, y)
}
}
call sfree (sp)
call sigl2_free (si)
end
# DS_ERASE_BORDER -- Zero the border of the window if the frame has not been
# erased, and if the displayed section does not occupy the full window.
# It would be more efficient to do this while writing the greyscale data to
# the output image, but that would complicate the display procedures and frames
# are commonly erased before displaying an image.
procedure ds_erase_border (im, wdes, wx1,wx2,wy1,wy2)
pointer im # input image
pointer wdes # window descriptor
int wx1,wx2,wy1,wy2 # section of display window filled by image data
int dx1,dx2,dy1,dy2 # coords of full display window in device pixels
int j, n, n1
pointer w0
pointer sp, zero
real xls, xle, xrs, xre, y
include "cv.com"
begin
call smark (sp)
call salloc (zero, cv_xres, TY_SHORT)
call aclrs (Mems[zero], cv_xres)
# Compute device pixel coordinates of the full display window.
w0 = W_WC(wdes,0)
dx1 = W_XS(w0) * (cv_xres - 1) + 1
dx2 = W_XE(w0) * (cv_xres - 1) + 1
dy1 = W_YS(w0) * (cv_yres - 1) + 1
dy2 = W_YE(w0) * (cv_yres - 1) + 1
# Determine left and right (exclusive), start and end, x values in NDC
# for pixels not already filled.
# If, say, dx1 < wx1, we want to clear dx1 through wx1-1, which means
# that for gpcell, we want the (right) end points to be the first
# pixel not cleared.
xls = real(dx1 - 1) * cv_xcon / GKI_MAXNDC
xle = real(wx1) * cv_xcon / GKI_MAXNDC
if (xle > 1.0)
xle = 1.0
xre = real(dx2 - 1) * cv_xcon / GKI_MAXNDC
xrs = real(wx2) * cv_xcon / GKI_MAXNDC
if (xre > 1.0)
xre = 1.0
# Erase lower margin.
n = dx2 - dx1 + 1
for (j=dy1; j < wy1; j=j+1) {
y = real(j-1) * cv_ycon / GKI_MAXNDC
call gpcell (cv_gp, Mems[zero], n, 1, xls, y, xre, y)
}
# Erase left and right margins. By doing the right margin of a line
# immediately after the left margin we have a high liklihood that the
# display line will still be in the FIO buffer.
n = wx1 - dx1
n1 = dx2 - wx2
for (j=wy1; j <= wy2; j=j+1) {
y = real(j-1) * cv_ycon / GKI_MAXNDC
if (dx1 < wx1)
call gpcell (cv_gp, Mems[zero], n, 1, xls, y, xle, y)
if (wx2 < dx2)
call gpcell (cv_gp, Mems[zero], n1, 1, xrs, y, xre, y)
}
# Erase upper margin.
n = dx2 - dx1 + 1
for (j=wy2+1; j <= dy2; j=j+1) {
y = real(j-1) * cv_ycon / GKI_MAXNDC
call gpcell (cv_gp, Mems[zero], n, 1, xls, y, xre, y)
}
call sfree (sp)
end
# IF_ELOG -- The error function for log10. Note that MAX_EXPONENT is
# currently an integer so it is converted to the appropriate data type
# before being returned.
real procedure if_elogr (x)
real x # the input pixel value
begin
return (real(-MAX_EXPONENT))
end
|