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
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
|
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
include <mach.h>
include <knet.h>
include <fio.h>
include <fset.h>
include <imio.h>
include <imhdr.h>
include "fxf.h"
# ZFIOFXF -- FITS kernel virtual file driver. This maps the actual
# FITS file into the virtual pixel file expected by IMIO.
# FXFZOP -- Open the file driver for i/o. The filename has appended the
# string "_nnnnn", where 'nnnnn' is the FIT descriptor to the structure
# defined in "fit.h".
procedure fxfzop (pkfn, mode, status)
char pkfn[ARB] #I packed virtual filename from FIO
int mode #I file access mode (ignored)
int status #O output status - i/o channel if successful
pointer im, fit
int ip, indx, channel, strldx(), ctoi()
bool lscale, lzero, bfloat, fxf_fpl_equald()
char fname[SZ_PATHNAME]
begin
# Separate the FIT descriptor from the file name.
call strupk (pkfn, fname, SZ_PATHNAME)
ip = strldx ("_", fname)
indx = ip + 1
if (ctoi (fname, indx, fit) <= 0) {
status = ERR
return
}
# Determine if we have a Fits Kernel non supported
# data format; i.e. Bitpix -32 or -64 and BSCALE and/or
# BZERO with non default values.
### Only "low level" routines can be falled from a file driver:
### high level routines like syserr cannot be used due to
### recursion/reentrancy problems.
# We are calling syserrs at this level because we want to
# give the application the freedom to manipulate the FITS header
# at will and not imposing restriction at that level.
im = FIT_IM(fit)
lscale = fxf_fpl_equald (1.0d0, FIT_BSCALE(fit), 1)
lzero = fxf_fpl_equald (0.0d0, FIT_BZERO(fit), 1)
# Determine if scaling is necessary.
#bfloat = (!lscale || !lzero)
#if (bfloat && (FIT_BITPIX(fit) == -32 || FIT_BITPIX(fit) == -64)) {
# FIT_IOSTAT(fit) = ERR
# #call syserrs (SYS_FXFRDHSC,IM_HDRFILE(im))
# status = ERR
# return
#}
fname[ip] = EOS
call strpak (fname, fname, SZ_PATHNAME)
# Open the file.
call zopnbf (fname, mode, channel)
if (channel == ERR) {
status = ERR
return
}
status = fit
FIT_IO(fit) = channel
end
# FITZCL -- Close the FIT binary file driver.
procedure fxfzcl (chan, status)
int chan #I FIT i/o channel
int status #O output status
pointer fit
begin
fit = chan
call zclsbf (FIT_IO(fit), status)
end
# FXFZRD -- Read the FIT file (header and pixel data). An offset pointer
# needs to be set to point to the data portion of the file. If we are reading
# pixel data, the scale routine fxf_unpack_data is called. We need to keep
# a counter (npix_read) with the current number of pixels unpacked since we
# don't want to convert beyond the total number of pixels; where the last
# block of data read can contain zeros or garbage up to a count of 2880 bytes.
procedure fxfzrd (chan, obuf, nbytes, boffset)
int chan #I FIT i/o channel
char obuf[ARB] #O output buffer
int nbytes #I nbytes to be read
int boffset #I file offset at which read commences
pointer fit, im
int ip, pixtype, nb
int status, totpix, npix
int datasizeb, pixoffb, nb_skipped, i
double dtemp
real rtemp, rscale, roffset
include <szpixtype.inc>
begin
fit = chan
im = FIT_IM(fit)
FIT_IOSTAT(fit) = OK
totpix = IM_PHYSLEN(im,1)
do i = 2, IM_NPHYSDIM(im)
totpix = totpix * IM_PHYSLEN(im,i)
if (FIT_ZCNV(fit) == YES) {
if (FIT_PIXTYPE(fit) != TY_REAL && FIT_PIXTYPE(fit) != TY_DOUBLE) {
call fxf_cnvpx (im, totpix, obuf, nbytes, boffset)
return
}
}
pixtype = IM_PIXTYPE(im)
datasizeb = totpix * (pix_size[pixtype] * SZB_CHAR)
pixoffb = (FIT_PIXOFF(fit) - 1) * SZB_CHAR + 1
# We can read the data directly into the caller's output buffer as
# any FITS kernel input conversions are guaranteed to not make the
# data smaller.
call zardbf (FIT_IO(fit), obuf, nbytes, boffset)
call zawtbf (FIT_IO(fit), status)
if (status == ERR) {
FIT_IOSTAT(fit) = ERR
return
}
### boffset is 1-indexed, so one would expect (boffset/SZB_CHAR) to
### be ((boffset - 1) * SZB_CHAR + 1). This is off by one from what
### is being calculated, so if PIXOFF and boffset point to the same
### place IP will be one, which happens to be the correct array index.
### Nonehtless expressions like this should be written out so that
### they can be verified easily by reading them. Any modern compiler
### will optimize the expression, we don't have to do this in the
### source code.
ip = FIT_PIXOFF(fit) - boffset/SZB_CHAR
if (ip <= 0)
ip = 1
nb_skipped = boffset - pixoffb
if (nb_skipped <= 0)
nb = min (status + nb_skipped, datasizeb)
else
nb = min (status, datasizeb - nb_skipped)
npix = max (0, nb / (pix_size[pixtype] * SZB_CHAR))
if (FIT_ZCNV(fit) == YES) {
if (FIT_PIXTYPE(fit) == TY_REAL) {
# This is for scaling -32 (should not be allowed)
call fxf_zaltrr(obuf[ip], npix, FIT_BSCALE(fit), FIT_BZERO(fit))
} else if (FIT_PIXTYPE(fit) == TY_DOUBLE) {
# This is for scaling -64 data (should not be allowed)
call fxf_zaltrd(obuf[ip], npix, FIT_BSCALE(fit), FIT_BZERO(fit))
}
} else {
call fxf_unpack_data (obuf[ip],
npix, pixtype, FIT_BSCALE(fit), FIT_BZERO(fit))
}
end
procedure fxf_zaltrr (data, npix, bscale, bzero)
real data[ARB], rt
int npix
double bscale, bzero
int i
begin
call ieevupkr (data, data, npix)
do i = 1, npix {
data[i] = data[i] * bscale + bzero
}
end
procedure fxf_zaltrd (data, npix, bscale, bzero)
double data[ARB]
int npix
double bscale, bzero
int i
begin
call ieevupkd (data, data, npix)
do i = 1, npix
data[i] = data[i] * bscale + bzero
end
# FXFZWR -- Write to the output file.
procedure fxfzwr (chan, ibuf, nbytes, boffset)
int chan #I QPF i/o channel
char ibuf[ARB] #O data buffer
int nbytes #I nbytes to be written
int boffset #I file offset
pointer fit, im, sp, obuf
bool noconvert, lscale, lzero, bfloat
int ip, op, pixtype, npix, totpix, nb, nchars, i
int datasizeb, pixoffb, nb_skipped, obufsize
bool fxf_fpl_equald()
include <szpixtype.inc>
begin
fit = chan
im = FIT_IM(fit)
FIT_IOSTAT(fit) = OK
# We don't have to pack the data if it is integer and we don't need
# to byte swap; the data buffer can be written directly out.
# Determine if we are writing into an scaled floating point data
# unit; i.e. bitpix > 0 and BSCALE or/and BZERO with non default
# values. This is an error since we are not supporting this
# combination for writing at this time.
lscale = fxf_fpl_equald (1.0d0, FIT_BSCALE(fit), 1)
lzero = fxf_fpl_equald (0.0d0, FIT_BZERO(fit), 1)
# Determine if scaling is necessary.
bfloat = (!lscale || !lzero)
if (bfloat &&
(IM_PIXTYPE(im) == TY_REAL || IM_PIXTYPE(im) == TY_DOUBLE)) {
FIT_IOSTAT(fit) = ERR
return
}
pixtype = IM_PIXTYPE(im)
noconvert = ((pixtype == TY_SHORT && BYTE_SWAP2 == NO) ||
((pixtype == TY_INT || pixtype == TY_LONG) && BYTE_SWAP4 == NO))
if (noconvert) {
call zawrbf (FIT_IO(fit), ibuf, nbytes, boffset)
return
}
# Writing pixel data to an image is currently illegal if on-the-fly
# conversion is in effect, as on-the-fly conversion is currently only
# available for reading.
if (FIT_ZCNV(fit) == YES) {
FIT_IOSTAT(fit) = ERR
return
}
totpix = IM_PHYSLEN(im,1)
do i = 2, IM_NPHYSDIM(im)
totpix = totpix * IM_PHYSLEN(im,i)
datasizeb = totpix * (pix_size[pixtype] * SZB_CHAR)
pixoffb = (FIT_PIXOFF(fit) - 1) * SZB_CHAR + 1
### Same comments as for fxfzrd apply here.
### There doesn't appear to be any support here for byte data like
### in fxfzwr. This must mean that byte images are read-only.
### This shouldn't be necessary, but we shouldn't try to do anything
### about it until the fxf_byte_short issue is addressed.
ip = FIT_PIXOFF(fit) - boffset / SZB_CHAR
if (ip <= 0)
ip = 1
nb_skipped = boffset - pixoffb
if (nb_skipped <= 0)
nb = min (nbytes + nb_skipped, datasizeb)
else
nb = min (nbytes, datasizeb - nb_skipped)
npix = max (0, nb / (pix_size[pixtype] * SZB_CHAR))
if (npix == 0)
return
# We don't do scaling (e.g. BSCALE/BZERO) when writing. All the
# generated FITS files in this interface are ieee fits standard.
### I didn't look into it but I don't understand this; when accessing
### a BSCALE image read-write, it should be necessary to scale both
### when reading and writing if the application sees TY_REAL pixels.
### When writing a new image I suppose the application would take
### care of any scaling.
# Convert any pixel data in the input buffer to the binary format
# required for FITS and write it out. Any non-pixel data in the
# buffer should be left as-is.
obufsize = (nbytes + SZB_CHAR-1) / SZB_CHAR
call smark (sp)
call salloc (obuf, obufsize, TY_CHAR)
# Preserve any leading non-pixel data.
op = 1
if (ip > 1) {
nchars = min (obufsize, ip - 1)
call amovc (ibuf[1], Memc[obuf], nchars)
op = op + nchars
}
# Convert and output the pixels.
call fxf_pak_data (ibuf[ip], Memc[obuf+op-1], npix, pixtype)
op = op + npix * pix_size[pixtype]
# Preserve any remaining non-pixel data.
nchars = obufsize - op + 1
if (nchars > 0)
call amovc (ibuf[op], Memc[obuf+op-1], nchars)
# Write out the data.
call zawrbf (FIT_IO(fit), Memc[obuf], nbytes, boffset)
call sfree (sp)
end
# FXFZWT -- Return the number of bytes transferred in the last i/o request.
procedure fxfzwt (chan, status)
int chan #I QPF i/o channel
int status #O i/o channel status
pointer fit, im
begin
fit = chan
im = FIT_IM(fit)
# A file driver returns status for i/o only in the AWAIT routine;
# hence any i/o errors occurring in the FK itself are indicated by
# setting FIT_IOSTAT. Otherwise the actual i/o operation must have
# been submitted, and we call zawtbf to wait for i/o, and get status.
if (FIT_IOSTAT(fit) != OK)
status = FIT_IOSTAT(fit)
else
call zawtbf (FIT_IO(fit), status)
# FIT_ZBYTES has the correct number of logical bytes that need
# to be passed to fio since we are expanding the buffer size
# from byte to short or real and short to real.
if (status > 0) {
if (FIT_PIXTYPE(fit) == TY_UBYTE)
status = FIT_ZBYTES(fit)
else if (FIT_PIXTYPE(fit) == TY_SHORT && IM_PIXTYPE(im) == TY_REAL)
status = FIT_ZBYTES(fit)
}
end
# FXFZST -- Query device/file parameters.
procedure fxfzst (chan, param, value)
int chan #I FIT i/o channel
int param #I parameter to be returned
int value #O parameter value
pointer fit, im
int i, totpix, szb_pixel, szb_real
include <szpixtype.inc>
begin
fit = chan
im = FIT_IM(fit)
totpix = IM_PHYSLEN(im,1)
do i = 2, IM_NPHYSDIM(im)
totpix = totpix * IM_PHYSLEN(im,i)
szb_pixel = pix_size[IM_PIXTYPE(im)] * SZB_CHAR
szb_real = SZ_REAL * SZB_CHAR
call zsttbf (FIT_IO(fit), param, value)
if (param == FSTT_FILSIZE) {
switch (FIT_PIXTYPE(fit)) {
case TY_SHORT:
if (IM_PIXTYPE(im) == TY_REAL) {
value = value + int ((totpix * SZ_SHORT * SZB_CHAR) /
2880. + .5) * 2880
}
case TY_UBYTE:
if (IM_PIXTYPE(im) == TY_SHORT)
value = value + int (totpix/2880. + 0.5)*2880
else if (IM_PIXTYPE(im) == TY_REAL)
value = value + int(totpix*(szb_real-1)/2880. + 0.5) * 2880
}
}
end
# FXF_CNVPX -- Convert FITS type BITPIX = 8 to SHORT or REAL depending
# on the value of BSCALE, BZERO (1, 32768 is already iraf supported as ushort
# and is not treated in here). If BITPIX=16 and BSCALE and BZERO are
# non-default then the pixels are converted to REAL.
procedure fxf_cnvpx (im, totpix, obuf, nbytes, boffset)
pointer im #I Image descriptor
int totpix #I Total number of pixels
char obuf[ARB] #O Output data buffer
int nbytes #I Size in bytes of the output buffer
int boffset #I Byte offset into the virtual image
pointer sp, buf, fit, op
double bscale, bzero
int ip, nelem, pfactor
int pixtype, nb, buf_size, bzoff, nboff
int status, offset, npix
int datasizeb, pixoffb, nb_skipped
include <szpixtype.inc>
begin
fit = IM_KDES(im)
bscale = FIT_BSCALE(fit)
bzero = FIT_BZERO(fit)
ip = FIT_PIXOFF(fit) - boffset/SZB_CHAR
if (ip <= 0)
ip = 1
# The beginning of the data portion in bytes.
pixoffb = (FIT_PIXOFF(fit)-1) * SZB_CHAR + 1
# Determine the factor to applied: size(im_pixtype)/size(fit_pixtype)
if (FIT_PIXTYPE(fit) == TY_UBYTE) {
if (IM_PIXTYPE(im) == TY_REAL)
pfactor = SZ_REAL * SZB_CHAR
else # TY_SHORT
pfactor = SZB_CHAR
datasizeb = totpix
} else if (FIT_PIXTYPE(fit) == TY_SHORT) {
pfactor = SZ_REAL / SZ_SHORT
pixtype = TY_SHORT
datasizeb = totpix * (pix_size[pixtype] * SZB_CHAR)
} else {
FIT_IOSTAT(fit) = ERR
return
}
# We need to map the virtual image of type im_pixtype to the actual
# file of type fit_pixtype. 'nbytes' is the number of bytes to read
# from the virtual image. To find out how many fit_pixtype bytes
# we need to read from disk we need to subtract the FITS
# header size (if boffset is 1) from nbytes and then divide
# the resultant value by the convertion factor.
# We then add the size of the header if necessary.
# Determine the offset into the pixel area.
nboff = boffset - pixoffb
if (nboff > 0) {
nelem = nboff / pfactor
offset = nelem + pixoffb
} else {
# Keep the 1st boffset.
bzoff = boffset
offset = boffset
}
# Calculates the number of elements to convert. We keep the offset from
# the beginning of the unit (bzoff) and not from file's 1st byte.
nelem = nbytes - (pixoffb - bzoff + 1)
nelem = nelem / pfactor
buf_size = nelem + (pixoffb - bzoff + 1)
if (buf_size*pfactor > nbytes && ip == 1)
buf_size = (nbytes - 1) / pfactor + 1
# Allocate space for TY_SHORT
call smark(sp)
call salloc (buf, buf_size/SZB_CHAR, TY_SHORT)
call zardbf (FIT_IO(fit), Mems[buf], buf_size, offset)
call zawtbf (FIT_IO(fit), status)
if (status == ERR) {
FIT_IOSTAT(fit) = ERR
call sfree (sp)
return
}
# Map the number of bytes of datatype FIT_PIXTYPE to
# IM_PIXTYPE for use in zfxfwt().
if (status*pfactor >= nbytes)
FIT_ZBYTES(fit) = nbytes
else
FIT_ZBYTES(fit) = status * pfactor
nb_skipped = offset - pixoffb
if (nb_skipped <= 0)
nb = min (status + nb_skipped, datasizeb)
else
nb = min (status, datasizeb - nb_skipped)
switch (FIT_PIXTYPE(fit)) {
case TY_UBYTE:
npix = max (0, nb)
if (IM_PIXTYPE(im) == TY_SHORT)
call achtbs (Mems[buf+ip-1], obuf[ip], npix)
else {
# Scaled from byte to REAL.
call achtbl (Mems[buf+ip-1], obuf[ip], npix)
call fxf_altmr (obuf[ip], obuf[ip], npix, bscale, bzero)
}
case TY_SHORT:
op = buf + ip - 1
npix = max (0, nb / (pix_size[pixtype] * SZB_CHAR))
if (BYTE_SWAP2 == YES)
call bswap2 (Mems[op], 1, Mems[op], 1, npix*SZB_CHAR)
call fxf_astmr (Mems[op], obuf[ip], npix, bscale, bzero)
}
call sfree (sp)
end
|