1 /* This file, getcolk.c, contains routines that read data elements from */
2 /* a FITS image or table, with 'int' data type. */
3
4 /* The FITSIO software was written by William Pence at the High Energy */
5 /* Astrophysic Science Archive Research Center (HEASARC) at the NASA */
6 /* Goddard Space Flight Center. */
7
8 #include <math.h>
9 #include <stdlib.h>
10 #include <limits.h>
11 #include <string.h>
12 #include "fitsio2.h"
13
14 /*--------------------------------------------------------------------------*/
ffgpvk(fitsfile * fptr,long group,LONGLONG firstelem,LONGLONG nelem,int nulval,int * array,int * anynul,int * status)15 int ffgpvk( fitsfile *fptr, /* I - FITS file pointer */
16 long group, /* I - group to read (1 = 1st group) */
17 LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */
18 LONGLONG nelem, /* I - number of values to read */
19 int nulval, /* I - value for undefined pixels */
20 int *array, /* O - array of values that are returned */
21 int *anynul, /* O - set to 1 if any values are null; else 0 */
22 int *status) /* IO - error status */
23 /*
24 Read an array of values from the primary array. Data conversion
25 and scaling will be performed if necessary (e.g, if the datatype of
26 the FITS array is not the same as the array being read).
27 Undefined elements will be set equal to NULVAL, unless NULVAL=0
28 in which case no checking for undefined values will be performed.
29 ANYNUL is returned with a value of .true. if any pixels are undefined.
30 */
31 {
32 long row;
33 char cdummy;
34 int nullcheck = 1;
35 int nullvalue;
36
37 if (fits_is_compressed_image(fptr, status))
38 {
39 /* this is a compressed image in a binary table */
40 nullvalue = nulval; /* set local variable */
41
42 fits_read_compressed_pixels(fptr, TINT, firstelem, nelem,
43 nullcheck, &nullvalue, array, NULL, anynul, status);
44 return(*status);
45 }
46
47 /*
48 the primary array is represented as a binary table:
49 each group of the primary array is a row in the table,
50 where the first column contains the group parameters
51 and the second column contains the image itself.
52 */
53
54 row=maxvalue(1,group);
55
56 ffgclk(fptr, 2, row, firstelem, nelem, 1, 1, nulval,
57 array, &cdummy, anynul, status);
58 return(*status);
59 }
60 /*--------------------------------------------------------------------------*/
ffgpfk(fitsfile * fptr,long group,LONGLONG firstelem,LONGLONG nelem,int * array,char * nularray,int * anynul,int * status)61 int ffgpfk( fitsfile *fptr, /* I - FITS file pointer */
62 long group, /* I - group to read (1 = 1st group) */
63 LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */
64 LONGLONG nelem, /* I - number of values to read */
65 int *array, /* O - array of values that are returned */
66 char *nularray, /* O - array of null pixel flags */
67 int *anynul, /* O - set to 1 if any values are null; else 0 */
68 int *status) /* IO - error status */
69 /*
70 Read an array of values from the primary array. Data conversion
71 and scaling will be performed if necessary (e.g, if the datatype of
72 the FITS array is not the same as the array being read).
73 Any undefined pixels in the returned array will be set = 0 and the
74 corresponding nularray value will be set = 1.
75 ANYNUL is returned with a value of .true. if any pixels are undefined.
76 */
77 {
78 long row;
79 int nullcheck = 2;
80
81 if (fits_is_compressed_image(fptr, status))
82 {
83 /* this is a compressed image in a binary table */
84
85 fits_read_compressed_pixels(fptr, TINT, firstelem, nelem,
86 nullcheck, NULL, array, nularray, anynul, status);
87 return(*status);
88 }
89
90 /*
91 the primary array is represented as a binary table:
92 each group of the primary array is a row in the table,
93 where the first column contains the group parameters
94 and the second column contains the image itself.
95 */
96
97 row=maxvalue(1,group);
98
99 ffgclk(fptr, 2, row, firstelem, nelem, 1, 2, 0L,
100 array, nularray, anynul, status);
101 return(*status);
102 }
103 /*--------------------------------------------------------------------------*/
ffg2dk(fitsfile * fptr,long group,int nulval,LONGLONG ncols,LONGLONG naxis1,LONGLONG naxis2,int * array,int * anynul,int * status)104 int ffg2dk(fitsfile *fptr, /* I - FITS file pointer */
105 long group, /* I - group to read (1 = 1st group) */
106 int nulval, /* set undefined pixels equal to this */
107 LONGLONG ncols, /* I - number of pixels in each row of array */
108 LONGLONG naxis1, /* I - FITS image NAXIS1 value */
109 LONGLONG naxis2, /* I - FITS image NAXIS2 value */
110 int *array, /* O - array to be filled and returned */
111 int *anynul, /* O - set to 1 if any values are null; else 0 */
112 int *status) /* IO - error status */
113 /*
114 Read an entire 2-D array of values to the primary array. Data conversion
115 and scaling will be performed if necessary (e.g, if the datatype of the
116 FITS array is not the same as the array being read). Any null
117 values in the array will be set equal to the value of nulval, unless
118 nulval = 0 in which case no null checking will be performed.
119 */
120 {
121 /* call the 3D reading routine, with the 3rd dimension = 1 */
122
123 ffg3dk(fptr, group, nulval, ncols, naxis2, naxis1, naxis2, 1, array,
124 anynul, status);
125
126 return(*status);
127 }
128 /*--------------------------------------------------------------------------*/
ffg3dk(fitsfile * fptr,long group,int nulval,LONGLONG ncols,LONGLONG nrows,LONGLONG naxis1,LONGLONG naxis2,LONGLONG naxis3,int * array,int * anynul,int * status)129 int ffg3dk(fitsfile *fptr, /* I - FITS file pointer */
130 long group, /* I - group to read (1 = 1st group) */
131 int nulval, /* set undefined pixels equal to this */
132 LONGLONG ncols, /* I - number of pixels in each row of array */
133 LONGLONG nrows, /* I - number of rows in each plane of array */
134 LONGLONG naxis1, /* I - FITS image NAXIS1 value */
135 LONGLONG naxis2, /* I - FITS image NAXIS2 value */
136 LONGLONG naxis3, /* I - FITS image NAXIS3 value */
137 int *array, /* O - array to be filled and returned */
138 int *anynul, /* O - set to 1 if any values are null; else 0 */
139 int *status) /* IO - error status */
140 /*
141 Read an entire 3-D array of values to the primary array. Data conversion
142 and scaling will be performed if necessary (e.g, if the datatype of the
143 FITS array is not the same as the array being read). Any null
144 values in the array will be set equal to the value of nulval, unless
145 nulval = 0 in which case no null checking will be performed.
146 */
147 {
148 long tablerow, ii, jj;
149 char cdummy;
150 int nullcheck = 1;
151 long inc[] = {1,1,1};
152 LONGLONG fpixel[] = {1,1,1}, nfits, narray;
153 LONGLONG lpixel[3];
154 int nullvalue;
155
156 if (fits_is_compressed_image(fptr, status))
157 {
158 /* this is a compressed image in a binary table */
159
160 lpixel[0] = ncols;
161 lpixel[1] = nrows;
162 lpixel[2] = naxis3;
163 nullvalue = nulval; /* set local variable */
164
165 fits_read_compressed_img(fptr, TINT, fpixel, lpixel, inc,
166 nullcheck, &nullvalue, array, NULL, anynul, status);
167 return(*status);
168 }
169
170 /*
171 the primary array is represented as a binary table:
172 each group of the primary array is a row in the table,
173 where the first column contains the group parameters
174 and the second column contains the image itself.
175 */
176 tablerow=maxvalue(1,group);
177
178 if (ncols == naxis1 && nrows == naxis2) /* arrays have same size? */
179 {
180 /* all the image pixels are contiguous, so read all at once */
181 ffgclk(fptr, 2, tablerow, 1, naxis1 * naxis2 * naxis3, 1, 1, nulval,
182 array, &cdummy, anynul, status);
183 return(*status);
184 }
185
186 if (ncols < naxis1 || nrows < naxis2)
187 return(*status = BAD_DIMEN);
188
189 nfits = 1; /* next pixel in FITS image to read */
190 narray = 0; /* next pixel in output array to be filled */
191
192 /* loop over naxis3 planes in the data cube */
193 for (jj = 0; jj < naxis3; jj++)
194 {
195 /* loop over the naxis2 rows in the FITS image, */
196 /* reading naxis1 pixels to each row */
197
198 for (ii = 0; ii < naxis2; ii++)
199 {
200 if (ffgclk(fptr, 2, tablerow, nfits, naxis1, 1, 1, nulval,
201 &array[narray], &cdummy, anynul, status) > 0)
202 return(*status);
203
204 nfits += naxis1;
205 narray += ncols;
206 }
207 narray += (nrows - naxis2) * ncols;
208 }
209
210 return(*status);
211 }
212 /*--------------------------------------------------------------------------*/
ffgsvk(fitsfile * fptr,int colnum,int naxis,long * naxes,long * blc,long * trc,long * inc,int nulval,int * array,int * anynul,int * status)213 int ffgsvk(fitsfile *fptr, /* I - FITS file pointer */
214 int colnum, /* I - number of the column to read (1 = 1st) */
215 int naxis, /* I - number of dimensions in the FITS array */
216 long *naxes, /* I - size of each dimension */
217 long *blc, /* I - 'bottom left corner' of the subsection */
218 long *trc, /* I - 'top right corner' of the subsection */
219 long *inc, /* I - increment to be applied in each dimension */
220 int nulval, /* I - value to set undefined pixels */
221 int *array, /* O - array to be filled and returned */
222 int *anynul, /* O - set to 1 if any values are null; else 0 */
223 int *status) /* IO - error status */
224 /*
225 Read a subsection of data values from an image or a table column.
226 This routine is set up to handle a maximum of nine dimensions.
227 */
228 {
229 long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
230 long str[9],stp[9],incr[9],dir[9];
231 long nelem, nultyp, ninc, numcol;
232 LONGLONG felem, dsize[10], blcll[9], trcll[9];
233 int hdutype, anyf;
234 char ldummy, msg[FLEN_ERRMSG];
235 int nullcheck = 1;
236 int nullvalue;
237
238 if (naxis < 1 || naxis > 9)
239 {
240 snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvj is out of range", naxis);
241 ffpmsg(msg);
242 return(*status = BAD_DIMEN);
243 }
244
245 if (fits_is_compressed_image(fptr, status))
246 {
247 /* this is a compressed image in a binary table */
248
249 for (ii=0; ii < naxis; ii++) {
250 blcll[ii] = blc[ii];
251 trcll[ii] = trc[ii];
252 }
253
254 nullvalue = nulval; /* set local variable */
255
256 fits_read_compressed_img(fptr, TINT, blcll, trcll, inc,
257 nullcheck, &nullvalue, array, NULL, anynul, status);
258 return(*status);
259 }
260
261 /*
262 if this is a primary array, then the input COLNUM parameter should
263 be interpreted as the row number, and we will alway read the image
264 data from column 2 (any group parameters are in column 1).
265 */
266 if (ffghdt(fptr, &hdutype, status) > 0)
267 return(*status);
268
269 if (hdutype == IMAGE_HDU)
270 {
271 /* this is a primary array, or image extension */
272 if (colnum == 0)
273 {
274 rstr = 1;
275 rstp = 1;
276 }
277 else
278 {
279 rstr = colnum;
280 rstp = colnum;
281 }
282 rinc = 1;
283 numcol = 2;
284 }
285 else
286 {
287 /* this is a table, so the row info is in the (naxis+1) elements */
288 rstr = blc[naxis];
289 rstp = trc[naxis];
290 rinc = inc[naxis];
291 numcol = colnum;
292 }
293
294 nultyp = 1;
295 if (anynul)
296 *anynul = FALSE;
297
298 i0 = 0;
299 for (ii = 0; ii < 9; ii++)
300 {
301 str[ii] = 1;
302 stp[ii] = 1;
303 incr[ii] = 1;
304 dsize[ii] = 1;
305 dir[ii] = 1;
306 }
307
308 for (ii = 0; ii < naxis; ii++)
309 {
310 if (trc[ii] < blc[ii])
311 {
312 if (hdutype == IMAGE_HDU)
313 {
314 dir[ii] = -1;
315 }
316 else
317 {
318 snprintf(msg, FLEN_ERRMSG,"ffgsvk: illegal range specified for axis %ld", ii + 1);
319 ffpmsg(msg);
320 return(*status = BAD_PIX_NUM);
321 }
322 }
323
324 str[ii] = blc[ii];
325 stp[ii] = trc[ii];
326 incr[ii] = inc[ii];
327 dsize[ii + 1] = dsize[ii] * naxes[ii];
328 dsize[ii] = dsize[ii] * dir[ii];
329 }
330 dsize[naxis] = dsize[naxis] * dir[naxis];
331
332 if (naxis == 1 && naxes[0] == 1)
333 {
334 /* This is not a vector column, so read all the rows at once */
335 nelem = (rstp - rstr) / rinc + 1;
336 ninc = rinc;
337 rstp = rstr;
338 }
339 else
340 {
341 /* have to read each row individually, in all dimensions */
342 nelem = (stp[0]*dir[0] - str[0]*dir[0]) / inc[0] + 1;
343 ninc = incr[0] * dir[0];
344 }
345
346 for (row = rstr; row <= rstp; row += rinc)
347 {
348 for (i8 = str[8]*dir[8]; i8 <= stp[8]*dir[8]; i8 += incr[8])
349 {
350 for (i7 = str[7]*dir[7]; i7 <= stp[7]*dir[7]; i7 += incr[7])
351 {
352 for (i6 = str[6]*dir[6]; i6 <= stp[6]*dir[6]; i6 += incr[6])
353 {
354 for (i5 = str[5]*dir[5]; i5 <= stp[5]*dir[5]; i5 += incr[5])
355 {
356 for (i4 = str[4]*dir[4]; i4 <= stp[4]*dir[4]; i4 += incr[4])
357 {
358 for (i3 = str[3]*dir[3]; i3 <= stp[3]*dir[3]; i3 += incr[3])
359 {
360 for (i2 = str[2]*dir[2]; i2 <= stp[2]*dir[2]; i2 += incr[2])
361 {
362 for (i1 = str[1]*dir[1]; i1 <= stp[1]*dir[1]; i1 += incr[1])
363 {
364
365 felem=str[0] + (i1 - dir[1]) * dsize[1] + (i2 - dir[2]) * dsize[2] +
366 (i3 - dir[3]) * dsize[3] + (i4 - dir[4]) * dsize[4] +
367 (i5 - dir[5]) * dsize[5] + (i6 - dir[6]) * dsize[6] +
368 (i7 - dir[7]) * dsize[7] + (i8 - dir[8]) * dsize[8];
369
370 if ( ffgclk(fptr, numcol, row, felem, nelem, ninc, nultyp,
371 nulval, &array[i0], &ldummy, &anyf, status) > 0)
372 return(*status);
373
374 if (anyf && anynul)
375 *anynul = TRUE;
376
377 i0 += nelem;
378 }
379 }
380 }
381 }
382 }
383 }
384 }
385 }
386 }
387 return(*status);
388 }
389 /*--------------------------------------------------------------------------*/
ffgsfk(fitsfile * fptr,int colnum,int naxis,long * naxes,long * blc,long * trc,long * inc,int * array,char * flagval,int * anynul,int * status)390 int ffgsfk(fitsfile *fptr, /* I - FITS file pointer */
391 int colnum, /* I - number of the column to read (1 = 1st) */
392 int naxis, /* I - number of dimensions in the FITS array */
393 long *naxes, /* I - size of each dimension */
394 long *blc, /* I - 'bottom left corner' of the subsection */
395 long *trc, /* I - 'top right corner' of the subsection */
396 long *inc, /* I - increment to be applied in each dimension */
397 int *array, /* O - array to be filled and returned */
398 char *flagval, /* O - set to 1 if corresponding value is null */
399 int *anynul, /* O - set to 1 if any values are null; else 0 */
400 int *status) /* IO - error status */
401 /*
402 Read a subsection of data values from an image or a table column.
403 This routine is set up to handle a maximum of nine dimensions.
404 */
405 {
406 long ii,i0, i1,i2,i3,i4,i5,i6,i7,i8,row,rstr,rstp,rinc;
407 long str[9],stp[9],incr[9],dsize[10];
408 LONGLONG blcll[9], trcll[9];
409 long felem, nelem, nultyp, ninc, numcol;
410 long nulval = 0;
411 int hdutype, anyf;
412 char msg[FLEN_ERRMSG];
413 int nullcheck = 2;
414
415 if (naxis < 1 || naxis > 9)
416 {
417 snprintf(msg, FLEN_ERRMSG,"NAXIS = %d in call to ffgsvj is out of range", naxis);
418 ffpmsg(msg);
419 return(*status = BAD_DIMEN);
420 }
421
422 if (fits_is_compressed_image(fptr, status))
423 {
424 /* this is a compressed image in a binary table */
425
426 for (ii=0; ii < naxis; ii++) {
427 blcll[ii] = blc[ii];
428 trcll[ii] = trc[ii];
429 }
430
431 fits_read_compressed_img(fptr, TINT, blcll, trcll, inc,
432 nullcheck, NULL, array, flagval, anynul, status);
433 return(*status);
434 }
435
436 /*
437 if this is a primary array, then the input COLNUM parameter should
438 be interpreted as the row number, and we will alway read the image
439 data from column 2 (any group parameters are in column 1).
440 */
441 if (ffghdt(fptr, &hdutype, status) > 0)
442 return(*status);
443
444 if (hdutype == IMAGE_HDU)
445 {
446 /* this is a primary array, or image extension */
447 if (colnum == 0)
448 {
449 rstr = 1;
450 rstp = 1;
451 }
452 else
453 {
454 rstr = colnum;
455 rstp = colnum;
456 }
457 rinc = 1;
458 numcol = 2;
459 }
460 else
461 {
462 /* this is a table, so the row info is in the (naxis+1) elements */
463 rstr = blc[naxis];
464 rstp = trc[naxis];
465 rinc = inc[naxis];
466 numcol = colnum;
467 }
468
469 nultyp = 2;
470 if (anynul)
471 *anynul = FALSE;
472
473 i0 = 0;
474 for (ii = 0; ii < 9; ii++)
475 {
476 str[ii] = 1;
477 stp[ii] = 1;
478 incr[ii] = 1;
479 dsize[ii] = 1;
480 }
481
482 for (ii = 0; ii < naxis; ii++)
483 {
484 if (trc[ii] < blc[ii])
485 {
486 snprintf(msg, FLEN_ERRMSG,"ffgsvj: illegal range specified for axis %ld", ii + 1);
487 ffpmsg(msg);
488 return(*status = BAD_PIX_NUM);
489 }
490
491 str[ii] = blc[ii];
492 stp[ii] = trc[ii];
493 incr[ii] = inc[ii];
494 dsize[ii + 1] = dsize[ii] * naxes[ii];
495 }
496
497 if (naxis == 1 && naxes[0] == 1)
498 {
499 /* This is not a vector column, so read all the rows at once */
500 nelem = (rstp - rstr) / rinc + 1;
501 ninc = rinc;
502 rstp = rstr;
503 }
504 else
505 {
506 /* have to read each row individually, in all dimensions */
507 nelem = (stp[0] - str[0]) / inc[0] + 1;
508 ninc = incr[0];
509 }
510
511 for (row = rstr; row <= rstp; row += rinc)
512 {
513 for (i8 = str[8]; i8 <= stp[8]; i8 += incr[8])
514 {
515 for (i7 = str[7]; i7 <= stp[7]; i7 += incr[7])
516 {
517 for (i6 = str[6]; i6 <= stp[6]; i6 += incr[6])
518 {
519 for (i5 = str[5]; i5 <= stp[5]; i5 += incr[5])
520 {
521 for (i4 = str[4]; i4 <= stp[4]; i4 += incr[4])
522 {
523 for (i3 = str[3]; i3 <= stp[3]; i3 += incr[3])
524 {
525 for (i2 = str[2]; i2 <= stp[2]; i2 += incr[2])
526 {
527 for (i1 = str[1]; i1 <= stp[1]; i1 += incr[1])
528 {
529 felem=str[0] + (i1 - 1) * dsize[1] + (i2 - 1) * dsize[2] +
530 (i3 - 1) * dsize[3] + (i4 - 1) * dsize[4] +
531 (i5 - 1) * dsize[5] + (i6 - 1) * dsize[6] +
532 (i7 - 1) * dsize[7] + (i8 - 1) * dsize[8];
533
534 if ( ffgclk(fptr, numcol, row, felem, nelem, ninc, nultyp,
535 nulval, &array[i0], &flagval[i0], &anyf, status) > 0)
536 return(*status);
537
538 if (anyf && anynul)
539 *anynul = TRUE;
540
541 i0 += nelem;
542 }
543 }
544 }
545 }
546 }
547 }
548 }
549 }
550 }
551 return(*status);
552 }
553 /*--------------------------------------------------------------------------*/
ffggpk(fitsfile * fptr,long group,long firstelem,long nelem,int * array,int * status)554 int ffggpk( fitsfile *fptr, /* I - FITS file pointer */
555 long group, /* I - group to read (1 = 1st group) */
556 long firstelem, /* I - first vector element to read (1 = 1st) */
557 long nelem, /* I - number of values to read */
558 int *array, /* O - array of values that are returned */
559 int *status) /* IO - error status */
560 /*
561 Read an array of group parameters from the primary array. Data conversion
562 and scaling will be performed if necessary (e.g, if the datatype of
563 the FITS array is not the same as the array being read).
564 */
565 {
566 long row;
567 int idummy;
568 char cdummy;
569 /*
570 the primary array is represented as a binary table:
571 each group of the primary array is a row in the table,
572 where the first column contains the group parameters
573 and the second column contains the image itself.
574 */
575
576 row=maxvalue(1,group);
577
578 ffgclk(fptr, 1, row, firstelem, nelem, 1, 1, 0L,
579 array, &cdummy, &idummy, status);
580 return(*status);
581 }
582 /*--------------------------------------------------------------------------*/
ffgcvk(fitsfile * fptr,int colnum,LONGLONG firstrow,LONGLONG firstelem,LONGLONG nelem,int nulval,int * array,int * anynul,int * status)583 int ffgcvk(fitsfile *fptr, /* I - FITS file pointer */
584 int colnum, /* I - number of column to read (1 = 1st col) */
585 LONGLONG firstrow, /* I - first row to read (1 = 1st row) */
586 LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */
587 LONGLONG nelem, /* I - number of values to read */
588 int nulval, /* I - value for null pixels */
589 int *array, /* O - array of values that are read */
590 int *anynul, /* O - set to 1 if any values are null; else 0 */
591 int *status) /* IO - error status */
592 /*
593 Read an array of values from a column in the current FITS HDU. Automatic
594 datatype conversion will be performed if the datatype of the column does not
595 match the datatype of the array parameter. The output values will be scaled
596 by the FITS TSCALn and TZEROn values if these values have been defined.
597 Any undefined pixels will be set equal to the value of 'nulval' unless
598 nulval = 0 in which case no checks for undefined pixels will be made.
599 */
600 {
601 char cdummy;
602
603 ffgclk(fptr, colnum, firstrow, firstelem, nelem, 1, 1, nulval,
604 array, &cdummy, anynul, status);
605 return(*status);
606 }
607 /*--------------------------------------------------------------------------*/
ffgcfk(fitsfile * fptr,int colnum,LONGLONG firstrow,LONGLONG firstelem,LONGLONG nelem,int * array,char * nularray,int * anynul,int * status)608 int ffgcfk(fitsfile *fptr, /* I - FITS file pointer */
609 int colnum, /* I - number of column to read (1 = 1st col) */
610 LONGLONG firstrow, /* I - first row to read (1 = 1st row) */
611 LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */
612 LONGLONG nelem, /* I - number of values to read */
613 int *array, /* O - array of values that are read */
614 char *nularray, /* O - array of flags: 1 if null pixel; else 0 */
615 int *anynul, /* O - set to 1 if any values are null; else 0 */
616 int *status) /* IO - error status */
617 /*
618 Read an array of values from a column in the current FITS HDU. Automatic
619 datatype conversion will be performed if the datatype of the column does not
620 match the datatype of the array parameter. The output values will be scaled
621 by the FITS TSCALn and TZEROn values if these values have been defined.
622 Nularray will be set = 1 if the corresponding array pixel is undefined,
623 otherwise nularray will = 0.
624 */
625 {
626 int dummy = 0;
627
628 ffgclk(fptr, colnum, firstrow, firstelem, nelem, 1, 2, dummy,
629 array, nularray, anynul, status);
630 return(*status);
631 }
632 /*--------------------------------------------------------------------------*/
ffgclk(fitsfile * fptr,int colnum,LONGLONG firstrow,LONGLONG firstelem,LONGLONG nelem,long elemincre,int nultyp,int nulval,int * array,char * nularray,int * anynul,int * status)633 int ffgclk( fitsfile *fptr, /* I - FITS file pointer */
634 int colnum, /* I - number of column to read (1 = 1st col) */
635 LONGLONG firstrow, /* I - first row to read (1 = 1st row) */
636 LONGLONG firstelem, /* I - first vector element to read (1 = 1st) */
637 LONGLONG nelem, /* I - number of values to read */
638 long elemincre, /* I - pixel increment; e.g., 2 = every other */
639 int nultyp, /* I - null value handling code: */
640 /* 1: set undefined pixels = nulval */
641 /* 2: set nularray=1 for undefined pixels */
642 int nulval, /* I - value for null pixels if nultyp = 1 */
643 int *array, /* O - array of values that are read */
644 char *nularray, /* O - array of flags = 1 if nultyp = 2 */
645 int *anynul, /* O - set to 1 if any values are null; else 0 */
646 int *status) /* IO - error status */
647 /*
648 Read an array of values from a column in the current FITS HDU.
649 The column number may refer to a real column in an ASCII or binary table,
650 or it may refer be a virtual column in a 1 or more grouped FITS primary
651 array or image extension. FITSIO treats a primary array as a binary table
652 with 2 vector columns: the first column contains the group parameters (often
653 with length = 0) and the second column contains the array of image pixels.
654 Each row of the table represents a group in the case of multigroup FITS
655 images.
656
657 The output array of values will be converted from the datatype of the column
658 and will be scaled by the FITS TSCALn and TZEROn values if necessary.
659 */
660 {
661 double scale, zero, power, dtemp;
662 int tcode, maxelem2, hdutype, xcode, decimals;
663 long twidth, incre;
664 long ii, xwidth, ntodo;
665 int convert, nulcheck, readcheck = 0;
666 LONGLONG repeat, startpos, elemnum, readptr, tnull;
667 LONGLONG rowlen, rownum, remain, next, rowincre, maxelem;
668 char tform[20];
669 char message[FLEN_ERRMSG];
670 char snull[20]; /* the FITS null value if reading from ASCII table */
671
672 double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
673 void *buffer;
674
675 if (*status > 0 || nelem == 0) /* inherit input status value if > 0 */
676 return(*status);
677
678 /* call the 'short' or 'long' version of this routine, if possible */
679 if (sizeof(int) == sizeof(short))
680 ffgcli(fptr, colnum, firstrow, firstelem, nelem, elemincre, nultyp,
681 (short) nulval, (short *) array, nularray, anynul, status);
682 else if (sizeof(int) == sizeof(long))
683 ffgclj(fptr, colnum, firstrow, firstelem, nelem, elemincre, nultyp,
684 (long) nulval, (long *) array, nularray, anynul, status);
685 else
686 {
687 /*
688 This is a special case: sizeof(int) is not equal to sizeof(short) or
689 sizeof(long). This occurs on Alpha OSF systems where short = 2 bytes,
690 int = 4 bytes, and long = 8 bytes.
691 */
692
693 buffer = cbuff;
694 power = 1.;
695
696 if (anynul)
697 *anynul = 0;
698
699 if (nultyp == 2)
700 memset(nularray, 0, (size_t) nelem); /* initialize nullarray */
701
702 /*---------------------------------------------------*/
703 /* Check input and get parameters about the column: */
704 /*---------------------------------------------------*/
705 if (elemincre < 0)
706 readcheck = -1; /* don't do range checking in this case */
707
708 if ( ffgcprll( fptr, colnum, firstrow, firstelem, nelem, readcheck, &scale, &zero,
709 tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre,
710 &repeat, &rowlen, &hdutype, &tnull, snull, status) > 0 )
711 return(*status);
712 maxelem = maxelem2;
713
714 incre *= elemincre; /* multiply incre to just get every nth pixel */
715
716 if (tcode == TSTRING) /* setup for ASCII tables */
717 {
718 /* get the number of implied decimal places if no explicit decmal point */
719 ffasfm(tform, &xcode, &xwidth, &decimals, status);
720 for(ii = 0; ii < decimals; ii++)
721 power *= 10.;
722 }
723 /*------------------------------------------------------------------*/
724 /* Decide whether to check for null values in the input FITS file: */
725 /*------------------------------------------------------------------*/
726 nulcheck = nultyp; /* by default check for null values in the FITS file */
727
728 if (nultyp == 1 && nulval == 0)
729 nulcheck = 0; /* calling routine does not want to check for nulls */
730
731 else if (tcode%10 == 1 && /* if reading an integer column, and */
732 tnull == NULL_UNDEFINED) /* if a null value is not defined, */
733 nulcheck = 0; /* then do not check for null values. */
734
735 else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
736 nulcheck = 0; /* Impossible null value */
737
738 else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
739 nulcheck = 0; /* Impossible null value */
740
741 else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
742 nulcheck = 0;
743
744 /*----------------------------------------------------------------------*/
745 /* If FITS column and output data array have same datatype, then we do */
746 /* not need to use a temporary buffer to store intermediate datatype. */
747 /*----------------------------------------------------------------------*/
748 convert = 1;
749 if (tcode == TLONG) /* Special Case: */
750 { /* no type convertion required, so read */
751 /* data directly into output buffer. */
752
753 if (nelem < (LONGLONG)INT32_MAX/4) {
754 maxelem = nelem;
755 } else {
756 maxelem = INT32_MAX/4;
757 }
758
759 if (nulcheck == 0 && scale == 1. && zero == 0.)
760 convert = 0; /* no need to scale data or find nulls */
761 }
762
763 /*---------------------------------------------------------------------*/
764 /* Now read the pixels from the FITS column. If the column does not */
765 /* have the same datatype as the output array, then we have to read */
766 /* the raw values into a temporary buffer (of limited size). In */
767 /* the case of a vector colum read only 1 vector of values at a time */
768 /* then skip to the next row if more values need to be read. */
769 /* After reading the raw values, then call the fffXXYY routine to (1) */
770 /* test for undefined values, (2) convert the datatype if necessary, */
771 /* and (3) scale the values by the FITS TSCALn and TZEROn linear */
772 /* scaling parameters. */
773 /*---------------------------------------------------------------------*/
774 remain = nelem; /* remaining number of values to read */
775 next = 0; /* next element in array to be read */
776 rownum = 0; /* row number, relative to firstrow */
777
778 while (remain)
779 {
780 /* limit the number of pixels to read at one time to the number that
781 will fit in the buffer or to the number of pixels that remain in
782 the current vector, which ever is smaller.
783 */
784 ntodo = (long) minvalue(remain, maxelem);
785 if (elemincre >= 0)
786 {
787 ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));
788 }
789 else
790 {
791 ntodo = (long) minvalue(ntodo, (elemnum/(-elemincre) +1));
792 }
793
794 readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre));
795
796 switch (tcode)
797 {
798 case (TLONG):
799 ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) &array[next],
800 status);
801 if (convert)
802 fffi4int((INT32BIT *) &array[next], ntodo, scale, zero,
803 nulcheck, (INT32BIT) tnull, nulval,
804 &nularray[next], anynul, &array[next], status);
805 break;
806 case (TLONGLONG):
807
808 ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status);
809 fffi8int( (LONGLONG *) buffer, ntodo, scale, zero,
810 nulcheck, tnull, nulval, &nularray[next],
811 anynul, &array[next], status);
812 break;
813 case (TBYTE):
814 ffgi1b(fptr, readptr, ntodo, incre, (unsigned char *) buffer,
815 status);
816 fffi1int((unsigned char *) buffer, ntodo, scale, zero, nulcheck,
817 (unsigned char) tnull, nulval, &nularray[next], anynul,
818 &array[next], status);
819 break;
820 case (TSHORT):
821 ffgi2b(fptr, readptr, ntodo, incre, (short *) buffer, status);
822 fffi2int((short *) buffer, ntodo, scale, zero, nulcheck,
823 (short) tnull, nulval, &nularray[next], anynul,
824 &array[next], status);
825 break;
826 case (TFLOAT):
827 ffgr4b(fptr, readptr, ntodo, incre, (float *) buffer, status);
828 fffr4int((float *) buffer, ntodo, scale, zero, nulcheck,
829 nulval, &nularray[next], anynul,
830 &array[next], status);
831 break;
832 case (TDOUBLE):
833 ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status);
834 fffr8int((double *) buffer, ntodo, scale, zero, nulcheck,
835 nulval, &nularray[next], anynul,
836 &array[next], status);
837 break;
838 case (TSTRING):
839 ffmbyt(fptr, readptr, REPORT_EOF, status);
840
841 if (incre == twidth) /* contiguous bytes */
842 ffgbyt(fptr, ntodo * twidth, buffer, status);
843 else
844 ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
845 status);
846
847 fffstrint((char *) buffer, ntodo, scale, zero, twidth, power,
848 nulcheck, snull, nulval, &nularray[next], anynul,
849 &array[next], status);
850 break;
851
852 default: /* error trap for invalid column format */
853 snprintf(message, FLEN_ERRMSG,
854 "Cannot read numbers from column %d which has format %s",
855 colnum, tform);
856 ffpmsg(message);
857 if (hdutype == ASCII_TBL)
858 return(*status = BAD_ATABLE_FORMAT);
859 else
860 return(*status = BAD_BTABLE_FORMAT);
861
862 } /* End of switch block */
863
864 /*-------------------------*/
865 /* Check for fatal error */
866 /*-------------------------*/
867 if (*status > 0) /* test for error during previous read operation */
868 {
869 dtemp = (double) next;
870 if (hdutype > 0)
871 snprintf(message, FLEN_ERRMSG,
872 "Error reading elements %.0f thru %.0f from column %d (ffgclk).",
873 dtemp+1., dtemp+ntodo, colnum);
874 else
875 snprintf(message, FLEN_ERRMSG,
876 "Error reading elements %.0f thru %.0f from image (ffgclk).",
877 dtemp+1., dtemp+ntodo);
878
879 ffpmsg(message);
880 return(*status);
881 }
882
883 /*--------------------------------------------*/
884 /* increment the counters for the next loop */
885 /*--------------------------------------------*/
886 remain -= ntodo;
887 if (remain)
888 {
889 next += ntodo;
890 elemnum = elemnum + (ntodo * elemincre);
891
892 if (elemnum >= repeat) /* completed a row; start on later row */
893 {
894 rowincre = elemnum / repeat;
895 rownum += rowincre;
896 elemnum = elemnum - (rowincre * repeat);
897 }
898 else if (elemnum < 0) /* completed a row; start on a previous row */
899 {
900 rowincre = (-elemnum - 1) / repeat + 1;
901 rownum -= rowincre;
902 elemnum = (rowincre * repeat) + elemnum;
903 }
904 }
905 } /* End of main while Loop */
906
907
908 /*--------------------------------*/
909 /* check for numerical overflow */
910 /*--------------------------------*/
911 if (*status == OVERFLOW_ERR)
912 {
913 ffpmsg(
914 "Numerical overflow during type conversion while reading FITS data.");
915 *status = NUM_OVERFLOW;
916 }
917
918 } /* end of DEC Alpha special case */
919
920 return(*status);
921 }
922 /*--------------------------------------------------------------------------*/
fffi1int(unsigned char * input,long ntodo,double scale,double zero,int nullcheck,unsigned char tnull,int nullval,char * nullarray,int * anynull,int * output,int * status)923 int fffi1int(unsigned char *input,/* I - array of values to be converted */
924 long ntodo, /* I - number of elements in the array */
925 double scale, /* I - FITS TSCALn or BSCALE value */
926 double zero, /* I - FITS TZEROn or BZERO value */
927 int nullcheck, /* I - null checking code; 0 = don't check */
928 /* 1:set null pixels = nullval */
929 /* 2: if null pixel, set nullarray = 1 */
930 unsigned char tnull, /* I - value of FITS TNULLn keyword if any */
931 int nullval, /* I - set null pixels, if nullcheck = 1 */
932 char *nullarray, /* I - bad pixel array, if nullcheck = 2 */
933 int *anynull, /* O - set to 1 if any pixels are null */
934 int *output, /* O - array of converted pixels */
935 int *status) /* IO - error status */
936 /*
937 Copy input to output following reading of the input from a FITS file.
938 Check for null values and do datatype conversion and scaling if required.
939 The nullcheck code value determines how any null values in the input array
940 are treated. A null value is an input pixel that is equal to tnull. If
941 nullcheck = 0, then no checking for nulls is performed and any null values
942 will be transformed just like any other pixel. If nullcheck = 1, then the
943 output pixel will be set = nullval if the corresponding input pixel is null.
944 If nullcheck = 2, then if the pixel is null then the corresponding value of
945 nullarray will be set to 1; the value of nullarray for non-null pixels
946 will = 0. The anynull parameter will be set = 1 if any of the returned
947 pixels are null, otherwise anynull will be returned with a value = 0;
948 */
949 {
950 long ii;
951 double dvalue;
952
953 if (nullcheck == 0) /* no null checking required */
954 {
955 if (scale == 1. && zero == 0.) /* no scaling */
956 {
957 for (ii = 0; ii < ntodo; ii++)
958 output[ii] = (int) input[ii]; /* copy input to output */
959 }
960 else /* must scale the data */
961 {
962 for (ii = 0; ii < ntodo; ii++)
963 {
964 dvalue = input[ii] * scale + zero;
965
966 if (dvalue < DINT_MIN)
967 {
968 *status = OVERFLOW_ERR;
969 output[ii] = INT_MIN;
970 }
971 else if (dvalue > DINT_MAX)
972 {
973 *status = OVERFLOW_ERR;
974 output[ii] = INT_MAX;
975 }
976 else
977 output[ii] = (int) dvalue;
978 }
979 }
980 }
981 else /* must check for null values */
982 {
983 if (scale == 1. && zero == 0.) /* no scaling */
984 {
985 for (ii = 0; ii < ntodo; ii++)
986 {
987 if (input[ii] == tnull)
988 {
989 *anynull = 1;
990 if (nullcheck == 1)
991 output[ii] = nullval;
992 else
993 nullarray[ii] = 1;
994 }
995 else
996 output[ii] = (int) input[ii];
997 }
998 }
999 else /* must scale the data */
1000 {
1001 for (ii = 0; ii < ntodo; ii++)
1002 {
1003 if (input[ii] == tnull)
1004 {
1005 *anynull = 1;
1006 if (nullcheck == 1)
1007 output[ii] = nullval;
1008 else
1009 nullarray[ii] = 1;
1010 }
1011 else
1012 {
1013 dvalue = input[ii] * scale + zero;
1014
1015 if (dvalue < DINT_MIN)
1016 {
1017 *status = OVERFLOW_ERR;
1018 output[ii] = INT_MIN;
1019 }
1020 else if (dvalue > DINT_MAX)
1021 {
1022 *status = OVERFLOW_ERR;
1023 output[ii] = INT_MAX;
1024 }
1025 else
1026 output[ii] = (int) dvalue;
1027 }
1028 }
1029 }
1030 }
1031 return(*status);
1032 }
1033 /*--------------------------------------------------------------------------*/
fffi2int(short * input,long ntodo,double scale,double zero,int nullcheck,short tnull,int nullval,char * nullarray,int * anynull,int * output,int * status)1034 int fffi2int(short *input, /* I - array of values to be converted */
1035 long ntodo, /* I - number of elements in the array */
1036 double scale, /* I - FITS TSCALn or BSCALE value */
1037 double zero, /* I - FITS TZEROn or BZERO value */
1038 int nullcheck, /* I - null checking code; 0 = don't check */
1039 /* 1:set null pixels = nullval */
1040 /* 2: if null pixel, set nullarray = 1 */
1041 short tnull, /* I - value of FITS TNULLn keyword if any */
1042 int nullval, /* I - set null pixels, if nullcheck = 1 */
1043 char *nullarray, /* I - bad pixel array, if nullcheck = 2 */
1044 int *anynull, /* O - set to 1 if any pixels are null */
1045 int *output, /* O - array of converted pixels */
1046 int *status) /* IO - error status */
1047 /*
1048 Copy input to output following reading of the input from a FITS file.
1049 Check for null values and do datatype conversion and scaling if required.
1050 The nullcheck code value determines how any null values in the input array
1051 are treated. A null value is an input pixel that is equal to tnull. If
1052 nullcheck = 0, then no checking for nulls is performed and any null values
1053 will be transformed just like any other pixel. If nullcheck = 1, then the
1054 output pixel will be set = nullval if the corresponding input pixel is null.
1055 If nullcheck = 2, then if the pixel is null then the corresponding value of
1056 nullarray will be set to 1; the value of nullarray for non-null pixels
1057 will = 0. The anynull parameter will be set = 1 if any of the returned
1058 pixels are null, otherwise anynull will be returned with a value = 0;
1059 */
1060 {
1061 long ii;
1062 double dvalue;
1063
1064 if (nullcheck == 0) /* no null checking required */
1065 {
1066 if (scale == 1. && zero == 0.) /* no scaling */
1067 {
1068 for (ii = 0; ii < ntodo; ii++)
1069 output[ii] = (int) input[ii]; /* copy input to output */
1070 }
1071 else /* must scale the data */
1072 {
1073 for (ii = 0; ii < ntodo; ii++)
1074 {
1075 dvalue = input[ii] * scale + zero;
1076
1077 if (dvalue < DINT_MIN)
1078 {
1079 *status = OVERFLOW_ERR;
1080 output[ii] = INT_MIN;
1081 }
1082 else if (dvalue > DINT_MAX)
1083 {
1084 *status = OVERFLOW_ERR;
1085 output[ii] = INT_MAX;
1086 }
1087 else
1088 output[ii] = (int) dvalue;
1089 }
1090 }
1091 }
1092 else /* must check for null values */
1093 {
1094 if (scale == 1. && zero == 0.) /* no scaling */
1095 {
1096 for (ii = 0; ii < ntodo; ii++)
1097 {
1098 if (input[ii] == tnull)
1099 {
1100 *anynull = 1;
1101 if (nullcheck == 1)
1102 output[ii] = nullval;
1103 else
1104 nullarray[ii] = 1;
1105 }
1106 else
1107 output[ii] = (int) input[ii];
1108 }
1109 }
1110 else /* must scale the data */
1111 {
1112 for (ii = 0; ii < ntodo; ii++)
1113 {
1114 if (input[ii] == tnull)
1115 {
1116 *anynull = 1;
1117 if (nullcheck == 1)
1118 output[ii] = nullval;
1119 else
1120 nullarray[ii] = 1;
1121 }
1122 else
1123 {
1124 dvalue = input[ii] * scale + zero;
1125
1126 if (dvalue < DINT_MIN)
1127 {
1128 *status = OVERFLOW_ERR;
1129 output[ii] = INT_MIN;
1130 }
1131 else if (dvalue > DINT_MAX)
1132 {
1133 *status = OVERFLOW_ERR;
1134 output[ii] = INT_MAX;
1135 }
1136 else
1137 output[ii] = (int) dvalue;
1138 }
1139 }
1140 }
1141 }
1142 return(*status);
1143 }
1144 /*--------------------------------------------------------------------------*/
fffi4int(INT32BIT * input,long ntodo,double scale,double zero,int nullcheck,INT32BIT tnull,int nullval,char * nullarray,int * anynull,int * output,int * status)1145 int fffi4int(INT32BIT *input, /* I - array of values to be converted */
1146 long ntodo, /* I - number of elements in the array */
1147 double scale, /* I - FITS TSCALn or BSCALE value */
1148 double zero, /* I - FITS TZEROn or BZERO value */
1149 int nullcheck, /* I - null checking code; 0 = don't check */
1150 /* 1:set null pixels = nullval */
1151 /* 2: if null pixel, set nullarray = 1 */
1152 INT32BIT tnull, /* I - value of FITS TNULLn keyword if any */
1153 int nullval, /* I - set null pixels, if nullcheck = 1 */
1154 char *nullarray, /* I - bad pixel array, if nullcheck = 2 */
1155 int *anynull, /* O - set to 1 if any pixels are null */
1156 int *output, /* O - array of converted pixels */
1157 int *status) /* IO - error status */
1158 /*
1159 Copy input to output following reading of the input from a FITS file.
1160 Check for null values and do datatype conversion and scaling if required.
1161 The nullcheck code value determines how any null values in the input array
1162 are treated. A null value is an input pixel that is equal to tnull. If
1163 nullcheck = 0, then no checking for nulls is performed and any null values
1164 will be transformed just like any other pixel. If nullcheck = 1, then the
1165 output pixel will be set = nullval if the corresponding input pixel is null.
1166 If nullcheck = 2, then if the pixel is null then the corresponding value of
1167 nullarray will be set to 1; the value of nullarray for non-null pixels
1168 will = 0. The anynull parameter will be set = 1 if any of the returned
1169 pixels are null, otherwise anynull will be returned with a value = 0;
1170 */
1171 {
1172 long ii;
1173 double dvalue;
1174 if (nullcheck == 0) /* no null checking required */
1175 {
1176 if (scale == 1. && zero == 0.) /* no scaling */
1177 {
1178 for (ii = 0; ii < ntodo; ii++)
1179 output[ii] = (int) input[ii]; /* copy input to output */
1180 }
1181 else /* must scale the data */
1182 {
1183 for (ii = 0; ii < ntodo; ii++)
1184 {
1185 dvalue = input[ii] * scale + zero;
1186
1187 if (dvalue < DINT_MIN)
1188 {
1189 *status = OVERFLOW_ERR;
1190 output[ii] = INT_MIN;
1191 }
1192 else if (dvalue > DINT_MAX)
1193 {
1194 *status = OVERFLOW_ERR;
1195 output[ii] = INT_MAX;
1196 }
1197 else
1198 output[ii] = (int) dvalue;
1199 }
1200 }
1201 }
1202 else /* must check for null values */
1203 {
1204 if (scale == 1. && zero == 0.) /* no scaling */
1205 {
1206 for (ii = 0; ii < ntodo; ii++)
1207 {
1208 if (input[ii] == tnull)
1209 {
1210 *anynull = 1;
1211 if (nullcheck == 1)
1212 output[ii] = nullval;
1213 else
1214 nullarray[ii] = 1;
1215 }
1216 else
1217 output[ii] = (int) input[ii];
1218
1219 }
1220 }
1221 else /* must scale the data */
1222 {
1223 for (ii = 0; ii < ntodo; ii++)
1224 {
1225 if (input[ii] == tnull)
1226 {
1227 *anynull = 1;
1228 if (nullcheck == 1)
1229 output[ii] = nullval;
1230 else
1231 nullarray[ii] = 1;
1232 }
1233 else
1234 {
1235 dvalue = input[ii] * scale + zero;
1236
1237 if (dvalue < DINT_MIN)
1238 {
1239 *status = OVERFLOW_ERR;
1240 output[ii] = INT_MIN;
1241 }
1242 else if (dvalue > DINT_MAX)
1243 {
1244 *status = OVERFLOW_ERR;
1245 output[ii] = INT_MAX;
1246 }
1247 else
1248 output[ii] = (int) dvalue;
1249 }
1250 }
1251 }
1252 }
1253 return(*status);
1254 }
1255 /*--------------------------------------------------------------------------*/
fffi8int(LONGLONG * input,long ntodo,double scale,double zero,int nullcheck,LONGLONG tnull,int nullval,char * nullarray,int * anynull,int * output,int * status)1256 int fffi8int(LONGLONG *input, /* I - array of values to be converted */
1257 long ntodo, /* I - number of elements in the array */
1258 double scale, /* I - FITS TSCALn or BSCALE value */
1259 double zero, /* I - FITS TZEROn or BZERO value */
1260 int nullcheck, /* I - null checking code; 0 = don't check */
1261 /* 1:set null pixels = nullval */
1262 /* 2: if null pixel, set nullarray = 1 */
1263 LONGLONG tnull, /* I - value of FITS TNULLn keyword if any */
1264 int nullval, /* I - set null pixels, if nullcheck = 1 */
1265 char *nullarray, /* I - bad pixel array, if nullcheck = 2 */
1266 int *anynull, /* O - set to 1 if any pixels are null */
1267 int *output, /* O - array of converted pixels */
1268 int *status) /* IO - error status */
1269 /*
1270 Copy input to output following reading of the input from a FITS file.
1271 Check for null values and do datatype conversion and scaling if required.
1272 The nullcheck code value determines how any null values in the input array
1273 are treated. A null value is an input pixel that is equal to tnull. If
1274 nullcheck = 0, then no checking for nulls is performed and any null values
1275 will be transformed just like any other pixel. If nullcheck = 1, then the
1276 output pixel will be set = nullval if the corresponding input pixel is null.
1277 If nullcheck = 2, then if the pixel is null then the corresponding value of
1278 nullarray will be set to 1; the value of nullarray for non-null pixels
1279 will = 0. The anynull parameter will be set = 1 if any of the returned
1280 pixels are null, otherwise anynull will be returned with a value = 0;
1281 */
1282 {
1283 long ii;
1284 double dvalue;
1285 ULONGLONG ulltemp;
1286
1287 if (nullcheck == 0) /* no null checking required */
1288 {
1289 if (scale == 1. && zero == 9223372036854775808.)
1290 {
1291 /* The column we read contains unsigned long long values. */
1292 /* Instead of adding 9223372036854775808, it is more efficient */
1293 /* and more precise to just flip the sign bit with the XOR operator */
1294
1295 for (ii = 0; ii < ntodo; ii++) {
1296
1297 ulltemp = (ULONGLONG) (((LONGLONG) input[ii]) ^ 0x8000000000000000);
1298
1299 if (ulltemp > INT_MAX)
1300 {
1301 *status = OVERFLOW_ERR;
1302 output[ii] = INT_MAX;
1303 }
1304 else
1305 {
1306 output[ii] = (int) ulltemp;
1307 }
1308 }
1309 }
1310 else if (scale == 1. && zero == 0.) /* no scaling */
1311 {
1312 for (ii = 0; ii < ntodo; ii++)
1313 {
1314 if (input[ii] < INT_MIN)
1315 {
1316 *status = OVERFLOW_ERR;
1317 output[ii] = INT_MIN;
1318 }
1319 else if (input[ii] > INT_MAX)
1320 {
1321 *status = OVERFLOW_ERR;
1322 output[ii] = INT_MAX;
1323 }
1324 else
1325 output[ii] = (int) input[ii];
1326 }
1327 }
1328 else /* must scale the data */
1329 {
1330 for (ii = 0; ii < ntodo; ii++)
1331 {
1332 dvalue = input[ii] * scale + zero;
1333
1334 if (dvalue < DINT_MIN)
1335 {
1336 *status = OVERFLOW_ERR;
1337 output[ii] = INT_MIN;
1338 }
1339 else if (dvalue > DINT_MAX)
1340 {
1341 *status = OVERFLOW_ERR;
1342 output[ii] = INT_MAX;
1343 }
1344 else
1345 output[ii] = (int) dvalue;
1346 }
1347 }
1348 }
1349 else /* must check for null values */
1350 {
1351 if (scale == 1. && zero == 9223372036854775808.)
1352 {
1353 /* The column we read contains unsigned long long values. */
1354 /* Instead of subtracting 9223372036854775808, it is more efficient */
1355 /* and more precise to just flip the sign bit with the XOR operator */
1356
1357 for (ii = 0; ii < ntodo; ii++) {
1358
1359 if (input[ii] == tnull)
1360 {
1361 *anynull = 1;
1362 if (nullcheck == 1)
1363 output[ii] = nullval;
1364 else
1365 nullarray[ii] = 1;
1366 }
1367 else
1368 {
1369 ulltemp = (ULONGLONG) (((LONGLONG) input[ii]) ^ 0x8000000000000000);
1370
1371 if (ulltemp > INT_MAX)
1372 {
1373 *status = OVERFLOW_ERR;
1374 output[ii] = INT_MAX;
1375 }
1376 else
1377 {
1378 output[ii] = (int) ulltemp;
1379 }
1380 }
1381 }
1382 }
1383 else if (scale == 1. && zero == 0.) /* no scaling */
1384 {
1385 for (ii = 0; ii < ntodo; ii++)
1386 {
1387 if (input[ii] == tnull)
1388 {
1389 *anynull = 1;
1390 if (nullcheck == 1)
1391 output[ii] = nullval;
1392 else
1393 nullarray[ii] = 1;
1394 }
1395 else
1396 {
1397 if (input[ii] < INT_MIN)
1398 {
1399 *status = OVERFLOW_ERR;
1400 output[ii] = INT_MIN;
1401 }
1402 else if (input[ii] > INT_MAX)
1403 {
1404 *status = OVERFLOW_ERR;
1405 output[ii] = INT_MAX;
1406 }
1407 else
1408 output[ii] = (int) input[ii];
1409 }
1410 }
1411 }
1412 else /* must scale the data */
1413 {
1414 for (ii = 0; ii < ntodo; ii++)
1415 {
1416 if (input[ii] == tnull)
1417 {
1418 *anynull = 1;
1419 if (nullcheck == 1)
1420 output[ii] = nullval;
1421 else
1422 nullarray[ii] = 1;
1423 }
1424 else
1425 {
1426 dvalue = input[ii] * scale + zero;
1427
1428 if (dvalue < DINT_MIN)
1429 {
1430 *status = OVERFLOW_ERR;
1431 output[ii] = INT_MIN;
1432 }
1433 else if (dvalue > DINT_MAX)
1434 {
1435 *status = OVERFLOW_ERR;
1436 output[ii] = INT_MAX;
1437 }
1438 else
1439 output[ii] = (int) dvalue;
1440 }
1441 }
1442 }
1443 }
1444 return(*status);
1445 }
1446 /*--------------------------------------------------------------------------*/
fffr4int(float * input,long ntodo,double scale,double zero,int nullcheck,int nullval,char * nullarray,int * anynull,int * output,int * status)1447 int fffr4int(float *input, /* I - array of values to be converted */
1448 long ntodo, /* I - number of elements in the array */
1449 double scale, /* I - FITS TSCALn or BSCALE value */
1450 double zero, /* I - FITS TZEROn or BZERO value */
1451 int nullcheck, /* I - null checking code; 0 = don't check */
1452 /* 1:set null pixels = nullval */
1453 /* 2: if null pixel, set nullarray = 1 */
1454 int nullval, /* I - set null pixels, if nullcheck = 1 */
1455 char *nullarray, /* I - bad pixel array, if nullcheck = 2 */
1456 int *anynull, /* O - set to 1 if any pixels are null */
1457 int *output, /* O - array of converted pixels */
1458 int *status) /* IO - error status */
1459 /*
1460 Copy input to output following reading of the input from a FITS file.
1461 Check for null values and do datatype conversion and scaling if required.
1462 The nullcheck code value determines how any null values in the input array
1463 are treated. A null value is an input pixel that is equal to NaN. If
1464 nullcheck = 0, then no checking for nulls is performed and any null values
1465 will be transformed just like any other pixel. If nullcheck = 1, then the
1466 output pixel will be set = nullval if the corresponding input pixel is null.
1467 If nullcheck = 2, then if the pixel is null then the corresponding value of
1468 nullarray will be set to 1; the value of nullarray for non-null pixels
1469 will = 0. The anynull parameter will be set = 1 if any of the returned
1470 pixels are null, otherwise anynull will be returned with a value = 0;
1471 */
1472 {
1473 long ii;
1474 double dvalue;
1475 short *sptr, iret;
1476
1477 if (nullcheck == 0) /* no null checking required */
1478 {
1479 if (scale == 1. && zero == 0.) /* no scaling */
1480 {
1481 for (ii = 0; ii < ntodo; ii++)
1482 {
1483 if (input[ii] < DINT_MIN)
1484 {
1485 *status = OVERFLOW_ERR;
1486 output[ii] = INT_MIN;
1487 }
1488 else if (input[ii] > DINT_MAX)
1489 {
1490 *status = OVERFLOW_ERR;
1491 output[ii] = INT_MAX;
1492 }
1493 else
1494 output[ii] = (int) input[ii];
1495 }
1496 }
1497 else /* must scale the data */
1498 {
1499 for (ii = 0; ii < ntodo; ii++)
1500 {
1501 dvalue = input[ii] * scale + zero;
1502
1503 if (dvalue < DINT_MIN)
1504 {
1505 *status = OVERFLOW_ERR;
1506 output[ii] = INT_MIN;
1507 }
1508 else if (dvalue > DINT_MAX)
1509 {
1510 *status = OVERFLOW_ERR;
1511 output[ii] = INT_MAX;
1512 }
1513 else
1514 output[ii] = (int) dvalue;
1515 }
1516 }
1517 }
1518 else /* must check for null values */
1519 {
1520 sptr = (short *) input;
1521
1522 #if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
1523 sptr++; /* point to MSBs */
1524 #endif
1525
1526 if (scale == 1. && zero == 0.) /* no scaling */
1527 {
1528 for (ii = 0; ii < ntodo; ii++, sptr += 2)
1529 {
1530 if (0 != (iret = fnan(*sptr) ) ) /* test for NaN or underflow */
1531 {
1532 if (iret == 1) /* is it a NaN? */
1533 {
1534 *anynull = 1;
1535 if (nullcheck == 1)
1536 output[ii] = nullval;
1537 else
1538 nullarray[ii] = 1;
1539 }
1540 else /* it's an underflow */
1541 output[ii] = 0;
1542 }
1543 else
1544 {
1545 if (input[ii] < DINT_MIN)
1546 {
1547 *status = OVERFLOW_ERR;
1548 output[ii] = INT_MIN;
1549 }
1550 else if (input[ii] > DINT_MAX)
1551 {
1552 *status = OVERFLOW_ERR;
1553 output[ii] = INT_MAX;
1554 }
1555 else
1556 output[ii] = (int) input[ii];
1557 }
1558 }
1559 }
1560 else /* must scale the data */
1561 {
1562 for (ii = 0; ii < ntodo; ii++, sptr += 2)
1563 {
1564 if (0 != (iret = fnan(*sptr) ) ) /* test for NaN or underflow */
1565 {
1566 if (iret == 1) /* is it a NaN? */
1567 {
1568 *anynull = 1;
1569 if (nullcheck == 1)
1570 output[ii] = nullval;
1571 else
1572 nullarray[ii] = 1;
1573 }
1574 else /* it's an underflow */
1575 {
1576 if (zero < DINT_MIN)
1577 {
1578 *status = OVERFLOW_ERR;
1579 output[ii] = INT_MIN;
1580 }
1581 else if (zero > DINT_MAX)
1582 {
1583 *status = OVERFLOW_ERR;
1584 output[ii] = INT_MAX;
1585 }
1586 else
1587 output[ii] = (int) zero;
1588 }
1589 }
1590 else
1591 {
1592 dvalue = input[ii] * scale + zero;
1593
1594 if (dvalue < DINT_MIN)
1595 {
1596 *status = OVERFLOW_ERR;
1597 output[ii] = INT_MIN;
1598 }
1599 else if (dvalue > DINT_MAX)
1600 {
1601 *status = OVERFLOW_ERR;
1602 output[ii] = INT_MAX;
1603 }
1604 else
1605 output[ii] = (int) dvalue;
1606 }
1607 }
1608 }
1609 }
1610 return(*status);
1611 }
1612 /*--------------------------------------------------------------------------*/
fffr8int(double * input,long ntodo,double scale,double zero,int nullcheck,int nullval,char * nullarray,int * anynull,int * output,int * status)1613 int fffr8int(double *input, /* I - array of values to be converted */
1614 long ntodo, /* I - number of elements in the array */
1615 double scale, /* I - FITS TSCALn or BSCALE value */
1616 double zero, /* I - FITS TZEROn or BZERO value */
1617 int nullcheck, /* I - null checking code; 0 = don't check */
1618 /* 1:set null pixels = nullval */
1619 /* 2: if null pixel, set nullarray = 1 */
1620 int nullval, /* I - set null pixels, if nullcheck = 1 */
1621 char *nullarray, /* I - bad pixel array, if nullcheck = 2 */
1622 int *anynull, /* O - set to 1 if any pixels are null */
1623 int *output, /* O - array of converted pixels */
1624 int *status) /* IO - error status */
1625 /*
1626 Copy input to output following reading of the input from a FITS file.
1627 Check for null values and do datatype conversion and scaling if required.
1628 The nullcheck code value determines how any null values in the input array
1629 are treated. A null value is an input pixel that is equal to NaN. If
1630 nullcheck = 0, then no checking for nulls is performed and any null values
1631 will be transformed just like any other pixel. If nullcheck = 1, then the
1632 output pixel will be set = nullval if the corresponding input pixel is null.
1633 If nullcheck = 2, then if the pixel is null then the corresponding value of
1634 nullarray will be set to 1; the value of nullarray for non-null pixels
1635 will = 0. The anynull parameter will be set = 1 if any of the returned
1636 pixels are null, otherwise anynull will be returned with a value = 0;
1637 */
1638 {
1639 long ii;
1640 double dvalue;
1641 short *sptr, iret;
1642
1643 if (nullcheck == 0) /* no null checking required */
1644 {
1645 if (scale == 1. && zero == 0.) /* no scaling */
1646 {
1647 for (ii = 0; ii < ntodo; ii++)
1648 {
1649 if (input[ii] < DINT_MIN)
1650 {
1651 *status = OVERFLOW_ERR;
1652 output[ii] = INT_MIN;
1653 }
1654 else if (input[ii] > DINT_MAX)
1655 {
1656 *status = OVERFLOW_ERR;
1657 output[ii] = INT_MAX;
1658 }
1659 else
1660 output[ii] = (int) input[ii];
1661 }
1662 }
1663 else /* must scale the data */
1664 {
1665 for (ii = 0; ii < ntodo; ii++)
1666 {
1667 dvalue = input[ii] * scale + zero;
1668
1669 if (dvalue < DINT_MIN)
1670 {
1671 *status = OVERFLOW_ERR;
1672 output[ii] = INT_MIN;
1673 }
1674 else if (dvalue > DINT_MAX)
1675 {
1676 *status = OVERFLOW_ERR;
1677 output[ii] = INT_MAX;
1678 }
1679 else
1680 output[ii] = (int) dvalue;
1681 }
1682 }
1683 }
1684 else /* must check for null values */
1685 {
1686 sptr = (short *) input;
1687
1688 #if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
1689 sptr += 3; /* point to MSBs */
1690 #endif
1691 if (scale == 1. && zero == 0.) /* no scaling */
1692 {
1693 for (ii = 0; ii < ntodo; ii++, sptr += 4)
1694 {
1695 if (0 != (iret = dnan(*sptr)) ) /* test for NaN or underflow */
1696 {
1697 if (iret == 1) /* is it a NaN? */
1698 {
1699 *anynull = 1;
1700 if (nullcheck == 1)
1701 output[ii] = nullval;
1702 else
1703 nullarray[ii] = 1;
1704 }
1705 else /* it's an underflow */
1706 output[ii] = 0;
1707 }
1708 else
1709 {
1710 if (input[ii] < DINT_MIN)
1711 {
1712 *status = OVERFLOW_ERR;
1713 output[ii] = INT_MIN;
1714 }
1715 else if (input[ii] > DINT_MAX)
1716 {
1717 *status = OVERFLOW_ERR;
1718 output[ii] = INT_MAX;
1719 }
1720 else
1721 output[ii] = (int) input[ii];
1722 }
1723 }
1724 }
1725 else /* must scale the data */
1726 {
1727 for (ii = 0; ii < ntodo; ii++, sptr += 4)
1728 {
1729 if (0 != (iret = dnan(*sptr)) ) /* test for NaN or underflow */
1730 {
1731 if (iret == 1) /* is it a NaN? */
1732 {
1733 *anynull = 1;
1734 if (nullcheck == 1)
1735 output[ii] = nullval;
1736 else
1737 nullarray[ii] = 1;
1738 }
1739 else /* it's an underflow */
1740 {
1741 if (zero < DINT_MIN)
1742 {
1743 *status = OVERFLOW_ERR;
1744 output[ii] = INT_MIN;
1745 }
1746 else if (zero > DINT_MAX)
1747 {
1748 *status = OVERFLOW_ERR;
1749 output[ii] = INT_MAX;
1750 }
1751 else
1752 output[ii] = (int) zero;
1753 }
1754 }
1755 else
1756 {
1757 dvalue = input[ii] * scale + zero;
1758
1759 if (dvalue < DINT_MIN)
1760 {
1761 *status = OVERFLOW_ERR;
1762 output[ii] = INT_MIN;
1763 }
1764 else if (dvalue > DINT_MAX)
1765 {
1766 *status = OVERFLOW_ERR;
1767 output[ii] = INT_MAX;
1768 }
1769 else
1770 output[ii] = (int) dvalue;
1771 }
1772 }
1773 }
1774 }
1775 return(*status);
1776 }
1777 /*--------------------------------------------------------------------------*/
fffstrint(char * input,long ntodo,double scale,double zero,long twidth,double implipower,int nullcheck,char * snull,int nullval,char * nullarray,int * anynull,int * output,int * status)1778 int fffstrint(char *input, /* I - array of values to be converted */
1779 long ntodo, /* I - number of elements in the array */
1780 double scale, /* I - FITS TSCALn or BSCALE value */
1781 double zero, /* I - FITS TZEROn or BZERO value */
1782 long twidth, /* I - width of each substring of chars */
1783 double implipower, /* I - power of 10 of implied decimal */
1784 int nullcheck, /* I - null checking code; 0 = don't check */
1785 /* 1:set null pixels = nullval */
1786 /* 2: if null pixel, set nullarray = 1 */
1787 char *snull, /* I - value of FITS null string, if any */
1788 int nullval, /* I - set null pixels, if nullcheck = 1 */
1789 char *nullarray, /* I - bad pixel array, if nullcheck = 2 */
1790 int *anynull, /* O - set to 1 if any pixels are null */
1791 int *output, /* O - array of converted pixels */
1792 int *status) /* IO - error status */
1793 /*
1794 Copy input to output following reading of the input from a FITS file. Check
1795 for null values and do scaling if required. The nullcheck code value
1796 determines how any null values in the input array are treated. A null
1797 value is an input pixel that is equal to snull. If nullcheck= 0, then
1798 no special checking for nulls is performed. If nullcheck = 1, then the
1799 output pixel will be set = nullval if the corresponding input pixel is null.
1800 If nullcheck = 2, then if the pixel is null then the corresponding value of
1801 nullarray will be set to 1; the value of nullarray for non-null pixels
1802 will = 0. The anynull parameter will be set = 1 if any of the returned
1803 pixels are null, otherwise anynull will be returned with a value = 0;
1804 */
1805 {
1806 int nullen;
1807 long ii;
1808 double dvalue;
1809 char *cstring, message[FLEN_ERRMSG];
1810 char *cptr, *tpos;
1811 char tempstore, chrzero = '0';
1812 double val, power;
1813 int exponent, sign, esign, decpt;
1814
1815 nullen = strlen(snull);
1816 cptr = input; /* pointer to start of input string */
1817 for (ii = 0; ii < ntodo; ii++)
1818 {
1819 cstring = cptr;
1820 /* temporarily insert a null terminator at end of the string */
1821 tpos = cptr + twidth;
1822 tempstore = *tpos;
1823 *tpos = 0;
1824
1825 /* check if null value is defined, and if the */
1826 /* column string is identical to the null string */
1827 if (snull[0] != ASCII_NULL_UNDEFINED &&
1828 !strncmp(snull, cptr, nullen) )
1829 {
1830 if (nullcheck)
1831 {
1832 *anynull = 1;
1833 if (nullcheck == 1)
1834 output[ii] = nullval;
1835 else
1836 nullarray[ii] = 1;
1837 }
1838 cptr += twidth;
1839 }
1840 else
1841 {
1842 /* value is not the null value, so decode it */
1843 /* remove any embedded blank characters from the string */
1844
1845 decpt = 0;
1846 sign = 1;
1847 val = 0.;
1848 power = 1.;
1849 exponent = 0;
1850 esign = 1;
1851
1852 while (*cptr == ' ') /* skip leading blanks */
1853 cptr++;
1854
1855 if (*cptr == '-' || *cptr == '+') /* check for leading sign */
1856 {
1857 if (*cptr == '-')
1858 sign = -1;
1859
1860 cptr++;
1861
1862 while (*cptr == ' ') /* skip blanks between sign and value */
1863 cptr++;
1864 }
1865
1866 while (*cptr >= '0' && *cptr <= '9')
1867 {
1868 val = val * 10. + *cptr - chrzero; /* accumulate the value */
1869 cptr++;
1870
1871 while (*cptr == ' ') /* skip embedded blanks in the value */
1872 cptr++;
1873 }
1874
1875 if (*cptr == '.' || *cptr == ',') /* check for decimal point */
1876 {
1877 decpt = 1; /* set flag to show there was a decimal point */
1878 cptr++;
1879 while (*cptr == ' ') /* skip any blanks */
1880 cptr++;
1881
1882 while (*cptr >= '0' && *cptr <= '9')
1883 {
1884 val = val * 10. + *cptr - chrzero; /* accumulate the value */
1885 power = power * 10.;
1886 cptr++;
1887
1888 while (*cptr == ' ') /* skip embedded blanks in the value */
1889 cptr++;
1890 }
1891 }
1892
1893 if (*cptr == 'E' || *cptr == 'D') /* check for exponent */
1894 {
1895 cptr++;
1896 while (*cptr == ' ') /* skip blanks */
1897 cptr++;
1898
1899 if (*cptr == '-' || *cptr == '+') /* check for exponent sign */
1900 {
1901 if (*cptr == '-')
1902 esign = -1;
1903
1904 cptr++;
1905
1906 while (*cptr == ' ') /* skip blanks between sign and exp */
1907 cptr++;
1908 }
1909
1910 while (*cptr >= '0' && *cptr <= '9')
1911 {
1912 exponent = exponent * 10 + *cptr - chrzero; /* accumulate exp */
1913 cptr++;
1914
1915 while (*cptr == ' ') /* skip embedded blanks */
1916 cptr++;
1917 }
1918 }
1919
1920 if (*cptr != 0) /* should end up at the null terminator */
1921 {
1922 snprintf(message, FLEN_ERRMSG,"Cannot read number from ASCII table");
1923 ffpmsg(message);
1924 snprintf(message, FLEN_ERRMSG,"Column field = %s.", cstring);
1925 ffpmsg(message);
1926 /* restore the char that was overwritten by the null */
1927 *tpos = tempstore;
1928 return(*status = BAD_C2D);
1929 }
1930
1931 if (!decpt) /* if no explicit decimal, use implied */
1932 power = implipower;
1933
1934 dvalue = (sign * val / power) * pow(10., (double) (esign * exponent));
1935
1936 dvalue = dvalue * scale + zero; /* apply the scaling */
1937
1938 if (dvalue < DINT_MIN)
1939 {
1940 *status = OVERFLOW_ERR;
1941 output[ii] = INT_MIN;
1942 }
1943 else if (dvalue > DINT_MAX)
1944 {
1945 *status = OVERFLOW_ERR;
1946 output[ii] = INT_MAX;
1947 }
1948 else
1949 output[ii] = (long) dvalue;
1950 }
1951 /* restore the char that was overwritten by the null */
1952 *tpos = tempstore;
1953 }
1954 return(*status);
1955 }
1956