1
0
Fork 0
sattools/qfits/saft/stripfits.c

368 lines
9.5 KiB
C

/*----------------------------------------------------------------------------*/
/**
@file stripfits.c
@author N. Devillard
@date January 1999
@version $Revision: 1.2 $
@brief Dumps all the pixels from a FITS header into another file.
This is a stand-alone tool, compile it with:
gcc -o stripfits stripfits.c -O
This program dumps all the pixels from a FITS header into another file.
It has been written in less than 10 minutes (reusing most of the code
from iofits.c) to help the guys working on the ISAAC detector that day.
Since it is a good example of how to write a stand-alone FITS command, I
leave it here in the distribution.
*/
/*----------------------------------------------------------------------------*/
/*
$Id: stripfits.c,v 1.2 2002/11/21 14:18:18 yjung Exp $
$Author: yjung $
$Date: 2002/11/21 14:18:18 $
$Revision: 1.2 $
*/
/*-----------------------------------------------------------------------------
Include
-----------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <string.h>
#include <ctype.h>
/*-----------------------------------------------------------------------------
Define
-----------------------------------------------------------------------------*/
#define NM_SIZ 512
#define FITS_BLSZ 2880
#define ONE_MEGABYTE (1024 * 1024)
#ifndef SEEK_SET
#define SEEK_SET 0
#endif
/*-----------------------------------------------------------------------------
Function prototypes
-----------------------------------------------------------------------------*/
static int dump_pix (char *, char *);
static int get_FITS_header_size (char *);
static int filesize (char *);
static int get_bitpix (char *);
static int get_npix (char *);
/*-----------------------------------------------------------------------------
Main
-----------------------------------------------------------------------------*/
int
main (int argc, char *argv[])
{
if (argc < 3)
{
printf ("\n\n");
printf ("use: %s <in> <out>\n", argv[0]);
printf ("\n");
printf ("\t<in> is a valid FITS file in the current directory\n");
printf ("\t<out> is the name of the output file\n");
printf ("\n\n");
return 0;
}
if (!strcmp (argv[1], argv[2]))
{
fprintf (stderr, "cannot convert a file to itself\n");
fprintf (stderr, "specify another name for the output\n");
return -1;
}
return dump_pix (argv[1], argv[2]);
}
/*----------------------------------------------------------------------------*/
/**
@brief dump pixels from a FITS file to a binary file
@param name_in Input file name
@param name_out Output file name
@return int 0 if Ok, anything else otherwise
Heavy use of mmap() to speed up the process
*/
/*----------------------------------------------------------------------------*/
static int
dump_pix (char *name_in, char *name_out)
{
int fd_in, fd_out;
char *buf_in;
char *buf_out;
int fsize_in, fsize_out, header_size;
int npix;
/*
* Open input file and get information we need:
* - pixel depth
* - number of pixels
*/
fsize_in = filesize (name_in);
header_size = get_FITS_header_size (name_in);
if ((fd_in = open (name_in, O_RDONLY)) == -1)
{
fprintf (stderr, "cannot open file %s: aborting\n", name_in);
return -1;
}
buf_in = (char *) mmap (0, fsize_in, PROT_READ, MAP_SHARED, fd_in, 0);
if (buf_in == (char *) -1)
{
perror ("mmap");
fprintf (stderr, "cannot mmap file: %s\n", name_in);
close (fd_in);
return -1;
}
if (get_bitpix (buf_in) != -32)
{
fprintf (stderr, "only 32-bit IEEE floating point format supported\n");
close (fd_in);
munmap (buf_in, fsize_in);
return -1;
}
/*
* Compute the size of the output file
* same header size, + pixel area + blank padding
*/
npix = get_npix (buf_in);
if (npix < 1)
{
fprintf (stderr, "cannot compute number of pixels\n");
close (fd_in);
munmap (buf_in, fsize_in);
return -1;
}
fsize_out = npix * 4;
/*
* Now create the output file and fill it with zeros, then mmap it.
* The permissions are rw-rw-r-- by default.
*/
if ((fd_out =
creat (name_out,
S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH)) == -1)
{
perror ("creat");
fprintf (stderr, "cannot create file %s: aborting\n", name_out);
close (fd_in);
munmap (buf_in, fsize_in);
return -1;
}
buf_out = malloc (fsize_out);
if (buf_out == NULL)
{
fprintf (stderr, "not enough memory\n");
fprintf (stderr, "failed to allocate %d bytes\n", fsize_out);
close (fd_in);
munmap (buf_in, fsize_in);
return -1;
}
write (fd_out, buf_out, fsize_out);
close (fd_out);
free (buf_out);
fd_out = open (name_out, O_RDWR);
if (fd_out == -1)
{
fprintf (stderr, "error opening file %s\n", name_out);
close (fd_in);
munmap (buf_in, fsize_in);
return -1;
}
buf_out = (char *) mmap (0,
fsize_out,
PROT_READ | PROT_WRITE, MAP_SHARED, fd_out, 0);
if (buf_out == (char *) -1)
{
perror ("mmap");
fprintf (stderr, "cannot mmap file: %s\n", name_out);
munmap (buf_in, fsize_in);
close (fd_in);
close (fd_out);
return -1;
}
/*
* Copy FITS header from input to output, modify BITPIX
*/
memcpy (buf_out, buf_in + header_size, fsize_out);
/*
* Close, unmap, goodbye
*/
close (fd_in);
close (fd_out);
munmap (buf_in, fsize_in);
munmap (buf_out, fsize_out);
return 0;
}
/*----------------------------------------------------------------------------*/
/**
@brief compute the size (in bytes) of a FITS header
@param name FITS file name
@return unsigned long
Should always be a multiple of 2880. This implementation assumes only that
80 characters are found per line.
*/
/*----------------------------------------------------------------------------*/
static int
get_FITS_header_size (char *name)
{
FILE *in;
char line[81];
int found = 0;
int count;
int hs;
if ((in = fopen (name, "r")) == NULL)
{
fprintf (stderr, "cannot open %s: aborting\n", name);
return 0;
}
count = 0;
while (!found)
{
if (fread (line, 1, 80, in) != 80)
{
break;
}
count++;
if (!strncmp (line, "END ", 4))
{
found = 1;
}
}
fclose (in);
if (!found)
return 0;
/*
* The size is the number of found cards times 80,
* rounded to the closest higher multiple of 2880.
*/
hs = count * 80;
if ((hs % FITS_BLSZ) != 0)
{
hs = (1 + (hs / FITS_BLSZ)) * FITS_BLSZ;
}
return hs;
}
/*----------------------------------------------------------------------------*/
/**
@brief how many bytes can I read from this file
@param filename File name
@return size of the file in bytes
Strongly non portable. Only on Unix systems!
*/
/*----------------------------------------------------------------------------*/
static int
filesize (char *filename)
{
int size;
struct stat fileinfo;
/* POSIX compliant */
if (stat (filename, &fileinfo) != 0)
{
size = (int) 0;
}
else
{
size = (int) fileinfo.st_size;
}
return size;
}
/*----------------------------------------------------------------------------*/
/**
@brief gets the value of BITPIX from a FITS header
@param buf allocated char buffer containing the whole FITS header
@return int 8 16 32 -32 or -64 or 0 if cannot find it
*/
/*----------------------------------------------------------------------------*/
static int
get_bitpix (char *buf)
{
int bitpix;
char *where;
where = strstr (buf, "BITPIX");
if (where == NULL)
{
fprintf (stderr, "cannot find BITPIX in header: aborting\n");
return 0;
}
sscanf (where, "%*[^=] = %d", &bitpix);
/*
* Check the returned value makes sense
*/
if ((bitpix != 8) &&
(bitpix != 16) && (bitpix != 32) && (bitpix != -32) && (bitpix != -64))
{
bitpix = 0;
}
return bitpix;
}
/*----------------------------------------------------------------------------*/
/**
@brief retrieves how many pixels in a FITS file from the header
@param buf allocated char buffer containing the whole FITS header
@return unsigned long: # of pixels in the file
Does not support extensions!
*/
/*----------------------------------------------------------------------------*/
static int
get_npix (char *buf)
{
int naxes;
int npix;
int naxis;
char *where;
char lookfor[80];
int i;
where = strstr (buf, "NAXIS");
if (where == NULL)
{
fprintf (stderr, "cannot find NAXIS in header: aborting\n");
return 0;
}
sscanf (where, "%*[^=] = %d", &naxes);
if ((naxes < 1) || (naxes > 999))
{
fprintf (stderr, "illegal value for %s: %d\n", lookfor, naxes);
return 0;
}
npix = 1;
for (i = 1; i <= naxes; i++)
{
sprintf (lookfor, "NAXIS%d", i);
where = strstr (buf, lookfor);
if (where == NULL)
{
fprintf (stderr, "cannot find %s in header: aborting\n", lookfor);
return 0;
}
sscanf (where, "%*[^=] = %d", &naxis);
if (naxis < 1)
{
fprintf (stderr, "error: found %s=%d\n", lookfor, naxis);
return 0;
}
npix *= (int) naxis;
}
return npix;
}