#ifndef lint static char SccsId[] = "%W% %G%"; #endif /* Module: imgcheck.c (Image Check) * Purpose: Check parameters for consistency and check image file size * Subroutine: check_image() returns: int * Xlib calls: none * Unix calls: stat() * Copyright: 1994-2001 Smithsonian Astrophysical Observatory * You may do anything you like with this file except remove * this copyright. The Smithsonian Astrophysical Observatory * makes no representations about the suitability of this * software for any purpose. It is provided "as is" without * express or implied warranty. * Modified: {0} Eric Mandel, M VanHilst initial version 9 January 1989 * {1} Doug Mink .fit and .fts are FITS, too 28 October 1994 * {2} Doug Mink ignore name after comma 9 October 1997 * {3} Doug Mink avoid using uninitialized ext 19 December 1997 * {4} Doug Mink check file type with isfits() 9 February 1999 * {5} Doug Mink drop multiwcs and mulspec flags 12 March 2001 * {n} -- -- */ #include /* stderr, NULL, etc. */ #include /* define sqrt */ #include #include /* define stat */ #ifndef VMS #ifdef SYSV #include #else #include /* strlen, etc. for unenlightened BSD's */ #endif #else #include #endif #include "hfiles/constant.h" /* define codes */ #include "hfiles/image.h" #include "hfiles/cmdparse.h" /* define parse status bits */ /* * Subroutine: check_image * Purpose: Do some consistency checks on image type and size * Returns: 0 if no errors found, else -1 */ int check_image ( img, got_status ) struct imageRec *img; int got_status; { int len; char *ext, *mwcs, cext; static int check_array(); extern int isfits(); ext = NULL; mwcs = NULL; if( (got_status & CMD_FTYPE) == 0 ) { if( img->filename != NULL ) { /* if no image type given, check name suffix or assume an array */ mwcs = strchr (img->filename, '%'); if (mwcs != NULL) *mwcs = 0; ext = strchr (img->filename, ','); if (ext == NULL) ext = strchr (img->filename, '['); if (ext != NULL) { cext = *ext; *ext = 0; } len = strlen(img->filename); if( strcmp(&img->filename[len - 5], ".fits") == 0 ) { img->file_type = SOP_FITS; } else if( strcmp(&img->filename[len - 5], ".FITS") == 0 ) { img->file_type = SOP_FITS; } else if( strcmp(&img->filename[len - 4], ".fit") == 0 ) { img->file_type = SOP_FITS; } else if( strcmp(&img->filename[len - 4], ".FIT") == 0 ) { img->file_type = SOP_FITS; } else if( strcmp(&img->filename[len - 4], ".fts") == 0 ) { img->file_type = SOP_FITS; } else if( strcmp(&img->filename[len - 4], ".FTS") == 0 ) { img->file_type = SOP_FITS; #ifdef OIF } else if( strcmp(&img->filename[len - 4], ".imh") == 0 ) { img->file_type = SOP_IRAF; #endif } else if (isfits (img->filename)) { img->file_type = SOP_FITS; } else img->file_type = SOP_Array; } else /* if no name, default */ img->file_type = SOP_Logo; } /* check for file existence and validity early on */ if ((img->file_type != SOP_Imtool) && (img->file_type != SOP_PROS) && (img->file_type != SOP_Logo) && (img->filename != NULL) ) { struct stat statbuf; if( stat(img->filename, &statbuf) <0 ) { if (ext != NULL) *ext = cext; if (mwcs != NULL) *mwcs = '%'; (void)fprintf(stderr, "Error: cannot access image: %s\n", img->filename); perror(img->filename); return( -1 ); } } /* for arrays, we can make some checks and some calculations */ if( img->file_type == SOP_Array ) { if( check_array(img) <0 ) { return( -1 ); } } /* conflicting zoom factors? */ if( img->fdblock == 0 ) { img->fdblock = img->fiblock; } else if( (img->fdblock < img->fiblock) && ((img->fdblock % img->fiblock) != 0) ) { (void)fprintf(stderr, "Error: incompatible display and buffer zooms\n"); return( -1 ); } /* if we are dealing with fits files on a little endian (vax), swap bytes */ #ifdef LSB /* Standard FITS images are fixed order (not in native order to VAX) */ if( img->file_type == SOP_FITS ) img->byte_swap = !img->byte_swap; #endif if (ext != NULL) *ext = cext; if (mwcs != NULL) *mwcs = '%'; return( 0 ); } /* * Subroutine: check_array * Purpose: Check array size vs file size etc * Returns: 0 if size determined and/or OK, else -1 */ static int check_array ( img ) struct imageRec *img; { long fsize; long arrsize; float posdim; /* possible dimension */ int headersize; /* size in bytes of header */ int rawsize; static long size_imagefile(); /* get header size */ headersize = img->headersize; /* get file size */ fsize = size_imagefile(img, headersize, &rawsize); /* we might be able to figure out the dimensions for a square */ if( (img->filerows == 0) || (img->filecols == 0) ) { /* if there is an image data type specified, try it */ if( img->storage_type != ARR_None ){ posdim = (int)sqrt((double)fsize); if( fsize == (posdim * posdim) ){ img->filecols = (int)posdim; img->filerows = (int)posdim; } else { (void)fprintf(stderr, "File size neither given nor square: %d (%d)\n", rawsize, fsize); return( -1 ); } } else { /* check 2, 4 byte data size */ /* check for I2 default */ fsize /= 2; posdim = (int)sqrt((double)fsize); if( fsize == (posdim * posdim) ){ img->storage_type = ARR_I2; } else { /* check for R4 default */ fsize /= 2; posdim = (int)sqrt((double)fsize); if( fsize == (posdim * posdim) ){ img->storage_type = ARR_R4; } else { (void)fprintf(stderr, "File size not square I2 or R4: %d (%d)\n", rawsize, rawsize - headersize); return( -1 ); } } img->filecols = posdim; img->filerows = posdim; } } else if( img->storage_type == ARR_None ) { /* get product of array dimensions in bytes */ arrsize = img->filecols * img->filerows; /* we might find pixel size for a default, if only rows&cols given */ if( fsize == arrsize ) { img->storage_type = ARR_U1; } else if( fsize == (arrsize*2) ) { img->storage_type = ARR_I2; } else if( fsize == (arrsize*4) ) { img->storage_type = ARR_R4; } else if( fsize == (arrsize*8) ) { img->storage_type = ARR_R8; } else { (void)fprintf(stderr, "File size does not scale to any type: %d (%d)\n", rawsize, rawsize - headersize); return( -1 ); } } else { /* in any case, image must not exceed file */ arrsize = img->filecols * img->filerows; if( arrsize > fsize ) { (void)fprintf(stderr, "Request (%d) exceeds file size: %d (%d)\n", arrsize, rawsize, fsize); return( -1 ); } } return( 0 ); } /* * Subroutine: size_imagefile * Purpose: return size of file adjusted for header and storage type */ static long size_imagefile ( img, headersize, rawsize ) struct imageRec *img; int headersize; /* given size of file header area */ int *rawsize; /* raw file size in bytes */ { struct stat buf; int fsize; /* get the file length in bytes */ (void)stat(img->filename, &buf); *rawsize = buf.st_size; /* computed the equivalent array size */ switch( img->storage_type ) { case ARR_R8: fsize = (*rawsize - headersize) / sizeof(double); break; case ARR_I4: case ARR_R4: fsize = (*rawsize - headersize) / sizeof(float); break; case ARR_U2: case ARR_I2: fsize = (*rawsize - headersize) / sizeof(short); break; case ARR_U1: default: fsize = *rawsize - headersize; break; } return( fsize ); }