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
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
|
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
include <syserr.h>
include <mach.h>
include <imio.h>
include <imhdr.h>
include <mii.h>
include <plset.h>
include <pmset.h>
include "fxf.h"
# FXFPLWRITE.X -- Routines to handle masks in FITS extensions.
#
# fxf_plwrite (im, fd)
# fxf_plinfo (im, maxlen, pcount, depth)
# fxf_pl_adj_heap (im, hdr_fd, pcount)
# fxf_copy_adj (im, in_fd, hdroff, poff, datasize)
# fxf_plpf (im)
#
# FXF_PLWRITE -- Write the data from a PLIO mask into the data area of a
# FITS compressed image (ZIMAGE) binary table extension. The data is
# written to the file pointed to by file descriptor FD.
#
# The data to be written consists of the data for the ZIMAGE binary table
# records, followed by the heap area of the BINTABLE extension, which
# contains the actual encoded line lists. For simplicity we assume that
# the table contains only one column, the COMPRESSED_DATA column, which is
# of type variable length integer array. Each element of this column is a
# BINTABLE variable length array descriptor which physically consists of two
# integer values: an integer giving the length of the stored array (encoded
# line list), followed by an integer (in byte unit) giving the offset of
# the array data (encoded line list) in the heap area. Multiple variable
# length array descriptors may point to the same stored array, and in
# fact PLIO uses this feature to implement compression in the Y direction
# (adjacent mask lines will point to the same encoded line list).
# The code here supports masks of up to 3 dimensions.
procedure fxf_plwrite (im, fd)
pointer im #I image descriptor
int fd #I output file descriptor
int i, j, v_in[PL_MAXDIM], lp_len
int naxes, axlen[PL_MAXDIM], depth
int heap_offset, ep_off, lp_off, vararray[2]
pointer pl, lp, op, emptyline, lastline
int pl_llen()
pointer pl_access(), pl_emptyline()
errchk pl_access
begin
pl = IM_PL(im)
call pl_gsize (pl, naxes, axlen, depth)
# Write the COMPRESSED_DATA table column. This is an index giving
# the length and heap offset of the encoded PLIO line list for each
# line of the image. Multiple image lines (index entries) may point
# to the same stored line list: this happens if a mask line is empty
# (the empty line) or if successive lines are all the same. For the
# sake of simplicity, only masks of up to 3 dimensions are supported.
op = 0
heap_offset = 0
emptyline = pl_emptyline (pl)
ep_off = -1
lastline = NULL
lp_off = -1
call amovkl(long(1), v_in, PL_MAXDIM)
do j = 1, axlen[3] {
v_in[3] = j
do i = 1, axlen[2] {
v_in[2] = i
lp = pl_access (pl, v_in)
lp_len = pl_llen (Mems[lp])
if (lp == emptyline && ep_off >= 0)
op = ep_off
else if (lp == lastline)
op = lp_off
else
op = heap_offset
vararray[1] = lp_len
# The offsets on the FITS BINTABLE is in byte unit
# as establish by the FITS standard.
vararray[2] = op * 2 # Byte offset
call miiwritei (fd, vararray, 2)
lastline = lp
lp_off = op
if (lp == emptyline && ep_off < 0)
ep_off = op
if (op == heap_offset)
heap_offset = heap_offset + lp_len
}
}
# Now write the line list data to the heap area. The logic here must
# follow that above or the line offsets won't match.
ep_off = -1
lp_off = -1
lastline = NULL
do j = 1, axlen[3] {
v_in[3] = j
do i = 1, axlen[2] {
v_in[2] = i
lp = pl_access (pl, v_in)
lp_len = pl_llen (Mems[lp])
if (lp == emptyline && ep_off >= 0)
next
else if (lp == lastline)
next
call miiwrites (fd, Mems[lp], lp_len)
lastline = lp
if (lp == emptyline && ep_off < 0)
ep_off = 0
}
}
end
# FXF_PLINFO -- Examine a PLIO mask and compute the maximum length of an
# encoded line list, and the storage in bytes required to store the mask
# data in the heap area of a FITS binary table.
procedure fxf_plinfo (im, maxlen, pcount, depth)
pointer im #I image descriptor
int maxlen #O maximum line list length
int pcount #O storage required to store mask (bytes)
int depth #O mask depth
int naxes, axlen[PL_MAXDIM]
int i, j, v_in[PL_MAXDIM], lp_len
int heap_offset, ep_off, lp_off
pointer pl, lp, op, emptyline, lastline
int pl_llen()
pointer pl_access(), pl_emptyline()
errchk pl_access
begin
pl = IM_PL(im)
call pl_gsize (pl, naxes, axlen, depth)
op = 0
maxlen = 0
heap_offset = 0
emptyline = pl_emptyline (pl)
ep_off = -1
lastline = NULL
lp_off = -1
call amovkl(long(1), v_in, PL_MAXDIM)
# The following must duplicate the logic above for determining what
# gets written to the heap area. All we are doing here is computing
# the amount of heap storage required to store the compressed mask.
do j = 1, axlen[3] {
v_in[3] = j
do i = 1, axlen[2] {
v_in[2] = i
lp = pl_access (pl, v_in)
lp_len = pl_llen (Mems[lp])
maxlen = max (maxlen, lp_len)
if (lp == emptyline && ep_off >= 0)
op = ep_off
else if (lp == lastline)
op = lp_off
else
op = heap_offset
lastline = lp
lp_off = op
if (lp == emptyline && ep_off < 0)
ep_off = op
if (op == heap_offset)
heap_offset = heap_offset + lp_len
}
}
pcount = heap_offset * (SZ_SHORT * SZB_CHAR)
end
# FXF_PL_ADJ_HEAP -- Resize heap when we have a hole bigger than 2880 bytes
# or if we overwrite the next extension.
procedure fxf_pl_adj_heap (im, hdr_fd, pcount)
pointer im #I imio descriptor
int hdr_fd #U file descriptor
int pcount #I new heap size in bytes
pointer fk, hdrp, pixp
int datasize, hdroff, diff, nb, group, i
begin
fk = IM_KDES(im)
# Calculate the size of the TABLE data. (8 bytes per line)
datasize = FIT_LENAXIS(fk,1)*FIT_LENAXIS(fk,2)*
FIT_LENAXIS(fk,3)
datasize = (datasize + pcount)/SZB_CHAR
call fxf_not_incache(im)
hdrp = FIT_HDRPTR(fk)
pixp = FIT_PIXPTR(fk)
group = FIT_GROUP(fk)
hdroff = Memi[hdrp+group]
# Calculate the amount of space left or grown in the heap
# as a result of the READ-WRITE operation on the data.
diff = datasize - (Memi[hdrp+group+1] - Memi[pixp+group])
# See if the new data overwrites the next unit or
# there is a hole with more than 2880 bytes.
if ( (diff > 0) || ((-diff / 2880) > 0) ) {
# Adjust the header and pixel offset for subsequent groups.
# Add header size.
datasize = datasize + Memi[pixp+group] - Memi[hdrp+group]
call fxf_copy_adj (im, hdr_fd, hdroff, Memi[hdrp+group+1], datasize)
if (diff > 0)
nb = FITS_LEN_CHAR (diff)
else
nb = (diff / 1440) * 1440
# Update FK cache offset values
do i = group+1, FIT_NUMOFFS(fk) {
Memi[hdrp+i] = Memi[hdrp+i] + nb
if (Memi[pixp+i] > 0) {
Memi[pixp+i] = Memi[pixp+i] + nb
} else
break
}
}
end
# FXF_COPY_ADJ -- Make a copy of the input file extending or shrinking
# the heap area.
procedure fxf_copy_adj (im, in_fd, hdroff, poff, datasize)
pointer im #I Imio descriptor
int in_fd #I Input file descriptor
int hdroff #I Header offset
int poff #I Pixel offset
int datasize #I New FITS unit size
pointer sp, tempfile, outname
int nchars, junk, inoff, out_fd, size
int fnldir(), fnroot(), open(), note()
errchk open, note, seek, close, delete, rename
errchk fxf_make_adj_copy, fxf_write_blanks
begin
call smark (sp)
call salloc (tempfile, SZ_FNAME, TY_CHAR)
call salloc (outname, SZ_FNAME, TY_CHAR)
nchars = fnldir (IM_HDRFILE(im), Memc[tempfile], SZ_FNAME)
junk = fnroot (IM_HDRFILE(im), Memc[tempfile+nchars], SZ_FNAME)
call mktemp (Memc[tempfile], Memc[outname], SZ_PATHNAME)
call strcat (".fits", Memc[outname], SZ_PATHNAME)
inoff = note (in_fd)
out_fd = open (Memc[outname], NEW_FILE, BINARY_FILE)
call fxf_make_adj_copy (in_fd, out_fd, hdroff, poff, datasize)
# Pad to 2880 bytes block
size = note (out_fd) - 1
size = mod(size, FITS_BLOCK_CHARS)
if (size != 0) {
size = FITS_BLOCK_CHARS - size
call fxf_write_blanks (out_fd, size)
}
size = note (out_fd) - 1
call close (in_fd)
call delete (IM_HDRFILE(im))
call rename (Memc[outname], IM_HDRFILE(im))
in_fd = out_fd
call seek (in_fd, inoff)
call sfree (sp)
end
# FXF_PLPF -- Initialize IMIO dependencies when dealing with a PLIO
# image mask.
procedure fxf_plpf (im)
pointer im #I IMIO descriptor
int pfd
pointer sp, imname, ref_im
int sv_acmode, sv_update, ndim, i, depth
errchk iki_opix, open
int open()
begin
call smark (sp)
call salloc (imname, SZ_IMNAME, TY_CHAR)
# Complete the initialization of a mask image.
ref_im = IM_PLREFIM(im)
sv_acmode = IM_ACMODE(im)
sv_update = IM_UPDATE(im)
call strcpy (IM_NAME(im), Memc[imname], SZ_IMNAME)
if (ref_im != NULL) {
# Create a mask the same size as the physical size of the
# reference image. Inherit any image section from the
# reference image.
IM_NDIM(im) = IM_NDIM(ref_im)
IM_NPHYSDIM(im) = IM_NPHYSDIM(ref_im)
IM_SECTUSED(im) = IM_SECTUSED(ref_im)
call amovl (IM_LEN(ref_im,1), IM_LEN(im,1), IM_MAXDIM)
call amovl (IM_PHYSLEN(ref_im,1),IM_PHYSLEN(im,1),IM_MAXDIM)
call amovl (IM_SVLEN(ref_im,1), IM_SVLEN(im,1), IM_MAXDIM)
call amovl (IM_VMAP(ref_im,1), IM_VMAP(im,1), IM_MAXDIM)
call amovl (IM_VOFF(ref_im,1), IM_VOFF(im,1), IM_MAXDIM)
call amovl (IM_VSTEP(ref_im,1), IM_VSTEP(im,1), IM_MAXDIM)
# Tell PMIO to use this image as the reference image.
call pm_seti (IM_PL(im), P_REFIM, im)
} else if (sv_acmode == NEW_IMAGE || sv_acmode == NEW_COPY) {
# If ndim was not explicitly set, compute it by counting
# the number of nonzero dimensions.
ndim = IM_NDIM(im)
if (ndim == 0) {
ndim = 1
while (IM_LEN(im,ndim) > 0 && ndim <= IM_MAXDIM)
ndim = ndim + 1
ndim = ndim - 1
IM_NDIM(im) = ndim
}
# Make sure dimension stuff makes sense.
if (ndim < 0 || ndim > IM_MAXDIM)
call imerr (IM_NAME(im), SYS_IMNDIM)
do i = 1, ndim
if (IM_LEN(im,i) <= 0)
call imerr (IM_NAME(im), SYS_IMDIMLEN)
# Set the unused higher dimensions to 1. This makes it
# possible to access the image as if it were higher
# dimensional, and in a way it truely is.
do i = ndim + 1, IM_MAXDIM
IM_LEN(im,i) = 1
IM_NPHYSDIM(im) = ndim
call amovl (IM_LEN(im,1), IM_PHYSLEN(im,1), IM_MAXDIM)
call amovl (IM_LEN(im,1), IM_SVLEN(im,1), IM_MAXDIM)
if (sv_acmode == NEW_IMAGE)
call amovkl (long(1), IM_VSTEP(im,1), IM_MAXDIM)
depth = PL_MAXDEPTH
if (and (IM_PLFLAGS(im), PL_BOOL) != 0)
depth = 1
call pl_ssize (IM_PL(im), IM_NDIM(im), IM_LEN(im,1), depth)
}
call strcpy (Memc[imname], IM_NAME(im), SZ_IMNAME)
IM_ACMODE(im) = sv_acmode
IM_UPDATE(im) = sv_update
IM_PIXOFF(im) = 1
IM_HGMOFF(im) = NULL
IM_BLIST(im) = NULL
IM_HFD(im) = NULL
pfd = open ("dev$null", READ_WRITE, BINARY_FILE)
IM_PFD(im) = pfd
# Execute this even if pixel file has already been opened.
call imsetbuf (IM_PFD(im), im)
# "Fast i/o" in the conventional sense no IMIO buffering)
# is not permitted for mask images, since IMIO must buffer
# the pixels, which are generated at run time.
if (IM_FAST(im) == YES) {
IM_PLFLAGS(im) = or (IM_PLFLAGS(im), PL_FAST)
IM_FAST(im) = NO
}
call sfree (sp)
end
|