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