"Fossies" - the Fresh Open Source Software Archive

Member "cfitsio-4.0.0/getcolb.c" (20 May 2021, 78338 Bytes) of package /linux/misc/cfitsio-4.0.0.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "getcolb.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3.49_vs_4.0.0.

    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 /*--------------------------------------------------------------------------*/
   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 /*--------------------------------------------------------------------------*/
   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 /*--------------------------------------------------------------------------*/
  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 /*--------------------------------------------------------------------------*/
  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 /*--------------------------------------------------------------------------*/
  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         snprintf(msg, FLEN_ERRMSG,"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           snprintf(msg, FLEN_ERRMSG,"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 /*--------------------------------------------------------------------------*/
  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         snprintf(msg, FLEN_ERRMSG,"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         snprintf(msg, FLEN_ERRMSG,"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 /*--------------------------------------------------------------------------*/
  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 /*--------------------------------------------------------------------------*/
  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 /*--------------------------------------------------------------------------*/
  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 /*--------------------------------------------------------------------------*/
  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 = 16; /* see note below on readcheck */
  666     LONGLONG repeat, startpos, elemnum, readptr, tnull;
  667     LONGLONG rowlen, rownum, remain, next, rowincre, maxelem;
  668     char tform[20];
  669     char message[FLEN_ERRMSG];
  670     char snull[20];   /*  the FITS null value if reading from ASCII table  */
  671 
  672     double cbuff[DBUFFSIZE / sizeof(double)]; /* align cbuff on word boundary */
  673     void *buffer;
  674 
  675     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     /* IMPORTANT NOTE: that the special case of using this subroutine
  698        to read bytes from a character column are handled internally
  699        by the call to ffgcprll() below.  It will adjust the effective
  700        *tcode, repeats, etc, to appear as a TBYTE column. */
  701 
  702     /* Note that readcheck = 16 is equivalent to readcheck = 0 
  703        and readcheck = 15 is equivalent to readcheck = -1, 
  704        but either of those settings allow TSTRINGS to be 
  705        treated as TBYTE vectors, but with full error checking */
  706 
  707     ffgcprll( fptr, colnum, firstrow, firstelem, nelem, readcheck, &scale, &zero,
  708          tform, &twidth, &tcode, &maxelem2, &startpos, &elemnum, &incre,
  709          &repeat, &rowlen, &hdutype, &tnull, snull, status);
  710     maxelem = maxelem2;
  711 
  712     /* special case */
  713     if (tcode == TLOGICAL && elemincre == 1)
  714     {
  715         u.ucharval = nulval;
  716         ffgcll(fptr, colnum, firstrow, firstelem, nelem, nultyp,
  717                u.charval, (char *) array, nularray, anynul, status);
  718 
  719         return(*status);
  720     }
  721 
  722     if (*status > 0)
  723         return(*status);
  724         
  725     incre *= elemincre;   /* multiply incre to just get every nth pixel */
  726 
  727     if (tcode == TSTRING && hdutype == ASCII_TBL) /* setup for ASCII tables */
  728     {
  729       /* get the number of implied decimal places if no explicit decmal point */
  730       ffasfm(tform, &xcode, &xwidth, &decimals, status); 
  731       for(ii = 0; ii < decimals; ii++)
  732         power *= 10.;
  733     }
  734     /*------------------------------------------------------------------*/
  735     /*  Decide whether to check for null values in the input FITS file: */
  736     /*------------------------------------------------------------------*/
  737     nulcheck = nultyp; /* by default, check for null values in the FITS file */
  738 
  739     if (nultyp == 1 && nulval == 0)
  740        nulcheck = 0;    /* calling routine does not want to check for nulls */
  741 
  742     else if (tcode%10 == 1 &&        /* if reading an integer column, and  */ 
  743             tnull == NULL_UNDEFINED) /* if a null value is not defined,    */
  744             nulcheck = 0;            /* then do not check for null values. */
  745 
  746     else if (tcode == TSHORT && (tnull > SHRT_MAX || tnull < SHRT_MIN) )
  747             nulcheck = 0;            /* Impossible null value */
  748 
  749     else if (tcode == TBYTE && (tnull > 255 || tnull < 0) )
  750             nulcheck = 0;            /* Impossible null value */
  751 
  752     else if (tcode == TSTRING && snull[0] == ASCII_NULL_UNDEFINED)
  753          nulcheck = 0;
  754 
  755     /*----------------------------------------------------------------------*/
  756     /*  If FITS column and output data array have same datatype, then we do */
  757     /*  not need to use a temporary buffer to store intermediate datatype.  */
  758     /*----------------------------------------------------------------------*/
  759     convert = 1;
  760     if (tcode == TBYTE) /* Special Case:                        */
  761     {                             /* no type convertion required, so read */
  762                                   /* data directly into output buffer.    */
  763 
  764         if (nelem < (LONGLONG)INT32_MAX) {
  765             maxelem = nelem;
  766         } else {
  767             maxelem = INT32_MAX;
  768         }
  769 
  770         if (nulcheck == 0 && scale == 1. && zero == 0.)
  771             convert = 0;  /* no need to scale data or find nulls */
  772     }
  773 
  774     /*---------------------------------------------------------------------*/
  775     /*  Now read the pixels from the FITS column. If the column does not   */
  776     /*  have the same datatype as the output array, then we have to read   */
  777     /*  the raw values into a temporary buffer (of limited size).  In      */
  778     /*  the case of a vector colum read only 1 vector of values at a time  */
  779     /*  then skip to the next row if more values need to be read.          */
  780     /*  After reading the raw values, then call the fffXXYY routine to (1) */
  781     /*  test for undefined values, (2) convert the datatype if necessary,  */
  782     /*  and (3) scale the values by the FITS TSCALn and TZEROn linear      */
  783     /*  scaling parameters.                                                */
  784     /*---------------------------------------------------------------------*/
  785     remain = nelem;           /* remaining number of values to read */
  786     next = 0;                 /* next element in array to be read   */
  787     rownum = 0;               /* row number, relative to firstrow   */
  788 
  789     while (remain)
  790     {
  791         /* limit the number of pixels to read at one time to the number that
  792            will fit in the buffer or to the number of pixels that remain in
  793            the current vector, which ever is smaller.
  794         */
  795         ntodo = (long) minvalue(remain, maxelem);
  796         if (elemincre >= 0)
  797         {
  798           ntodo = (long) minvalue(ntodo, ((repeat - elemnum - 1)/elemincre +1));
  799         }
  800         else
  801         {
  802           ntodo = (long) minvalue(ntodo, (elemnum/(-elemincre) +1));
  803         }
  804 
  805         readptr = startpos + ((LONGLONG)rownum * rowlen) + (elemnum * (incre / elemincre));
  806 
  807         switch (tcode) 
  808         {
  809             case (TBYTE):
  810                 ffgi1b(fptr, readptr, ntodo, incre, &array[next], status);
  811                 if (convert)
  812                     fffi1i1(&array[next], ntodo, scale, zero, nulcheck, 
  813                     (unsigned char) tnull, nulval, &nularray[next], anynul, 
  814                            &array[next], status);
  815                 break;
  816             case (TSHORT):
  817                 ffgi2b(fptr, readptr, ntodo, incre, (short *) buffer, status);
  818                 fffi2i1((short  *) buffer, ntodo, scale, zero, nulcheck, 
  819                        (short) tnull, nulval, &nularray[next], anynul, 
  820                        &array[next], status);
  821                 break;
  822             case (TLONG):
  823                 ffgi4b(fptr, readptr, ntodo, incre, (INT32BIT *) buffer,
  824                        status);
  825                 fffi4i1((INT32BIT *) buffer, ntodo, scale, zero, nulcheck, 
  826                        (INT32BIT) tnull, nulval, &nularray[next], anynul, 
  827                        &array[next], status);
  828                 break;
  829             case (TLONGLONG):
  830                 ffgi8b(fptr, readptr, ntodo, incre, (long *) buffer, status);
  831                 fffi8i1( (LONGLONG *) buffer, ntodo, scale, zero, 
  832                            nulcheck, tnull, nulval, &nularray[next], 
  833                             anynul, &array[next], status);
  834                 break;
  835             case (TFLOAT):
  836                 ffgr4b(fptr, readptr, ntodo, incre, (float  *) buffer, status);
  837                 fffr4i1((float  *) buffer, ntodo, scale, zero, nulcheck, 
  838                        nulval, &nularray[next], anynul, 
  839                        &array[next], status);
  840                 break;
  841             case (TDOUBLE):
  842                 ffgr8b(fptr, readptr, ntodo, incre, (double *) buffer, status);
  843                 fffr8i1((double *) buffer, ntodo, scale, zero, nulcheck, 
  844                           nulval, &nularray[next], anynul, 
  845                           &array[next], status);
  846                 break;
  847             case (TSTRING):
  848                 ffmbyt(fptr, readptr, REPORT_EOF, status);
  849        
  850                 if (incre == twidth)    /* contiguous bytes */
  851                      ffgbyt(fptr, ntodo * twidth, buffer, status);
  852                 else
  853                      ffgbytoff(fptr, twidth, ntodo, incre - twidth, buffer,
  854                                status);
  855 
  856                 /* interpret the string as an ASCII formated number */
  857                 fffstri1((char *) buffer, ntodo, scale, zero, twidth, power,
  858                       nulcheck, snull, nulval, &nularray[next], anynul,
  859                       &array[next], status);
  860                 break;
  861 
  862             default:  /*  error trap for invalid column format */
  863                 snprintf(message, FLEN_ERRMSG,
  864                    "Cannot read bytes from column %d which has format %s",
  865                     colnum, tform);
  866                 ffpmsg(message);
  867                 if (hdutype == ASCII_TBL)
  868                     return(*status = BAD_ATABLE_FORMAT);
  869                 else
  870                     return(*status = BAD_BTABLE_FORMAT);
  871 
  872         } /* End of switch block */
  873 
  874         /*-------------------------*/
  875         /*  Check for fatal error  */
  876         /*-------------------------*/
  877         if (*status > 0)  /* test for error during previous read operation */
  878         {
  879       dtemp = (double) next;
  880           if (hdutype > 0)
  881             snprintf(message,FLEN_ERRMSG,
  882             "Error reading elements %.0f thru %.0f from column %d (ffgclb).",
  883               dtemp+1., dtemp+ntodo, colnum);
  884           else
  885             snprintf(message,FLEN_ERRMSG,
  886             "Error reading elements %.0f thru %.0f from image (ffgclb).",
  887               dtemp+1., dtemp+ntodo);
  888 
  889          ffpmsg(message);
  890          return(*status);
  891         }
  892 
  893         /*--------------------------------------------*/
  894         /*  increment the counters for the next loop  */
  895         /*--------------------------------------------*/
  896         remain -= ntodo;
  897         if (remain)
  898         {
  899             next += ntodo;
  900             elemnum = elemnum + (ntodo * elemincre);
  901 
  902             if (elemnum >= repeat)  /* completed a row; start on later row */
  903             {
  904                 rowincre = elemnum / repeat;
  905                 rownum += rowincre;
  906                 elemnum = elemnum - (rowincre * repeat);
  907             }
  908             else if (elemnum < 0)  /* completed a row; start on a previous row */
  909             {
  910                 rowincre = (-elemnum - 1) / repeat + 1;
  911                 rownum -= rowincre;
  912                 elemnum = (rowincre * repeat) + elemnum;
  913             }
  914         }
  915     }  /*  End of main while Loop  */
  916 
  917 
  918     /*--------------------------------*/
  919     /*  check for numerical overflow  */
  920     /*--------------------------------*/
  921     if (*status == OVERFLOW_ERR)
  922     {
  923         ffpmsg(
  924         "Numerical overflow during type conversion while reading FITS data.");
  925         *status = NUM_OVERFLOW;
  926     }
  927 
  928     return(*status);
  929 }
  930 /*--------------------------------------------------------------------------*/
  931 int ffgextn( fitsfile *fptr,        /* I - FITS file pointer                        */
  932             LONGLONG  offset,      /* I - byte offset from start of extension data */
  933             LONGLONG  nelem,       /* I - number of elements to read               */
  934             void *buffer,          /* I - stream of bytes to read                  */
  935             int  *status)          /* IO - error status                            */
  936 /*
  937   Read a stream of bytes from the current FITS HDU.  This primative routine is mainly
  938   for reading non-standard "conforming" extensions and should not be used
  939   for standard IMAGE, TABLE or BINTABLE extensions.
  940 */
  941 {
  942     if (*status > 0)           /* inherit input status value if > 0 */
  943         return(*status);
  944 
  945     /* reset position to the correct HDU if necessary */
  946     if (fptr->HDUposition != (fptr->Fptr)->curhdu)
  947         ffmahd(fptr, (fptr->HDUposition) + 1, NULL, status);
  948 
  949     /* rescan header if data structure is undefined */
  950     else if ((fptr->Fptr)->datastart == DATA_UNDEFINED)
  951         if ( ffrdef(fptr, status) > 0)               
  952             return(*status);
  953 
  954     /* move to write position */
  955     ffmbyt(fptr, (fptr->Fptr)->datastart+ offset, IGNORE_EOF, status);
  956     
  957     /* read the buffer */
  958     ffgbyt(fptr, nelem, buffer, status); 
  959 
  960     return(*status);
  961 }
  962 /*--------------------------------------------------------------------------*/
  963 int fffi1i1(unsigned char *input, /* I - array of values to be converted     */
  964             long ntodo,           /* I - number of elements in the array     */
  965             double scale,         /* I - FITS TSCALn or BSCALE value         */
  966             double zero,          /* I - FITS TZEROn or BZERO  value         */
  967             int nullcheck,        /* I - null checking code; 0 = don't check */
  968                                   /*     1:set null pixels = nullval         */
  969                                   /*     2: if null pixel, set nullarray = 1 */
  970             unsigned char tnull,  /* I - value of FITS TNULLn keyword if any */
  971             unsigned char nullval,/* I - set null pixels, if nullcheck = 1   */
  972             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
  973             int  *anynull,        /* O - set to 1 if any pixels are null     */
  974             unsigned char *output,/* O - array of converted pixels           */
  975             int *status)          /* IO - error status                       */
  976 /*
  977   Copy input to output following reading of the input from a FITS file.
  978   Check for null values and do datatype conversion and scaling if required.
  979   The nullcheck code value determines how any null values in the input array
  980   are treated.  A null value is an input pixel that is equal to tnull.  If 
  981   nullcheck = 0, then no checking for nulls is performed and any null values
  982   will be transformed just like any other pixel.  If nullcheck = 1, then the
  983   output pixel will be set = nullval if the corresponding input pixel is null.
  984   If nullcheck = 2, then if the pixel is null then the corresponding value of
  985   nullarray will be set to 1; the value of nullarray for non-null pixels 
  986   will = 0.  The anynull parameter will be set = 1 if any of the returned
  987   pixels are null, otherwise anynull will be returned with a value = 0;
  988 */
  989 {
  990     long ii;
  991     double dvalue;
  992 
  993     if (nullcheck == 0)     /* no null checking required */
  994     {
  995         if (scale == 1. && zero == 0.)      /* no scaling */
  996         {              /* this routine is normally not called in this case */
  997            memmove(output, input, ntodo );
  998         }
  999         else             /* must scale the data */
 1000         {                
 1001             for (ii = 0; ii < ntodo; ii++)
 1002             {
 1003                 dvalue = input[ii] * scale + zero;
 1004 
 1005                 if (dvalue < DUCHAR_MIN)
 1006                 {
 1007                     *status = OVERFLOW_ERR;
 1008                     output[ii] = 0;
 1009                 }
 1010                 else if (dvalue > DUCHAR_MAX)
 1011                 {
 1012                     *status = OVERFLOW_ERR;
 1013                     output[ii] = UCHAR_MAX;
 1014                 }
 1015                 else
 1016                     output[ii] = (unsigned char) dvalue;
 1017             }
 1018         }
 1019     }
 1020     else        /* must check for null values */
 1021     {
 1022         if (scale == 1. && zero == 0.)  /* no scaling */
 1023         {       
 1024             for (ii = 0; ii < ntodo; ii++)
 1025             {
 1026                 if (input[ii] == tnull)
 1027                 {
 1028                     *anynull = 1;
 1029                     if (nullcheck == 1)
 1030                         output[ii] = nullval;
 1031                     else
 1032                         nullarray[ii] = 1;
 1033                 }
 1034                 else
 1035                     output[ii] = input[ii];
 1036             }
 1037         }
 1038         else                  /* must scale the data */
 1039         {
 1040             for (ii = 0; ii < ntodo; ii++)
 1041             {
 1042                 if (input[ii] == tnull)
 1043                 {
 1044                     *anynull = 1;
 1045                     if (nullcheck == 1)
 1046                         output[ii] = nullval;
 1047                     else
 1048                         nullarray[ii] = 1;
 1049                 }
 1050                 else
 1051                 {
 1052                     dvalue = input[ii] * scale + zero;
 1053 
 1054                     if (dvalue < DUCHAR_MIN)
 1055                     {
 1056                         *status = OVERFLOW_ERR;
 1057                         output[ii] = 0;
 1058                     }
 1059                     else if (dvalue > DUCHAR_MAX)
 1060                     {
 1061                         *status = OVERFLOW_ERR;
 1062                         output[ii] = UCHAR_MAX;
 1063                     }
 1064                     else
 1065                         output[ii] = (unsigned char) dvalue;
 1066                 }
 1067             }
 1068         }
 1069     }
 1070     return(*status);
 1071 }
 1072 /*--------------------------------------------------------------------------*/
 1073 int fffi2i1(short *input,         /* I - array of values to be converted     */
 1074             long ntodo,           /* I - number of elements in the array     */
 1075             double scale,         /* I - FITS TSCALn or BSCALE value         */
 1076             double zero,          /* I - FITS TZEROn or BZERO  value         */
 1077             int nullcheck,        /* I - null checking code; 0 = don't check */
 1078                                   /*     1:set null pixels = nullval         */
 1079                                   /*     2: if null pixel, set nullarray = 1 */
 1080             short tnull,          /* I - value of FITS TNULLn keyword if any */
 1081             unsigned char nullval,/* I - set null pixels, if nullcheck = 1   */
 1082             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
 1083             int  *anynull,        /* O - set to 1 if any pixels are null     */
 1084             unsigned char *output,/* O - array of converted pixels           */
 1085             int *status)          /* IO - error status                       */
 1086 /*
 1087   Copy input to output following reading of the input from a FITS file.
 1088   Check for null values and do datatype conversion and scaling if required.
 1089   The nullcheck code value determines how any null values in the input array
 1090   are treated.  A null value is an input pixel that is equal to tnull.  If 
 1091   nullcheck = 0, then no checking for nulls is performed and any null values
 1092   will be transformed just like any other pixel.  If nullcheck = 1, then the
 1093   output pixel will be set = nullval if the corresponding input pixel is null.
 1094   If nullcheck = 2, then if the pixel is null then the corresponding value of
 1095   nullarray will be set to 1; the value of nullarray for non-null pixels 
 1096   will = 0.  The anynull parameter will be set = 1 if any of the returned
 1097   pixels are null, otherwise anynull will be returned with a value = 0;
 1098 */
 1099 {
 1100     long ii;
 1101     double dvalue;
 1102 
 1103     if (nullcheck == 0)     /* no null checking required */
 1104     {
 1105         if (scale == 1. && zero == 0.)      /* no scaling */
 1106         {       
 1107             for (ii = 0; ii < ntodo; ii++)
 1108             {
 1109                 if (input[ii] < 0)
 1110                 {
 1111                     *status = OVERFLOW_ERR;
 1112                     output[ii] = 0;
 1113                 }
 1114                 else if (input[ii] > UCHAR_MAX)
 1115                 {
 1116                     *status = OVERFLOW_ERR;
 1117                     output[ii] = UCHAR_MAX;
 1118                 }
 1119                 else
 1120                     output[ii] = (unsigned char) input[ii];
 1121             }
 1122         }
 1123         else             /* must scale the data */
 1124         {
 1125             for (ii = 0; ii < ntodo; ii++)
 1126             {
 1127                 dvalue = input[ii] * scale + zero;
 1128 
 1129                 if (dvalue < DUCHAR_MIN)
 1130                 {
 1131                     *status = OVERFLOW_ERR;
 1132                     output[ii] = 0;
 1133                 }
 1134                 else if (dvalue > DUCHAR_MAX)
 1135                 {
 1136                     *status = OVERFLOW_ERR;
 1137                     output[ii] = UCHAR_MAX;
 1138                 }
 1139                 else
 1140                     output[ii] = (unsigned char) dvalue;
 1141             }
 1142         }
 1143     }
 1144     else        /* must check for null values */
 1145     {
 1146         if (scale == 1. && zero == 0.)  /* no scaling */
 1147         {       
 1148             for (ii = 0; ii < ntodo; ii++)
 1149             {
 1150                 if (input[ii] == tnull)
 1151                 {
 1152                     *anynull = 1;
 1153                     if (nullcheck == 1)
 1154                         output[ii] = nullval;
 1155                     else
 1156                         nullarray[ii] = 1;
 1157                 }
 1158 
 1159                 else
 1160                 {
 1161                     if (input[ii] < 0)
 1162                     {
 1163                         *status = OVERFLOW_ERR;
 1164                         output[ii] = 0;
 1165                     }
 1166                     else if (input[ii] > UCHAR_MAX)
 1167                     {
 1168                         *status = OVERFLOW_ERR;
 1169                         output[ii] = UCHAR_MAX;
 1170                     }
 1171                     else
 1172                         output[ii] = (unsigned char) input[ii];
 1173                 }
 1174             }
 1175         }
 1176         else                  /* must scale the data */
 1177         {
 1178             for (ii = 0; ii < ntodo; ii++)
 1179             {
 1180                 if (input[ii] == tnull)
 1181                 {
 1182                     *anynull = 1;
 1183                     if (nullcheck == 1)
 1184                         output[ii] = nullval;
 1185                     else
 1186                         nullarray[ii] = 1;
 1187                 }
 1188                 else
 1189                 {
 1190                     dvalue = input[ii] * scale + zero;
 1191 
 1192                     if (dvalue < DUCHAR_MIN)
 1193                     {
 1194                         *status = OVERFLOW_ERR;
 1195                         output[ii] = 0;
 1196                     }
 1197                     else if (dvalue > DUCHAR_MAX)
 1198                     {
 1199                         *status = OVERFLOW_ERR;
 1200                         output[ii] = UCHAR_MAX;
 1201                     }
 1202                     else
 1203                         output[ii] = (unsigned char) dvalue;
 1204                 }
 1205             }
 1206         }
 1207     }
 1208     return(*status);
 1209 }
 1210 /*--------------------------------------------------------------------------*/
 1211 int fffi4i1(INT32BIT *input,          /* I - array of values to be converted     */
 1212             long ntodo,           /* I - number of elements in the array     */
 1213             double scale,         /* I - FITS TSCALn or BSCALE value         */
 1214             double zero,          /* I - FITS TZEROn or BZERO  value         */
 1215             int nullcheck,        /* I - null checking code; 0 = don't check */
 1216                                   /*     1:set null pixels = nullval         */
 1217                                   /*     2: if null pixel, set nullarray = 1 */
 1218             INT32BIT tnull,       /* I - value of FITS TNULLn keyword if any */
 1219             unsigned char nullval,/* I - set null pixels, if nullcheck = 1   */
 1220             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
 1221             int  *anynull,        /* O - set to 1 if any pixels are null     */
 1222             unsigned char *output,/* O - array of converted pixels           */
 1223             int *status)          /* IO - error status                       */
 1224 /*
 1225   Copy input to output following reading of the input from a FITS file.
 1226   Check for null values and do datatype conversion and scaling if required.
 1227   The nullcheck code value determines how any null values in the input array
 1228   are treated.  A null value is an input pixel that is equal to tnull.  If 
 1229   nullcheck = 0, then no checking for nulls is performed and any null values
 1230   will be transformed just like any other pixel.  If nullcheck = 1, then the
 1231   output pixel will be set = nullval if the corresponding input pixel is null.
 1232   If nullcheck = 2, then if the pixel is null then the corresponding value of
 1233   nullarray will be set to 1; the value of nullarray for non-null pixels 
 1234   will = 0.  The anynull parameter will be set = 1 if any of the returned
 1235   pixels are null, otherwise anynull will be returned with a value = 0;
 1236 */
 1237 {
 1238     long ii;
 1239     double dvalue;
 1240 
 1241     if (nullcheck == 0)     /* no null checking required */
 1242     {
 1243         if (scale == 1. && zero == 0.)      /* no scaling */
 1244         {       
 1245             for (ii = 0; ii < ntodo; ii++)
 1246             {
 1247                 if (input[ii] < 0)
 1248                 {
 1249                     *status = OVERFLOW_ERR;
 1250                     output[ii] = 0;
 1251                 }
 1252                 else if (input[ii] > UCHAR_MAX)
 1253                 {
 1254                     *status = OVERFLOW_ERR;
 1255                     output[ii] = UCHAR_MAX;
 1256                 }
 1257                 else
 1258                     output[ii] = (unsigned char) input[ii];
 1259             }
 1260         }
 1261         else             /* must scale the data */
 1262         {
 1263             for (ii = 0; ii < ntodo; ii++)
 1264             {
 1265                 dvalue = input[ii] * scale + zero;
 1266 
 1267                 if (dvalue < DUCHAR_MIN)
 1268                 {
 1269                     *status = OVERFLOW_ERR;
 1270                     output[ii] = 0;
 1271                 }
 1272                 else if (dvalue > DUCHAR_MAX)
 1273                 {
 1274                     *status = OVERFLOW_ERR;
 1275                     output[ii] = UCHAR_MAX;
 1276                 }
 1277                 else
 1278                     output[ii] = (unsigned char) dvalue;
 1279             }
 1280         }
 1281     }
 1282     else        /* must check for null values */
 1283     {
 1284         if (scale == 1. && zero == 0.)  /* no scaling */
 1285         {       
 1286             for (ii = 0; ii < ntodo; ii++)
 1287             {
 1288                 if (input[ii] == tnull)
 1289                 {
 1290                     *anynull = 1;
 1291                     if (nullcheck == 1)
 1292                         output[ii] = nullval;
 1293                     else
 1294                         nullarray[ii] = 1;
 1295                 }
 1296                 else
 1297                 {
 1298                     if (input[ii] < 0)
 1299                     {
 1300                         *status = OVERFLOW_ERR;
 1301                         output[ii] = 0;
 1302                     }
 1303                     else if (input[ii] > UCHAR_MAX)
 1304                     {
 1305                         *status = OVERFLOW_ERR;
 1306                         output[ii] = UCHAR_MAX;
 1307                     }
 1308                     else
 1309                         output[ii] = (unsigned char) input[ii];
 1310                 }
 1311             }
 1312         }
 1313         else                  /* must scale the data */
 1314         {
 1315             for (ii = 0; ii < ntodo; ii++)
 1316             {
 1317                 if (input[ii] == tnull)
 1318                 {
 1319                     *anynull = 1;
 1320                     if (nullcheck == 1)
 1321                         output[ii] = nullval;
 1322                     else
 1323                         nullarray[ii] = 1;
 1324                 }
 1325                 else
 1326                 {
 1327                     dvalue = input[ii] * scale + zero;
 1328 
 1329                     if (dvalue < DUCHAR_MIN)
 1330                     {
 1331                         *status = OVERFLOW_ERR;
 1332                         output[ii] = 0;
 1333                     }
 1334                     else if (dvalue > DUCHAR_MAX)
 1335                     {
 1336                         *status = OVERFLOW_ERR;
 1337                         output[ii] = UCHAR_MAX;
 1338                     }
 1339                     else
 1340                         output[ii] = (unsigned char) dvalue;
 1341                 }
 1342             }
 1343         }
 1344     }
 1345     return(*status);
 1346 }
 1347 /*--------------------------------------------------------------------------*/
 1348 int fffi8i1(LONGLONG *input,      /* I - array of values to be converted     */
 1349             long ntodo,           /* I - number of elements in the array     */
 1350             double scale,         /* I - FITS TSCALn or BSCALE value         */
 1351             double zero,          /* I - FITS TZEROn or BZERO  value         */
 1352             int nullcheck,        /* I - null checking code; 0 = don't check */
 1353                                   /*     1:set null pixels = nullval         */
 1354                                   /*     2: if null pixel, set nullarray = 1 */
 1355             LONGLONG tnull,       /* I - value of FITS TNULLn keyword if any */
 1356             unsigned char nullval,/* I - set null pixels, if nullcheck = 1   */
 1357             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
 1358             int  *anynull,        /* O - set to 1 if any pixels are null     */
 1359             unsigned char *output,/* O - array of converted pixels           */
 1360             int *status)          /* IO - error status                       */
 1361 /*
 1362   Copy input to output following reading of the input from a FITS file.
 1363   Check for null values and do datatype conversion and scaling if required.
 1364   The nullcheck code value determines how any null values in the input array
 1365   are treated.  A null value is an input pixel that is equal to tnull.  If 
 1366   nullcheck = 0, then no checking for nulls is performed and any null values
 1367   will be transformed just like any other pixel.  If nullcheck = 1, then the
 1368   output pixel will be set = nullval if the corresponding input pixel is null.
 1369   If nullcheck = 2, then if the pixel is null then the corresponding value of
 1370   nullarray will be set to 1; the value of nullarray for non-null pixels 
 1371   will = 0.  The anynull parameter will be set = 1 if any of the returned
 1372   pixels are null, otherwise anynull will be returned with a value = 0;
 1373 */
 1374 {
 1375     long ii;
 1376     double dvalue;
 1377     ULONGLONG ulltemp;
 1378 
 1379     if (nullcheck == 0)     /* no null checking required */
 1380     {
 1381         if (scale == 1. && zero ==  9223372036854775808.)
 1382         {       
 1383             /* The column we read contains unsigned long long values. */
 1384             /* Instead of adding 9223372036854775808, it is more efficient */
 1385             /* and more precise to just flip the sign bit with the XOR operator */
 1386 
 1387             for (ii = 0; ii < ntodo; ii++) {
 1388  
 1389                 ulltemp = (ULONGLONG) (((LONGLONG) input[ii]) ^ 0x8000000000000000);
 1390 
 1391                 if (ulltemp > UCHAR_MAX)
 1392                 {
 1393                     *status = OVERFLOW_ERR;
 1394                     output[ii] = UCHAR_MAX;
 1395                 }
 1396                 else
 1397                     output[ii] = (unsigned char) ulltemp;
 1398             }
 1399         }
 1400         else if (scale == 1. && zero == 0.)      /* no scaling */
 1401         {       
 1402             for (ii = 0; ii < ntodo; ii++)
 1403             {
 1404                 if (input[ii] < 0)
 1405                 {
 1406                     *status = OVERFLOW_ERR;
 1407                     output[ii] = 0;
 1408                 }
 1409                 else if (input[ii] > UCHAR_MAX)
 1410                 {
 1411                     *status = OVERFLOW_ERR;
 1412                     output[ii] = UCHAR_MAX;
 1413                 }
 1414                 else
 1415                     output[ii] = (unsigned char) input[ii];
 1416             }
 1417         }
 1418         else             /* must scale the data */
 1419         {
 1420             for (ii = 0; ii < ntodo; ii++)
 1421             {
 1422                 dvalue = input[ii] * scale + zero;
 1423 
 1424                 if (dvalue < DUCHAR_MIN)
 1425                 {
 1426                     *status = OVERFLOW_ERR;
 1427                     output[ii] = 0;
 1428                 }
 1429                 else if (dvalue > DUCHAR_MAX)
 1430                 {
 1431                     *status = OVERFLOW_ERR;
 1432                     output[ii] = UCHAR_MAX;
 1433                 }
 1434                 else
 1435                     output[ii] = (unsigned char) dvalue;
 1436             }
 1437         }
 1438     }
 1439     else        /* must check for null values */
 1440     {
 1441         if (scale == 1. && zero ==  9223372036854775808.)
 1442         {       
 1443             /* The column we read contains unsigned long long values. */
 1444             /* Instead of adding 9223372036854775808, it is more efficient */
 1445             /* and more precise to just flip the sign bit with the XOR operator */
 1446 
 1447             for (ii = 0; ii < ntodo; ii++) {
 1448  
 1449                 if (input[ii] == tnull)
 1450                 {
 1451                     *anynull = 1;
 1452                     if (nullcheck == 1)
 1453                         output[ii] = nullval;
 1454                     else
 1455                         nullarray[ii] = 1;
 1456                 }
 1457                 else
 1458                 {
 1459                     ulltemp = (ULONGLONG) (((LONGLONG) input[ii]) ^ 0x8000000000000000);
 1460 
 1461                     if (ulltemp > UCHAR_MAX)
 1462                     {
 1463                         *status = OVERFLOW_ERR;
 1464                         output[ii] = UCHAR_MAX;
 1465                     }
 1466                     else
 1467             {
 1468                         output[ii] = (unsigned char) ulltemp;
 1469             }
 1470                 }
 1471             }
 1472         }
 1473         else if (scale == 1. && zero == 0.)  /* no scaling */
 1474         {       
 1475             for (ii = 0; ii < ntodo; ii++)
 1476             {
 1477                 if (input[ii] == tnull)
 1478                 {
 1479                     *anynull = 1;
 1480                     if (nullcheck == 1)
 1481                         output[ii] = nullval;
 1482                     else
 1483                         nullarray[ii] = 1;
 1484                 }
 1485                 else
 1486                 {
 1487                     if (input[ii] < 0)
 1488                     {
 1489                         *status = OVERFLOW_ERR;
 1490                         output[ii] = 0;
 1491                     }
 1492                     else if (input[ii] > UCHAR_MAX)
 1493                     {
 1494                         *status = OVERFLOW_ERR;
 1495                         output[ii] = UCHAR_MAX;
 1496                     }
 1497                     else
 1498                         output[ii] = (unsigned char) input[ii];
 1499                 }
 1500             }
 1501         }
 1502         else                  /* must scale the data */
 1503         {
 1504             for (ii = 0; ii < ntodo; ii++)
 1505             {
 1506                 if (input[ii] == tnull)
 1507                 {
 1508                     *anynull = 1;
 1509                     if (nullcheck == 1)
 1510                         output[ii] = nullval;
 1511                     else
 1512                         nullarray[ii] = 1;
 1513                 }
 1514                 else
 1515                 {
 1516                     dvalue = input[ii] * scale + zero;
 1517 
 1518                     if (dvalue < DUCHAR_MIN)
 1519                     {
 1520                         *status = OVERFLOW_ERR;
 1521                         output[ii] = 0;
 1522                     }
 1523                     else if (dvalue > DUCHAR_MAX)
 1524                     {
 1525                         *status = OVERFLOW_ERR;
 1526                         output[ii] = UCHAR_MAX;
 1527                     }
 1528                     else
 1529                         output[ii] = (unsigned char) dvalue;
 1530                 }
 1531             }
 1532         }
 1533     }
 1534     return(*status);
 1535 }
 1536 /*--------------------------------------------------------------------------*/
 1537 int fffr4i1(float *input,         /* I - array of values to be converted     */
 1538             long ntodo,           /* I - number of elements in the array     */
 1539             double scale,         /* I - FITS TSCALn or BSCALE value         */
 1540             double zero,          /* I - FITS TZEROn or BZERO  value         */
 1541             int nullcheck,        /* I - null checking code; 0 = don't check */
 1542                                   /*     1:set null pixels = nullval         */
 1543                                   /*     2: if null pixel, set nullarray = 1 */
 1544             unsigned char nullval,/* I - set null pixels, if nullcheck = 1   */
 1545             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
 1546             int  *anynull,        /* O - set to 1 if any pixels are null     */
 1547             unsigned char *output,/* O - array of converted pixels           */
 1548             int *status)          /* IO - error status                       */
 1549 /*
 1550   Copy input to output following reading of the input from a FITS file.
 1551   Check for null values and do datatype conversion and scaling if required.
 1552   The nullcheck code value determines how any null values in the input array
 1553   are treated.  A null value is an input pixel that is equal to NaN.  If 
 1554   nullcheck = 0, then no checking for nulls is performed and any null values
 1555   will be transformed just like any other pixel.  If nullcheck = 1, then the
 1556   output pixel will be set = nullval if the corresponding input pixel is null.
 1557   If nullcheck = 2, then if the pixel is null then the corresponding value of
 1558   nullarray will be set to 1; the value of nullarray for non-null pixels 
 1559   will = 0.  The anynull parameter will be set = 1 if any of the returned
 1560   pixels are null, otherwise anynull will be returned with a value = 0;
 1561 */
 1562 {
 1563     long ii;
 1564     double dvalue;
 1565     short *sptr, iret;
 1566 
 1567     if (nullcheck == 0)     /* no null checking required */
 1568     {
 1569         if (scale == 1. && zero == 0.)      /* no scaling */
 1570         {       
 1571             for (ii = 0; ii < ntodo; ii++)
 1572             {
 1573                 if (input[ii] < DUCHAR_MIN)
 1574                 {
 1575                     *status = OVERFLOW_ERR;
 1576                     output[ii] = 0;
 1577                 }
 1578                 else if (input[ii] > DUCHAR_MAX)
 1579                 {
 1580                     *status = OVERFLOW_ERR;
 1581                     output[ii] = UCHAR_MAX;
 1582                 }
 1583                 else
 1584                     output[ii] = (unsigned char) input[ii];
 1585             }
 1586         }
 1587         else             /* must scale the data */
 1588         {
 1589             for (ii = 0; ii < ntodo; ii++)
 1590             {
 1591                 dvalue = input[ii] * scale + zero;
 1592 
 1593                 if (dvalue < DUCHAR_MIN)
 1594                 {
 1595                     *status = OVERFLOW_ERR;
 1596                     output[ii] = 0;
 1597                 }
 1598                 else if (dvalue > DUCHAR_MAX)
 1599                 {
 1600                     *status = OVERFLOW_ERR;
 1601                     output[ii] = UCHAR_MAX;
 1602                 }
 1603                 else
 1604                     output[ii] = (unsigned char) dvalue;
 1605             }
 1606         }
 1607     }
 1608     else        /* must check for null values */
 1609     {
 1610         sptr = (short *) input;
 1611 
 1612 #if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
 1613         sptr++;       /* point to MSBs */
 1614 #endif
 1615         if (scale == 1. && zero == 0.)  /* no scaling */
 1616         {       
 1617             for (ii = 0; ii < ntodo; ii++, sptr += 2)
 1618             {
 1619               /* use redundant boolean logic in following statement */
 1620               /* to suppress irritating Borland compiler warning message */
 1621               if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
 1622               {
 1623                   if (iret == 1)  /* is it a NaN? */
 1624                   {
 1625                     *anynull = 1;
 1626                     if (nullcheck == 1)
 1627                         output[ii] = nullval;
 1628                     else
 1629                         nullarray[ii] = 1;
 1630                   }
 1631                   else            /* it's an underflow */
 1632                      output[ii] = 0;
 1633               }
 1634               else
 1635                 {
 1636                     if (input[ii] < DUCHAR_MIN)
 1637                     {
 1638                         *status = OVERFLOW_ERR;
 1639                         output[ii] = 0;
 1640                     }
 1641                     else if (input[ii] > DUCHAR_MAX)
 1642                     {
 1643                         *status = OVERFLOW_ERR;
 1644                         output[ii] = UCHAR_MAX;
 1645                     }
 1646                     else
 1647                         output[ii] = (unsigned char) input[ii];
 1648                 }
 1649             }
 1650         }
 1651         else                  /* must scale the data */
 1652         {
 1653             for (ii = 0; ii < ntodo; ii++, sptr += 2)
 1654             {
 1655               if (0 != (iret = fnan(*sptr) ) )  /* test for NaN or underflow */
 1656               {
 1657                   if (iret == 1)  /* is it a NaN? */
 1658                   {  
 1659                     *anynull = 1;
 1660                     if (nullcheck == 1)
 1661                         output[ii] = nullval;
 1662                     else
 1663                         nullarray[ii] = 1;
 1664                   }
 1665                   else            /* it's an underflow */
 1666                   {
 1667                     if (zero < DUCHAR_MIN)
 1668                     {
 1669                         *status = OVERFLOW_ERR;
 1670                         output[ii] = 0;
 1671                     }
 1672                     else if (zero > DUCHAR_MAX)
 1673                     {
 1674                         *status = OVERFLOW_ERR;
 1675                         output[ii] = UCHAR_MAX;
 1676                     }
 1677                     else
 1678                         output[ii] = (unsigned char) zero;
 1679                   }
 1680               }
 1681               else
 1682                 {
 1683                     dvalue = input[ii] * scale + zero;
 1684 
 1685                     if (dvalue < DUCHAR_MIN)
 1686                     {
 1687                         *status = OVERFLOW_ERR;
 1688                         output[ii] = 0;
 1689                     }
 1690                     else if (dvalue > DUCHAR_MAX)
 1691                     {
 1692                         *status = OVERFLOW_ERR;
 1693                         output[ii] = UCHAR_MAX;
 1694                     }
 1695                     else
 1696                         output[ii] = (unsigned char) dvalue;
 1697                 }
 1698             }
 1699         }
 1700     }
 1701     return(*status);
 1702 }
 1703 /*--------------------------------------------------------------------------*/
 1704 int fffr8i1(double *input,        /* I - array of values to be converted     */
 1705             long ntodo,           /* I - number of elements in the array     */
 1706             double scale,         /* I - FITS TSCALn or BSCALE value         */
 1707             double zero,          /* I - FITS TZEROn or BZERO  value         */
 1708             int nullcheck,        /* I - null checking code; 0 = don't check */
 1709                                   /*     1:set null pixels = nullval         */
 1710                                   /*     2: if null pixel, set nullarray = 1 */
 1711             unsigned char nullval,/* I - set null pixels, if nullcheck = 1   */
 1712             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
 1713             int  *anynull,        /* O - set to 1 if any pixels are null     */
 1714             unsigned char *output,/* O - array of converted pixels           */
 1715             int *status)          /* IO - error status                       */
 1716 /*
 1717   Copy input to output following reading of the input from a FITS file.
 1718   Check for null values and do datatype conversion and scaling if required.
 1719   The nullcheck code value determines how any null values in the input array
 1720   are treated.  A null value is an input pixel that is equal to NaN.  If 
 1721   nullcheck = 0, then no checking for nulls is performed and any null values
 1722   will be transformed just like any other pixel.  If nullcheck = 1, then the
 1723   output pixel will be set = nullval if the corresponding input pixel is null.
 1724   If nullcheck = 2, then if the pixel is null then the corresponding value of
 1725   nullarray will be set to 1; the value of nullarray for non-null pixels 
 1726   will = 0.  The anynull parameter will be set = 1 if any of the returned
 1727   pixels are null, otherwise anynull will be returned with a value = 0;
 1728 */
 1729 {
 1730     long ii;
 1731     double dvalue;
 1732     short *sptr, iret;
 1733 
 1734     if (nullcheck == 0)     /* no null checking required */
 1735     {
 1736         if (scale == 1. && zero == 0.)      /* no scaling */
 1737         {       
 1738             for (ii = 0; ii < ntodo; ii++)
 1739             {
 1740                 if (input[ii] < DUCHAR_MIN)
 1741                 {
 1742                     *status = OVERFLOW_ERR;
 1743                     output[ii] = 0;
 1744                 }
 1745                 else if (input[ii] > DUCHAR_MAX)
 1746                 {
 1747                     *status = OVERFLOW_ERR;
 1748                     output[ii] = UCHAR_MAX;
 1749                 }
 1750                 else
 1751                     output[ii] = (unsigned char) input[ii];
 1752             }
 1753         }
 1754         else             /* must scale the data */
 1755         {
 1756             for (ii = 0; ii < ntodo; ii++)
 1757             {
 1758                 dvalue = input[ii] * scale + zero;
 1759 
 1760                 if (dvalue < DUCHAR_MIN)
 1761                 {
 1762                     *status = OVERFLOW_ERR;
 1763                     output[ii] = 0;
 1764                 }
 1765                 else if (dvalue > DUCHAR_MAX)
 1766                 {
 1767                     *status = OVERFLOW_ERR;
 1768                     output[ii] = UCHAR_MAX;
 1769                 }
 1770                 else
 1771                     output[ii] = (unsigned char) dvalue;
 1772             }
 1773         }
 1774     }
 1775     else        /* must check for null values */
 1776     {
 1777         sptr = (short *) input;
 1778 
 1779 #if BYTESWAPPED && MACHINE != VAXVMS && MACHINE != ALPHAVMS
 1780         sptr += 3;       /* point to MSBs */
 1781 #endif
 1782         if (scale == 1. && zero == 0.)  /* no scaling */
 1783         {       
 1784             for (ii = 0; ii < ntodo; ii++, sptr += 4)
 1785             {
 1786               if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
 1787               {
 1788                   if (iret == 1)  /* is it a NaN? */
 1789                   {
 1790                     *anynull = 1;
 1791                     if (nullcheck == 1)
 1792                         output[ii] = nullval;
 1793                     else
 1794                         nullarray[ii] = 1;
 1795                   }
 1796                   else            /* it's an underflow */
 1797                      output[ii] = 0;
 1798               }
 1799               else
 1800                 {
 1801                     if (input[ii] < DUCHAR_MIN)
 1802                     {
 1803                         *status = OVERFLOW_ERR;
 1804                         output[ii] = 0;
 1805                     }
 1806                     else if (input[ii] > DUCHAR_MAX)
 1807                     {
 1808                         *status = OVERFLOW_ERR;
 1809                         output[ii] = UCHAR_MAX;
 1810                     }
 1811                     else
 1812                         output[ii] = (unsigned char) input[ii];
 1813                 }
 1814             }
 1815         }
 1816         else                  /* must scale the data */
 1817         {
 1818             for (ii = 0; ii < ntodo; ii++, sptr += 4)
 1819             {
 1820               if (0 != (iret = dnan(*sptr)) )  /* test for NaN or underflow */
 1821               {
 1822                   if (iret == 1)  /* is it a NaN? */
 1823                   {  
 1824                     *anynull = 1;
 1825                     if (nullcheck == 1)
 1826                         output[ii] = nullval;
 1827                     else
 1828                         nullarray[ii] = 1;
 1829                   }
 1830                   else            /* it's an underflow */
 1831                   {
 1832                     if (zero < DUCHAR_MIN)
 1833                     {
 1834                         *status = OVERFLOW_ERR;
 1835                         output[ii] = 0;
 1836                     }
 1837                     else if (zero > DUCHAR_MAX)
 1838                     {
 1839                         *status = OVERFLOW_ERR;
 1840                         output[ii] = UCHAR_MAX;
 1841                     }
 1842                     else
 1843                         output[ii] = (unsigned char) zero;
 1844                   }
 1845               }
 1846               else
 1847                 {
 1848                     dvalue = input[ii] * scale + zero;
 1849 
 1850                     if (dvalue < DUCHAR_MIN)
 1851                     {
 1852                         *status = OVERFLOW_ERR;
 1853                         output[ii] = 0;
 1854                     }
 1855                     else if (dvalue > DUCHAR_MAX)
 1856                     {
 1857                         *status = OVERFLOW_ERR;
 1858                         output[ii] = UCHAR_MAX;
 1859                     }
 1860                     else
 1861                         output[ii] = (unsigned char) dvalue;
 1862                 }
 1863             }
 1864         }
 1865     }
 1866     return(*status);
 1867 }
 1868 /*--------------------------------------------------------------------------*/
 1869 int fffstri1(char *input,         /* I - array of values to be converted     */
 1870             long ntodo,           /* I - number of elements in the array     */
 1871             double scale,         /* I - FITS TSCALn or BSCALE value         */
 1872             double zero,          /* I - FITS TZEROn or BZERO  value         */
 1873             long twidth,          /* I - width of each substring of chars    */
 1874             double implipower,    /* I - power of 10 of implied decimal      */
 1875             int nullcheck,        /* I - null checking code; 0 = don't check */
 1876                                   /*     1:set null pixels = nullval         */
 1877                                   /*     2: if null pixel, set nullarray = 1 */
 1878             char  *snull,         /* I - value of FITS null string, if any   */
 1879             unsigned char nullval, /* I - set null pixels, if nullcheck = 1  */
 1880             char *nullarray,      /* I - bad pixel array, if nullcheck = 2   */
 1881             int  *anynull,        /* O - set to 1 if any pixels are null     */
 1882             unsigned char *output, /* O - array of converted pixels          */
 1883             int *status)          /* IO - error status                       */
 1884 /*
 1885   Copy input to output following reading of the input from a FITS file. Check
 1886   for null values and do scaling if required. The nullcheck code value
 1887   determines how any null values in the input array are treated. A null
 1888   value is an input pixel that is equal to snull.  If nullcheck= 0, then
 1889   no special checking for nulls is performed.  If nullcheck = 1, then the
 1890   output pixel will be set = nullval if the corresponding input pixel is null.
 1891   If nullcheck = 2, then if the pixel is null then the corresponding value of
 1892   nullarray will be set to 1; the value of nullarray for non-null pixels 
 1893   will = 0.  The anynull parameter will be set = 1 if any of the returned
 1894   pixels are null, otherwise anynull will be returned with a value = 0;
 1895 */
 1896 {
 1897     int  nullen;
 1898     long ii;
 1899     double dvalue;
 1900     char *cstring, message[FLEN_ERRMSG];
 1901     char *cptr, *tpos;
 1902     char tempstore, chrzero = '0';
 1903     double val, power;
 1904     int exponent, sign, esign, decpt;
 1905 
 1906     nullen = strlen(snull);
 1907     cptr = input;  /* pointer to start of input string */
 1908     for (ii = 0; ii < ntodo; ii++)
 1909     {
 1910       cstring = cptr;
 1911       /* temporarily insert a null terminator at end of the string */
 1912       tpos = cptr + twidth;
 1913       tempstore = *tpos;
 1914       *tpos = 0;
 1915 
 1916       /* check if null value is defined, and if the    */
 1917       /* column string is identical to the null string */
 1918       if (snull[0] != ASCII_NULL_UNDEFINED && 
 1919          !strncmp(snull, cptr, nullen) )
 1920       {
 1921         if (nullcheck)  
 1922         {
 1923           *anynull = 1;    
 1924           if (nullcheck == 1)
 1925             output[ii] = nullval;
 1926           else
 1927             nullarray[ii] = 1;
 1928         }
 1929         cptr += twidth;
 1930       }
 1931       else
 1932       {
 1933         /* value is not the null value, so decode it */
 1934         /* remove any embedded blank characters from the string */
 1935 
 1936         decpt = 0;
 1937         sign = 1;
 1938         val  = 0.;
 1939         power = 1.;
 1940         exponent = 0;
 1941         esign = 1;
 1942 
 1943         while (*cptr == ' ')               /* skip leading blanks */
 1944            cptr++;
 1945 
 1946         if (*cptr == '-' || *cptr == '+')  /* check for leading sign */
 1947         {
 1948           if (*cptr == '-')
 1949              sign = -1;
 1950 
 1951           cptr++;
 1952 
 1953           while (*cptr == ' ')         /* skip blanks between sign and value */
 1954             cptr++;
 1955         }
 1956 
 1957         while (*cptr >= '0' && *cptr <= '9')
 1958         {
 1959           val = val * 10. + *cptr - chrzero;  /* accumulate the value */
 1960           cptr++;
 1961 
 1962           while (*cptr == ' ')         /* skip embedded blanks in the value */
 1963             cptr++;
 1964         }
 1965 
 1966         if (*cptr == '.' || *cptr == ',')       /* check for decimal point */
 1967         {
 1968           decpt = 1;
 1969           cptr++;
 1970           while (*cptr == ' ')         /* skip any blanks */
 1971             cptr++;
 1972 
 1973           while (*cptr >= '0' && *cptr <= '9')
 1974           {
 1975             val = val * 10. + *cptr - chrzero;  /* accumulate the value */
 1976             power = power * 10.;
 1977             cptr++;
 1978 
 1979             while (*cptr == ' ')         /* skip embedded blanks in the value */
 1980               cptr++;
 1981           }
 1982         }
 1983 
 1984         if (*cptr == 'E' || *cptr == 'D')  /* check for exponent */
 1985         {
 1986           cptr++;
 1987           while (*cptr == ' ')         /* skip blanks */
 1988               cptr++;
 1989   
 1990           if (*cptr == '-' || *cptr == '+')  /* check for exponent sign */
 1991           {
 1992             if (*cptr == '-')
 1993                esign = -1;
 1994 
 1995             cptr++;
 1996 
 1997             while (*cptr == ' ')        /* skip blanks between sign and exp */
 1998               cptr++;
 1999           }
 2000 
 2001           while (*cptr >= '0' && *cptr <= '9')
 2002           {
 2003             exponent = exponent * 10 + *cptr - chrzero;  /* accumulate exp */
 2004             cptr++;
 2005 
 2006             while (*cptr == ' ')         /* skip embedded blanks */
 2007               cptr++;
 2008           }
 2009         }
 2010 
 2011         if (*cptr  != 0)  /* should end up at the null terminator */
 2012         {
 2013           snprintf(message, FLEN_ERRMSG,"Cannot read number from ASCII table");
 2014           ffpmsg(message);
 2015           snprintf(message, FLEN_ERRMSG,"Column field = %s.", cstring);
 2016           ffpmsg(message);
 2017           /* restore the char that was overwritten by the null */
 2018           *tpos = tempstore;
 2019           return(*status = BAD_C2D);
 2020         }
 2021 
 2022         if (!decpt)  /* if no explicit decimal, use implied */
 2023            power = implipower;
 2024 
 2025         dvalue = (sign * val / power) * pow(10., (double) (esign * exponent));
 2026 
 2027         dvalue = dvalue * scale + zero;   /* apply the scaling */
 2028 
 2029         if (dvalue < DUCHAR_MIN)
 2030         {
 2031             *status = OVERFLOW_ERR;
 2032             output[ii] = 0;
 2033         }
 2034         else if (dvalue > DUCHAR_MAX)
 2035         {
 2036             *status = OVERFLOW_ERR;
 2037             output[ii] = UCHAR_MAX;
 2038         }
 2039         else
 2040             output[ii] = (unsigned char) dvalue;
 2041       }
 2042       /* restore the char that was overwritten by the null */
 2043       *tpos = tempstore;
 2044     }
 2045     return(*status);
 2046 }