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