368 lines
9.5 KiB
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;
|
|
}
|