2022-08-06 21:03:09 -06:00
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
|
|
@file dfits.c
|
|
|
|
@author Nicolas Devillard
|
|
|
|
@date 30 Mar 2000
|
|
|
|
@version $Revision: 1.3 $
|
|
|
|
@brief FITS header display
|
|
|
|
*/
|
|
|
|
/*----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
$Id: dfits.c,v 1.3 2005/07/19 15:38:52 yjung Exp $
|
|
|
|
$Author: yjung $
|
|
|
|
$Date: 2005/07/19 15:38:52 $
|
|
|
|
$Revision: 1.3 $
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
|
|
Includes
|
|
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "qfits.h"
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
|
|
Define
|
|
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
#define BLOCK_SIZE 2880
|
|
|
|
#define LGTH 80
|
|
|
|
#define MAGIC "SIMPLE ="
|
|
|
|
|
|
|
|
/* If compiled against zlib, include support for gzipped files */
|
|
|
|
#if HAVE_ZLIB
|
|
|
|
#include "zlib.h"
|
|
|
|
#define FILE gzFile
|
|
|
|
#define fopen gzopen
|
|
|
|
#define fclose gzclose
|
|
|
|
#define fread(b,s,n,f) gzread(f,b,n*s)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
|
|
Function prototypes
|
|
|
|
-----------------------------------------------------------------------------*/
|
|
|
|
|
2022-08-06 22:20:48 -06:00
|
|
|
void usage (char *pname);
|
|
|
|
void parse_cmd_line (int, char **, int *, int *, int *);
|
|
|
|
int dump_fits_filter (FILE *, int);
|
|
|
|
int dump_fits (char *, int);
|
|
|
|
char *rstrip (char *);
|
2022-08-06 21:03:09 -06:00
|
|
|
|
|
|
|
/*-----------------------------------------------------------------------------
|
|
|
|
Main
|
|
|
|
-----------------------------------------------------------------------------*/
|
2022-08-06 22:20:48 -06:00
|
|
|
int
|
|
|
|
main (int argc, char *argv[])
|
2022-08-06 21:03:09 -06:00
|
|
|
{
|
2022-08-06 22:20:48 -06:00
|
|
|
int xtnum;
|
|
|
|
int c_arg;
|
|
|
|
int filter;
|
|
|
|
int err;
|
2022-08-06 21:03:09 -06:00
|
|
|
|
2022-08-06 22:20:48 -06:00
|
|
|
/* No arguments prints out a usage message */
|
|
|
|
if (argc < 2)
|
|
|
|
usage (argv[0]);
|
2022-08-06 21:03:09 -06:00
|
|
|
|
2022-08-06 22:20:48 -06:00
|
|
|
/* Parse command-line options */
|
|
|
|
parse_cmd_line (argc, argv, &xtnum, &filter, &c_arg);
|
2022-08-06 21:03:09 -06:00
|
|
|
|
2022-08-06 22:20:48 -06:00
|
|
|
/* Filter mode: process data received from stdin */
|
|
|
|
if (filter)
|
|
|
|
{
|
2022-08-06 21:03:09 -06:00
|
|
|
#if HAVE_ZLIB
|
2022-08-06 22:20:48 -06:00
|
|
|
printf ("filter mode does not support gzipped files\n");
|
|
|
|
printf ("use: gunzip -c file.fits | dfits -\n");
|
|
|
|
return 1;
|
2022-08-06 21:03:09 -06:00
|
|
|
#else
|
2022-08-06 22:20:48 -06:00
|
|
|
return dump_fits_filter (stdin, xtnum);
|
2022-08-06 21:03:09 -06:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2022-08-06 22:20:48 -06:00
|
|
|
/* Normal mode: loop on all file names given on command-line */
|
|
|
|
err = 0;
|
|
|
|
while (c_arg < argc)
|
|
|
|
{
|
|
|
|
err += dump_fits (argv[c_arg], xtnum);
|
|
|
|
c_arg++;
|
|
|
|
}
|
|
|
|
return err; /* Returns number of errors during process */
|
2022-08-06 21:03:09 -06:00
|
|
|
}
|
|
|
|
|
2022-08-06 22:20:48 -06:00
|
|
|
void
|
|
|
|
usage (char *pname)
|
2022-08-06 21:03:09 -06:00
|
|
|
{
|
2022-08-06 22:20:48 -06:00
|
|
|
printf ("\n\n"
|
|
|
|
"usage: %s [-x xtnum] <list of FITS files>\n"
|
|
|
|
"usage: %s [-x xtnum] -\n"
|
|
|
|
"\n"
|
|
|
|
"The former version expects file names.\n"
|
|
|
|
"The latter expects data coming in from stdin.\n"
|
|
|
|
"\n"
|
|
|
|
"-x xtnum specifies the extension header to print\n"
|
|
|
|
"-x 0 specifies main header + all extensions\n"
|
|
|
|
"\n\n", pname, pname);
|
2022-08-06 21:03:09 -06:00
|
|
|
|
|
|
|
#if HAVE_ZLIB
|
2022-08-06 22:20:48 -06:00
|
|
|
printf ("This program was compiled against zlib %s\n"
|
|
|
|
"This means you can use it with gzipped FITS files\n"
|
|
|
|
"as with uncompressed FITS files.\n"
|
|
|
|
"NB: this does not apply to the '-' option (input from stdin)\n"
|
|
|
|
"\n\n", ZLIB_VERSION);
|
2022-08-06 21:03:09 -06:00
|
|
|
#endif
|
2022-08-06 22:20:48 -06:00
|
|
|
exit (1);
|
2022-08-06 21:03:09 -06:00
|
|
|
}
|
|
|
|
|
2022-08-06 22:20:48 -06:00
|
|
|
void
|
|
|
|
parse_cmd_line (int argc, char **argv, int *xtnum, int *filter, int *c_arg)
|
2022-08-06 21:03:09 -06:00
|
|
|
{
|
2022-08-06 22:20:48 -06:00
|
|
|
*filter = 0;
|
|
|
|
*xtnum = -1;
|
|
|
|
*c_arg = argc - 1;
|
2022-08-06 21:03:09 -06:00
|
|
|
|
2022-08-06 22:20:48 -06:00
|
|
|
/* If '-' is on the command-line, it must be the last argument */
|
|
|
|
if (!strcmp (argv[argc - 1], "-"))
|
|
|
|
*filter = 1;
|
|
|
|
/* If -x xtnum is on the command-line, it must be the first two arguments */
|
|
|
|
if (!strcmp (argv[1], "-x"))
|
|
|
|
{
|
|
|
|
*xtnum = atoi (argv[2]);
|
|
|
|
*c_arg = 3;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*c_arg = 1;
|
|
|
|
}
|
|
|
|
return;
|
2022-08-06 21:03:09 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Strip off all blank characters in a string from the right-side. */
|
2022-08-06 22:20:48 -06:00
|
|
|
char *
|
|
|
|
rstrip (char *s)
|
2022-08-06 21:03:09 -06:00
|
|
|
{
|
2022-08-06 22:20:48 -06:00
|
|
|
int len;
|
|
|
|
if (s == NULL)
|
|
|
|
return s;
|
|
|
|
len = strlen (s);
|
|
|
|
if (len < 1)
|
|
|
|
return s;
|
|
|
|
len--;
|
|
|
|
while (s[len] == ' ')
|
|
|
|
{
|
|
|
|
s[len] = (char) 0;
|
|
|
|
len--;
|
|
|
|
if (len < 0)
|
|
|
|
break;
|
2022-08-06 21:03:09 -06:00
|
|
|
}
|
2022-08-06 22:20:48 -06:00
|
|
|
return s;
|
2022-08-06 21:03:09 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Dump the requested header (main or extension) from a filename. */
|
2022-08-06 22:20:48 -06:00
|
|
|
int
|
|
|
|
dump_fits (char *name, int xtnum)
|
2022-08-06 21:03:09 -06:00
|
|
|
{
|
2022-08-06 22:20:48 -06:00
|
|
|
FILE *in;
|
|
|
|
int err;
|
2022-08-06 21:03:09 -06:00
|
|
|
|
2022-08-06 22:20:48 -06:00
|
|
|
if ((in = fopen (name, "r")) == NULL)
|
|
|
|
{
|
|
|
|
fprintf (stderr, "error: cannot open file [%s]\n", name);
|
|
|
|
return 1;
|
|
|
|
}
|
2022-08-06 21:03:09 -06:00
|
|
|
|
2022-08-06 22:20:48 -06:00
|
|
|
printf ("====> file %s (main) <====\n", name);
|
|
|
|
err = dump_fits_filter (in, xtnum);
|
|
|
|
fclose (in);
|
|
|
|
return err;
|
2022-08-06 21:03:09 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Dump the requested header (main or extension) from a FILE * */
|
2022-08-06 22:20:48 -06:00
|
|
|
int
|
|
|
|
dump_fits_filter (FILE * in, int xtnum)
|
2022-08-06 21:03:09 -06:00
|
|
|
{
|
2022-08-06 22:20:48 -06:00
|
|
|
int n_xt;
|
|
|
|
char buf[LGTH + 1];
|
|
|
|
int err;
|
|
|
|
int data_bytes, naxis;
|
|
|
|
char *read_val;
|
|
|
|
int skip_blocks;
|
|
|
|
int seeked;
|
2022-08-06 21:03:09 -06:00
|
|
|
|
2022-08-06 22:20:48 -06:00
|
|
|
/* Try getting the first 80 chars */
|
|
|
|
memset (buf, 0, LGTH + 1);
|
|
|
|
if (fread (buf, sizeof (char), LGTH, in) != LGTH)
|
|
|
|
{
|
|
|
|
fprintf (stderr, "error reading input\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
/* Check that it is indeed FITS */
|
|
|
|
if (strncmp (buf, MAGIC, strlen (MAGIC)))
|
|
|
|
{
|
|
|
|
fprintf (stderr, "not a FITS file\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
naxis = 0;
|
|
|
|
data_bytes = 1;
|
|
|
|
if (xtnum < 1)
|
|
|
|
{
|
|
|
|
/* Output main header */
|
|
|
|
printf ("%s\n", rstrip (buf));
|
|
|
|
data_bytes = 1;
|
|
|
|
naxis = 0;
|
|
|
|
while ((err = fread (buf, sizeof (char), LGTH, in)) == LGTH)
|
|
|
|
{
|
|
|
|
printf ("%s\n", rstrip (buf));
|
|
|
|
/* Look for BITPIX keyword */
|
|
|
|
if (buf[0] == 'B' &&
|
|
|
|
buf[1] == 'I' &&
|
|
|
|
buf[2] == 'T' &&
|
|
|
|
buf[3] == 'P' &&
|
|
|
|
buf[4] == 'I' && buf[5] == 'X' && buf[6] == ' ')
|
|
|
|
{
|
|
|
|
read_val = qfits_getvalue (buf);
|
|
|
|
data_bytes *= (int) atoi (read_val) / 8;
|
|
|
|
if (data_bytes < 0)
|
|
|
|
data_bytes *= -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
/* Look for NAXIS keyword */
|
|
|
|
if (buf[0] == 'N' &&
|
|
|
|
buf[1] == 'A' &&
|
|
|
|
buf[2] == 'X' && buf[3] == 'I' && buf[4] == 'S')
|
|
|
|
{
|
2022-08-06 21:03:09 -06:00
|
|
|
|
2022-08-06 22:20:48 -06:00
|
|
|
if (buf[5] == ' ')
|
|
|
|
{
|
|
|
|
/* NAXIS keyword */
|
|
|
|
read_val = qfits_getvalue (buf);
|
|
|
|
naxis = (int) atoi (read_val);
|
2022-08-06 21:03:09 -06:00
|
|
|
}
|
2022-08-06 22:20:48 -06:00
|
|
|
else
|
|
|
|
{
|
|
|
|
/* NAXIS?? keyword (axis size) */
|
|
|
|
read_val = qfits_getvalue (buf);
|
|
|
|
data_bytes *= (int) atoi (read_val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
/* Look for END keyword */
|
|
|
|
if (buf[0] == 'E' && buf[1] == 'N' && buf[2] == 'D')
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2022-08-06 21:03:09 -06:00
|
|
|
}
|
2022-08-06 22:20:48 -06:00
|
|
|
if (err != LGTH)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (xtnum < 0)
|
|
|
|
return 0;
|
2022-08-06 21:03:09 -06:00
|
|
|
|
2022-08-06 22:20:48 -06:00
|
|
|
n_xt = 0;
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Skip the previous data section if pixels were declared
|
|
|
|
*/
|
|
|
|
if (naxis > 0)
|
|
|
|
{
|
|
|
|
/* Skip as many blocks as there are declared pixels */
|
|
|
|
skip_blocks = data_bytes / BLOCK_SIZE;
|
|
|
|
if ((data_bytes % BLOCK_SIZE) != 0)
|
|
|
|
skip_blocks++;
|
|
|
|
seeked = fseek (in, skip_blocks * BLOCK_SIZE, SEEK_CUR);
|
|
|
|
if (seeked < 0)
|
|
|
|
return -1;
|
|
|
|
}
|
2022-08-06 21:03:09 -06:00
|
|
|
|
2022-08-06 22:20:48 -06:00
|
|
|
/* Look for next XTENSION keyword */
|
|
|
|
while ((err = fread (buf, sizeof (char), LGTH, in)) == LGTH)
|
|
|
|
{
|
|
|
|
if (buf[0] == 'X' &&
|
|
|
|
buf[1] == 'T' &&
|
|
|
|
buf[2] == 'E' &&
|
|
|
|
buf[3] == 'N' &&
|
|
|
|
buf[4] == 'S' &&
|
|
|
|
buf[5] == 'I' && buf[6] == 'O' && buf[7] == 'N')
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (err == 0)
|
|
|
|
break;
|
|
|
|
if (err != LGTH)
|
|
|
|
return 1;
|
2022-08-06 21:03:09 -06:00
|
|
|
|
2022-08-06 22:20:48 -06:00
|
|
|
n_xt++;
|
2022-08-06 21:03:09 -06:00
|
|
|
|
2022-08-06 22:20:48 -06:00
|
|
|
if (xtnum == 0 || xtnum == n_xt)
|
|
|
|
{
|
|
|
|
printf ("===> xtension %d\n", n_xt);
|
|
|
|
printf ("%s\n", rstrip (buf));
|
|
|
|
}
|
|
|
|
|
|
|
|
data_bytes = 1;
|
|
|
|
naxis = 0;
|
|
|
|
while ((err = fread (buf, sizeof (char), LGTH, in)) == LGTH)
|
|
|
|
{
|
|
|
|
if (xtnum == 0 || xtnum == n_xt)
|
|
|
|
printf ("%s\n", rstrip (buf));
|
2022-08-06 21:03:09 -06:00
|
|
|
|
2022-08-06 22:20:48 -06:00
|
|
|
/* Look for BITPIX keyword */
|
|
|
|
if (buf[0] == 'B' &&
|
|
|
|
buf[1] == 'I' &&
|
|
|
|
buf[2] == 'T' &&
|
|
|
|
buf[3] == 'P' &&
|
|
|
|
buf[4] == 'I' && buf[5] == 'X' && buf[6] == ' ')
|
|
|
|
{
|
|
|
|
read_val = qfits_getvalue (buf);
|
|
|
|
data_bytes *= (int) atoi (read_val) / 8;
|
|
|
|
if (data_bytes < 0)
|
|
|
|
data_bytes *= -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
/* Look for NAXIS keyword */
|
|
|
|
if (buf[0] == 'N' &&
|
|
|
|
buf[1] == 'A' &&
|
|
|
|
buf[2] == 'X' && buf[3] == 'I' && buf[4] == 'S')
|
|
|
|
{
|
2022-08-06 21:03:09 -06:00
|
|
|
|
2022-08-06 22:20:48 -06:00
|
|
|
if (buf[5] == ' ')
|
|
|
|
{
|
|
|
|
/* NAXIS keyword */
|
|
|
|
read_val = qfits_getvalue (buf);
|
|
|
|
naxis = (int) atoi (read_val);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* NAXIS?? keyword (axis size) */
|
|
|
|
read_val = qfits_getvalue (buf);
|
|
|
|
data_bytes *= (int) atoi (read_val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
/* Look for END keyword */
|
|
|
|
if (buf[0] == 'E' && buf[1] == 'N' && buf[2] == 'D')
|
|
|
|
break;
|
2022-08-06 21:03:09 -06:00
|
|
|
}
|
2022-08-06 22:20:48 -06:00
|
|
|
if (n_xt == xtnum)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return 0;
|
2022-08-06 21:03:09 -06:00
|
|
|
}
|