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