miriad 4.1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/ext/xyio.c ADDED
@@ -0,0 +1,476 @@
1
+ /************************************************************************/
2
+ /* */
3
+ /* Routines to access and manipulate an image. */
4
+ /* */
5
+ /* History: */
6
+ /* rjs Dark-ages Original version. */
7
+ /* rjs 6nov89 Neatly handle the case of a non-existent mask file.*/
8
+ /* rjs 7feb90 Added comments, ready to be stripped out by "doc". */
9
+ /* rjs 13jul92 Improved error messages in xyopen, to appease nebk.*/
10
+ /* rjs 23feb93 Include maxdimc.h, which contains maxnax. */
11
+ /* rjs 6nov94 Change item handle to an integer. */
12
+ /* rjs 27feb96 Added xyflush. */
13
+ /* rjs 15mar96 Inlcude an exrta include file. */
14
+ /* pjt 17jun02 MIR4 prototypes, > 2GB patches */
15
+ /* rjs/pjt 3jun03 "append" mode in xyopen - long live non-CVS devel. */
16
+ /*----------------------------------------------------------------------*/
17
+
18
+ #include <stdio.h>
19
+ #include <string.h>
20
+ #include <sys/types.h>
21
+ #include <unistd.h>
22
+
23
+ #include "maxdimc.h"
24
+ #include "io.h"
25
+ #include "miriad.h"
26
+
27
+ #define OLD 1
28
+ #define NEW 2
29
+ #define MK_FLAGS 1
30
+ #define MK_RUNS 2
31
+ #define check(x) if(x)bugno_c('f',x)
32
+ #define CHECK(x,a) if(x) { bug_c('w',((void)sprintf a,message)); \
33
+ bugno_c('f',x); \
34
+ }
35
+ #define ERROR(sev,a) bug_c(sev,((void)sprintf a,message))
36
+
37
+ static char message[132];
38
+
39
+ static struct {
40
+ char *mask;
41
+ int image;
42
+ int naxis,axes[MAXNAX],mask_exists,image_exists;
43
+ off_t offset;
44
+ } images[MAXOPEN];
45
+
46
+ #define Strcpy (void)strcpy
47
+
48
+ static void xymkopen_c(int thandle,int mode);
49
+
50
+ /************************************************************************/
51
+ void xyopen_c(int *thandle,Const char *name,Const char *status,int naxis,int *axes)
52
+ /**xyopen -- Open an image file. */
53
+ /*:image-i/o */
54
+ /*+ FORTRAN call sequence:
55
+
56
+ subroutine xyopen(tno,name,status,naxis,axes)
57
+ integer tno,naxis,axes(naxis)
58
+ character name*(*),status*(*)
59
+
60
+ This opens an image file. For an old file, determine the size of
61
+ each axe. For a new file, it writes out this info.
62
+
63
+ Input:
64
+ name The name of the file to be opened.
65
+ status Either 'old', 'new' or 'append'.
66
+ naxis The maximum number of axes that the calling program can
67
+ handle. For an 'old' file, if the data file has fewer
68
+ than naxis axes, the higher dimensions are treated as having
69
+ only one element. If the data file has more than naxis
70
+ axes, and the higher dimensions are more than 1 element
71
+ deep, xyopen bombs out.
72
+ Input or Output:
73
+ axes This is input for status='new' and output for status='old'.
74
+ It gives the number of elements along each axis.
75
+ Output:
76
+ tno The handle of the output file. */
77
+ /*----------------------------------------------------------------------*/
78
+ {
79
+ int iostat,length,access,tno,i,ndim,npix,temp;
80
+ char *stat,*mode,naxes[16],s[ITEM_HDR_SIZE];
81
+
82
+ if(!strcmp("old",status)) { access = OLD; mode = "read"; stat = "old";}
83
+ else if(!strcmp("append",status)){ access = OLD; mode = "append";stat = "old";}
84
+ else if(!strcmp("new",status)) { access = NEW; mode = "write"; stat = "new";}
85
+ else
86
+ ERROR('f',(message,"Unrecognised status when opening %s, in XYOPEN",name));
87
+
88
+ /* Access the image data. */
89
+
90
+ hopen_c(&tno,name,stat,&iostat);
91
+ CHECK(iostat,(message,"Error opening %s, in XYOPEN",name));
92
+ haccess_c(tno,&(images[tno].image),"image",mode,&iostat);
93
+ CHECK(iostat,(message,"Error accessing pixel data of %s, in XYOPEN",name));
94
+
95
+ /*----------------------------------------------------------------------*/
96
+ /* */
97
+ /* Handle an old image. Get number of axes, and then the length */
98
+ /* of each axis. Also compute and check that the size of the */
99
+ /* image file looks OK. */
100
+ /* */
101
+ /*----------------------------------------------------------------------*/
102
+
103
+ if(access == OLD){
104
+ rdhdi_c(tno,"naxis",&ndim,0);
105
+ if(ndim <= 0 || ndim > MAXNAX)
106
+ ERROR('f',(message,"Bad number of dimensions for %s in XYOPEN",name));
107
+
108
+ Strcpy(naxes,"naxis0");
109
+ length = strlen(naxes) - 1;
110
+ npix = 1;
111
+ for(i=0; i<max(ndim,naxis); i++){
112
+ naxes[length] ++;
113
+ if(i < ndim) rdhdi_c(tno,naxes,&temp,0);
114
+ else temp = 1;
115
+ if(temp <= 0)
116
+ ERROR('f',(message,"Bad image dimension for %s, in XYOPEN",name));
117
+ npix = npix * temp;
118
+ if(i < naxis) axes[i] = temp;
119
+ else if(temp > 1)
120
+ ERROR('f',(message,"Too many dimensions for %s, in XYOPEN",name));
121
+ }
122
+
123
+ /* Check the file size if OK and that it starts with the "real_item"
124
+ sequence. */
125
+
126
+ if(hsize_c(images[tno].image) < H_REAL_SIZE*npix+ITEM_HDR_SIZE)
127
+ ERROR('f',(message,"Pixel data for %s appears too small, in XYOPEN",name));
128
+ hreadb_c(images[tno].image,s,0,ITEM_HDR_SIZE,&iostat);
129
+ CHECK(iostat,(message,"Error reading pixel data label for %s, in XYOPEN",name));
130
+ if( memcmp(s,real_item,ITEM_HDR_SIZE) )
131
+ ERROR('f',(message,"Bad pixel data label for %s, in XYOPEN",name));
132
+
133
+ /*----------------------------------------------------------------------*/
134
+ /* */
135
+ /* A new image. Write out all the axes infomation, and initialise */
136
+ /* the file with the "binary item" sequence. */
137
+ /* */
138
+ /*----------------------------------------------------------------------*/
139
+
140
+ } else {
141
+ wrhdi_c(tno,"naxis",naxis);
142
+ Strcpy(naxes,"naxis0");
143
+ length = strlen(naxes) - 1;
144
+ for(i=0; i < naxis; i++){
145
+ naxes[length] ++;
146
+ wrhdi_c(tno,naxes,axes[i]);
147
+ }
148
+ hwriteb_c(images[tno].image,real_item,0,ITEM_HDR_SIZE,&iostat);
149
+ CHECK(iostat,(message,"Error writing pixel data label for %s, in XYOPEN",name));
150
+ }
151
+
152
+ /* Common to old and new. Copy the dimension info to the local description. */
153
+
154
+ images[tno].offset = 0;
155
+ images[tno].naxis = naxis;
156
+ for(i=0; i < naxis; i++) images[tno].axes[i] = axes[i];
157
+ for(i = naxis; i < MAXNAX; i++) images[tno].axes[i] = 1;
158
+ images[tno].mask = NULL;
159
+ images[tno].image_exists = TRUE;
160
+ images[tno].mask_exists = TRUE;
161
+ *thandle = tno;
162
+ }
163
+ /************************************************************************/
164
+ void xyflush_c(int thandle)
165
+ /**xyflush -- Flush out any image changes to disk. */
166
+ /*:image-i/o */
167
+ /*+ FORTRAN call sequence:
168
+
169
+ subroutine xyflush(tno)
170
+ implicit none
171
+
172
+ This flushes any changes to an image to disk.
173
+
174
+ Input:
175
+ tno The handle of the image file. */
176
+ /*----------------------------------------------------------------------*/
177
+ {
178
+ int iostat,i;
179
+ off_t offset;
180
+ size_t nbytes, length;
181
+ float buf[MAXDIM];
182
+
183
+ /* Simply flush out the mask. */
184
+
185
+ if(images[thandle].mask != NULL) mkflush_c(images[thandle].mask);
186
+
187
+ /* If its a new file, and not all the pixels have yet been written,
188
+ write zero pixels. First determine the proper size. */
189
+
190
+ nbytes = H_REAL_SIZE;
191
+ for(i=0; i < images[thandle].naxis; i++) nbytes *= images[thandle].axes[i];
192
+ nbytes += ITEM_HDR_SIZE;
193
+ offset = hsize_c(images[thandle].image);
194
+
195
+ /* Determine the number of bytes to pad, and then pad it. */
196
+
197
+ nbytes -= offset;
198
+ if(nbytes > 0)for(i=0; i < MAXDIM; i++)buf[i] = 0.0;
199
+ while(nbytes > 0){
200
+ length = MAXDIM*H_REAL_SIZE;
201
+ if(length > nbytes) length = nbytes;
202
+ hwriter_c(images[thandle].image,buf,offset,length,&iostat);
203
+ CHECK(iostat,(message,"Error allocating space for image"));
204
+ offset += length;
205
+ nbytes -= length;
206
+ }
207
+
208
+ /* Do it all now. */
209
+
210
+ hflush_c(thandle,&iostat); check(iostat);
211
+ }
212
+ /************************************************************************/
213
+ void xyclose_c(int thandle)
214
+ /**xyclose -- Close up an image file. */
215
+ /*:image-i/o */
216
+ /*+ FORTRAN call sequence:
217
+
218
+ subroutine xyclose(tno)
219
+ integer tno
220
+
221
+ This closes an image file.
222
+
223
+ Input:
224
+ tno The handle of the image file. */
225
+ /*----------------------------------------------------------------------*/
226
+ {
227
+ int iostat;
228
+
229
+ hdaccess_c(images[thandle].image,&iostat); check(iostat);
230
+ if(images[thandle].mask != NULL) mkclose_c(images[thandle].mask);
231
+ hclose_c(thandle);
232
+ }
233
+ /************************************************************************/
234
+ void xyread_c(int thandle,int index,float *array)
235
+ /**xyread -- Read a row from an image. */
236
+ /*:image-i/o */
237
+ /*+ FORTRAN call sequence:
238
+
239
+ subroutine xyread(tno,index,array)
240
+ integer tno,index
241
+ real array(*)
242
+
243
+ This reads a single row from an image. This accesses the plane given
244
+ by the last call to xysetpl.
245
+
246
+ Input:
247
+ tno The image file handle, returned by xyopen.
248
+ index The row number to read. This varies from 1 to NAXIS2.
249
+ Output:
250
+ array The read row. NAXIS1 elements are returned. */
251
+ /*----------------------------------------------------------------------*/
252
+ {
253
+ off_t offset;
254
+ size_t length;
255
+ int iostat;
256
+
257
+ length = H_REAL_SIZE * images[thandle].axes[0];
258
+ offset = H_REAL_SIZE * images[thandle].offset + (index-1) * length +
259
+ ITEM_HDR_SIZE;
260
+ hreadr_c(images[thandle].image,array,offset,length,&iostat);
261
+ check(iostat);
262
+ }
263
+ /************************************************************************/
264
+ void xywrite_c(int thandle,int index,Const float *array)
265
+ /**xywrite -- Write a row to an image. */
266
+ /*:image-i/o */
267
+ /*+ FORTRAN call sequence:
268
+
269
+ subroutine xywrite(tno,index,array)
270
+ integer tno,index
271
+ real array(*)
272
+
273
+ This writes a single row to an image. This accesses the plane given
274
+ by the last call to xysetpl.
275
+
276
+ Input:
277
+ tno The image file handle, returned by xyopen.
278
+ index The row number to write. This varies from 1 to NAXIS2.
279
+ array The read row. NAXIS1 elements are written. */
280
+ /*----------------------------------------------------------------------*/
281
+ {
282
+ off_t offset;
283
+ size_t length;
284
+ int iostat;
285
+
286
+ length = H_REAL_SIZE * images[thandle].axes[0];
287
+ offset = H_REAL_SIZE * images[thandle].offset + (index-1) * length +
288
+ ITEM_HDR_SIZE;
289
+ hwriter_c(images[thandle].image,array,offset,length,&iostat);
290
+ check(iostat);
291
+ }
292
+ /************************************************************************/
293
+ void xymkrd_c(int thandle,int index,int *runs,int n,int *nread)
294
+ /**xymkrd -- Read the masking information for an image (runs format). */
295
+ /*:image-i/o */
296
+ /*+ FORTRAN call sequence:
297
+
298
+ subroutine xymkrd(tno,index,runs,n,nread)
299
+ integer tno,index,n,nread
300
+ integer runs(n)
301
+
302
+ This reads the masking information associated with a row of an image,
303
+ and returns it in "runs" format.
304
+
305
+ Input:
306
+ tnoe The handle associated with the image.
307
+ index The index of the row to determine mask info about. The
308
+ last call to xysetpl determines which plane to access.
309
+ n The size of the array to receive the mask info.
310
+ Output:
311
+ runs The mask info, in "runs" form. If "i" varies from 1 to
312
+ nread/2, then pixels runs(2*i-1) to runs(2*i) are
313
+ good, whereas pixels runs(2*i) to runs(2*i+1) are bad.
314
+ nread The number of "runs" read. */
315
+ /*----------------------------------------------------------------------*/
316
+ {
317
+ off_t offset;
318
+ size_t length;
319
+
320
+ if(images[thandle].mask == NULL && images[thandle].mask_exists)
321
+ xymkopen_c(thandle,OLD);
322
+ if(images[thandle].mask_exists){
323
+ length = images[thandle].axes[0];
324
+ offset = images[thandle].offset + (index-1) * length;
325
+ *nread = mkread_c(images[thandle].mask,MK_RUNS,runs,offset,length,n);
326
+ } else {
327
+ if(n < 2)
328
+ bug_c('f',"xymkrd_c: Runs array overflow");
329
+ runs[0] = 1;
330
+ runs[1] = images[thandle].axes[0];
331
+ *nread = 2;
332
+ }
333
+ }
334
+ /************************************************************************/
335
+ void xymkwr_c(int thandle,int index,Const int *runs,int n)
336
+ /**xymkwr -- write image masking information (runs format). */
337
+ /*:image-i/o */
338
+ /*+ FORTRAN call sequence:
339
+
340
+ subroutine xymkwr(tno,index,runs,n)
341
+ integer tno,index,n
342
+ integer runs(n)
343
+
344
+ This writes out the masking information associated with a row of an image.
345
+ This information is passes in in "runs" format.
346
+
347
+ Input:
348
+ tnoe The handle associated with the image.
349
+ index The index of the row to determine mask info about. The
350
+ last call to xysetpl determines which plane to access.
351
+ n The size of the array containing the mask info.
352
+ runs The mask info, in "runs" form. If "i" varies from 1 to
353
+ nread/2, then pixels runs(2*i-1) to runs(2*i) are
354
+ good, whereas pixels runs(2*i) to runs(2*i+1) are bad. */
355
+ /*----------------------------------------------------------------------*/
356
+ {
357
+ off_t offset;
358
+ size_t length;
359
+
360
+ if(images[thandle].mask == NULL) xymkopen_c(thandle,NEW);
361
+ if(images[thandle].mask == NULL)
362
+ bug_c('f',"xymkwr_c: Error writing to image mask file");
363
+ length = images[thandle].axes[0];
364
+ offset = images[thandle].offset + (index-1) * length;
365
+ mkwrite_c(images[thandle].mask,MK_RUNS,runs,offset,length,n);
366
+ }
367
+ /************************************************************************/
368
+ void xyflgwr_c(int thandle,int index,Const int *flags)
369
+ /**xyflgwr -- Write image masking information (flags format). */
370
+ /*:image-i/o */
371
+ /*+ FORTRAN call sequence:
372
+
373
+ subroutine xyflgwr(tno,index,flags)
374
+ integer tno,index
375
+ logical flags(*)
376
+
377
+ This writes image mask information. It is the counterpart of xywrite.
378
+ Input:
379
+ tno Handle of the image file.
380
+ index The row in a plane to write out. This varies between 1 and
381
+ NAXIS2. See xysetpl to set the which plane is to be
382
+ accessed.
383
+ flags A logical array of NAXIS1 elements. A true value indicates
384
+ that the pixel is good. */
385
+ /*----------------------------------------------------------------------*/
386
+ {
387
+ off_t offset;
388
+ size_t length;
389
+
390
+ if(images[thandle].mask == NULL)xymkopen_c(thandle,NEW);
391
+ if(images[thandle].mask == NULL)
392
+ bug_c('f',"xyflgwr_c: Error writing to image mask file");
393
+ length = images[thandle].axes[0];
394
+ offset = images[thandle].offset + (index-1) * length;
395
+ mkwrite_c(images[thandle].mask,MK_FLAGS,flags,offset,length,length);
396
+ }
397
+ /************************************************************************/
398
+ void xyflgrd_c(int thandle,int index,int *flags)
399
+ /**xyflgrd -- Read image masking information (flags format). */
400
+ /*:image-i/o */
401
+ /*+ FORTRAN call sequence:
402
+
403
+ subroutine xyflgrd(tno,index,flags)
404
+ integer tno,index
405
+ logical flags(*)
406
+
407
+ This reads image mask information. It is the counterpart of xyread.
408
+ Input:
409
+ tno Handle of the image file.
410
+ index The row in a plane to read in. This varies betwen 1 and
411
+ NAXIS2. Set xysetpl to change the plane being accessed.
412
+ Output:
413
+ flags A logical array of NAXIS1 elements. A true value indicates
414
+ that the pixel is good. */
415
+ /*----------------------------------------------------------------------*/
416
+ {
417
+ int n,i;
418
+ off_t offset;
419
+ size_t length;
420
+
421
+ if(images[thandle].mask == NULL && images[thandle].mask_exists)
422
+ xymkopen_c(thandle,OLD);
423
+ if(images[thandle].mask_exists){
424
+ length = images[thandle].axes[0];
425
+ offset = images[thandle].offset + (index-1) * length;
426
+ n = mkread_c(images[thandle].mask,MK_FLAGS,flags,offset,length,length);
427
+ } else {
428
+ n = images[thandle].axes[0];
429
+ for(i=0; i<n; i++) *flags++ = FORT_TRUE;
430
+ }
431
+ }
432
+ /************************************************************************/
433
+ static void xymkopen_c(int thandle,int mode)
434
+ /*
435
+ This opens the masking file.
436
+
437
+ Input:
438
+ thandle The handle of the image data-set.
439
+ mode Either OLD or NEW.
440
+ ------------------------------------------------------------------------*/
441
+ {
442
+ images[thandle].mask = mkopen_c(thandle,"mask",(mode == OLD ? "old" : "new"));
443
+ if(images[thandle].mask == NULL) images[thandle].mask_exists = FALSE;
444
+ }
445
+ /************************************************************************/
446
+ void xysetpl_c(int thandle,int naxis,Const int *axes)
447
+ /**xysetpl -- Set which plane of a cube is to be accessed. */
448
+ /*:image-i/o */
449
+ /*+ FORTRAN call sequence:
450
+
451
+ subroutine xysetpl(tno,naxis,nsize)
452
+ integer tno,naxis,nsize(naxis)
453
+
454
+ This sets up which plane of a cube is to be accessed.
455
+
456
+ Input:
457
+ tno Handle of the image file.
458
+ naxis Size of the "nsize" array.
459
+ nsize This gives the indices, along the 3rd, 4th, 5th, etc
460
+ dimensions, of the plane that is to be accessed. nsize(1)
461
+ corresponds to the index along the 3rd dimension. */
462
+ /*----------------------------------------------------------------------*/
463
+ {
464
+ int i;
465
+ size_t size;
466
+
467
+ if(naxis+2 > MAXNAX)
468
+ bug_c('f',"xysetpl_c: Too many dimensions");
469
+ size = 0;
470
+ for(i=naxis-1; i >= 0; i--){
471
+ if(axes[i] < 1 || axes[i] > images[thandle].axes[i+2])
472
+ bug_c('f',"Dimension error in XYSETPL");
473
+ size = ( size + axes[i] - 1) * images[thandle].axes[i+1];
474
+ }
475
+ images[thandle].offset = size * images[thandle].axes[0];
476
+ }