/* readimage.c *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * * Part of: SExtractor * * Author: E.BERTIN (IAP) * * Contents: functions for input of image data. * * Last modify: 13/07/2006 * *%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include "wcs/wcs.h" #include "define.h" #include "globals.h" #include "prefs.h" #include "check.h" #include "field.h" #include "fits/fitscat.h" #include "interpolate.h" #include "back.h" #include "astrom.h" #include "weight.h" #include "wcs/tnx.h" /******************************* loadstrip ***********************************/ /* Load a new strip of pixel data into the buffer. */ void *loadstrip(picstruct *field, picstruct *wfield) { checkstruct *check; int y, w, flags, interpflag; PIXTYPE *data, *wdata, *rmsdata; w = field->width; flags = field->flags; interpflag = (wfield && wfield->interp_flag); wdata = NULL; /* To avoid gcc -Wall warnings */ if (!field->y) { /*- First strip */ int nbpix; nbpix = w*field->stripheight; if (flags ^ FLAG_FIELD) { /*---- Allocate space for the frame-buffer */ if (!(field->strip=(PIXTYPE *)malloc(field->stripheight*field->width *sizeof(PIXTYPE)))) error(EXIT_FAILURE,"Not enough memory for the image buffer of ", field->rfilename); data = field->strip; /*---- We assume weight data have been read just before */ if (interpflag) wdata = wfield->strip; if (flags & BACKRMS_FIELD) for (y=0, rmsdata=data; ystripheight; y++, rmsdata += w) backrmsline(field, y, rmsdata); else if (flags & INTERP_FIELD) copydata(field, 0, nbpix); else readdata(field, data, nbpix); if (flags & (WEIGHT_FIELD|RMS_FIELD|BACKRMS_FIELD|VAR_FIELD)) weight_to_var(field, data, nbpix); if ((flags & MEASURE_FIELD) && (check=prefs.check[CHECK_IDENTICAL])) writecheck(check, data, nbpix); for (y=0; ystripheight; y++, data += w) { /*------ This is the only place where one can pick-up safely the current bkg */ if (flags & (MEASURE_FIELD|DETECT_FIELD)) subbackline(field, y, data); /*------ Go to interpolation process */ if (interpflag) { interpolate(field,wfield, data, wdata); wdata += w; } /*------ Check-image stuff */ if (prefs.check_flag) { if (flags & MEASURE_FIELD) { if ((check = prefs.check[CHECK_BACKGROUND])) writecheck(check, field->backline, w); if ((check = prefs.check[CHECK_SUBTRACTED])) writecheck(check, data, w); if ((check = prefs.check[CHECK_APERTURES])) writecheck(check, data, w); if ((check = prefs.check[CHECK_SUBPSFPROTOS])) writecheck(check, data, w); if ((check = prefs.check[CHECK_SUBPCPROTOS])) writecheck(check, data, w); } if ((flags&DETECT_FIELD) && (check=prefs.check[CHECK_BACKRMS])) { backrmsline(field, y, (PIXTYPE *)check->pix); writecheck(check, check->pix, w); } } } } else { if (!(field->fstrip=(FLAGTYPE *)malloc(field->stripheight*field->width *sizeof(FLAGTYPE)))) error(EXIT_FAILURE,"Not enough memory for the flag buffer of ", field->rfilename); readidata(field, field->fstrip, nbpix); } field->ymax = field->stripheight; if (field->ymax < field->height) field->stripysclim = field->stripheight - field->stripmargin; } else { /*- other strips */ if (flags ^ FLAG_FIELD) { data = field->strip + field->stripylim*w; /*---- We assume weight data have been read just before */ if (interpflag) wdata = wfield->strip + field->stripylim*w; /*---- copy to Check-image the "oldest" line before it is replaced */ if ((flags & MEASURE_FIELD) && (check=prefs.check[CHECK_SUBOBJECTS])) writecheck(check, data, w); if (flags & BACKRMS_FIELD) backrmsline(field, field->ymax, data); else if (flags & INTERP_FIELD) copydata(field, field->stripylim*w, w); else readdata(field, data, w); if (flags & (WEIGHT_FIELD|RMS_FIELD|BACKRMS_FIELD|VAR_FIELD)) weight_to_var(field, data, w); if ((flags & MEASURE_FIELD) && (check=prefs.check[CHECK_IDENTICAL])) writecheck(check, data, w); /*---- Interpolate and subtract the background at current line */ if (flags & (MEASURE_FIELD|DETECT_FIELD)) subbackline(field, field->ymax, data); if (interpflag) interpolate(field,wfield, data, wdata); /*---- Check-image stuff */ if (prefs.check_flag) { if (flags & MEASURE_FIELD) { if ((check = prefs.check[CHECK_BACKGROUND])) writecheck(check, field->backline, w); if ((check = prefs.check[CHECK_SUBTRACTED])) writecheck(check, data, w); if ((check = prefs.check[CHECK_APERTURES])) writecheck(check, data, w); if ((check = prefs.check[CHECK_SUBPSFPROTOS])) writecheck(check, data, w); if ((check = prefs.check[CHECK_SUBPCPROTOS])) writecheck(check, data, w); } if ((flags&DETECT_FIELD) && (check=prefs.check[CHECK_BACKRMS])) { backrmsline(field, field->ymax, (PIXTYPE *)check->pix); writecheck(check, check->pix, w); } } } else readidata(field, field->fstrip + field->stripylim*w, w); field->stripylim = (++field->ymin)%field->stripheight; if ((++field->ymax)height) field->stripysclim = (++field->stripysclim)%field->stripheight; } return (flags ^ FLAG_FIELD)? (void *)(field->strip + field->stripy*w) : (void *)(field->fstrip + field->stripy*w); } /******************************** copydata **********************************/ /* Copy image data from one field to the other. */ void copydata(picstruct *field, int offset, int size) { memcpy(field->strip+offset, field->reffield->strip+offset, size*sizeof(PIXTYPE)); return; } /******************************** readdata **********************************/ /* read and convert input data stream in PIXTYPE (float) format. */ void readdata(picstruct *field, PIXTYPE *ptr, int size) { static char bufdata0[DATA_BUFSIZE]; char *bufdata; short val16; int i, bowl, spoonful, npix, curval, dval; PIXTYPE bs,bz; bs = (PIXTYPE)field->bscale; bz = (PIXTYPE)field->bzero; switch(field->compress_type) { /*-- Uncompressed image */ case ICOMPRESS_NONE: bowl = DATA_BUFSIZE/field->bytepix; spoonful = size0; size -= spoonful) { if (spoonful>size) spoonful = size; bufdata = bufdata0; QFREAD(bufdata, spoonful*field->bytepix, field->file,field->filename); switch(field->bitpix) { case BP_BYTE: if (field->bitsgn) for (i=spoonful; i--;) *(ptr++) = *(bufdata++)*bs + bz; else for (i=spoonful; i--;) *(ptr++) = *((unsigned char *)bufdata++)*bs + bz; break; case BP_SHORT: if (bswapflag) swapbytes(bufdata, 2, spoonful); if (field->bitsgn) for (i=spoonful; i--; bufdata += sizeof(short)) *(ptr++) = *((short *)bufdata)*bs + bz; else for (i=spoonful; i--; bufdata += sizeof(USHORT)) *(ptr++) = *((USHORT *)bufdata)*bs + bz; break; case BP_LONG: if (bswapflag) swapbytes(bufdata, 4, spoonful); if (field->bitsgn) for (i=spoonful; i--; bufdata += sizeof(LONG)) *(ptr++) = *((LONG *)bufdata)*bs + bz; else for (i=spoonful; i--; bufdata += sizeof(ULONG)) *(ptr++) = *((ULONG *)bufdata)*bs + bz; break; case BP_FLOAT: if (bswapflag) swapbytes(bufdata, 4, spoonful); for (i=spoonful; i--; bufdata += sizeof(float)) *(ptr++) = *((float *)bufdata)*bs + bz; break; case BP_DOUBLE: if (bswapflag) swapbytes(bufdata, 8, spoonful); for (i=spoonful; i--; bufdata += sizeof(double)) *(ptr++) = *((double *)bufdata)*bs + bz; break; default: error(EXIT_FAILURE,"*FATAL ERROR*: unknown BITPIX type in ", "readdata()"); break; } } break; /*-- Compressed image */ case ICOMPRESS_BASEBYTE: bufdata = field->compress_bufptr; curval = field->compress_curval; npix = field->compress_npix; while (size--) { if (!(npix--)) { if (curval != field->compress_checkval) error(EXIT_FAILURE, "*Error*: invalid BASEBYTE checksum in ", field->filename); bufdata = field->compress_buf; QFREAD(bufdata, FBSIZE, field->file, field->filename); curval = 0; if (bswapflag) swapbytes(bufdata, 4, 1); field->compress_checkval = *((int *)bufdata); bufdata += 4; if (bswapflag) swapbytes(bufdata, 2, 1); npix = (int)(*((short *)bufdata))-1; bufdata+=2; } if ((dval=(int)*(bufdata++))==-128) { if (bswapflag) swapbytes(bufdata, 2, 1); memcpy(&val16, bufdata, 2); dval = (int)val16; if (dval==-32768) { bufdata += 2; if (bswapflag) swapbytes(bufdata, 4, 1); memcpy(&dval,bufdata,4); bufdata += 4; } else bufdata += 2; } *(ptr++) = dval*bs + bz; curval += dval; } field->compress_curval = curval; field->compress_bufptr = bufdata; field->compress_npix = npix; break; case ICOMPRESS_PREVPIX: bufdata = field->compress_bufptr; curval = field->compress_curval; npix = field->compress_npix; while (size--) { if (!(npix--)) { if (curval != field->compress_checkval) error(EXIT_FAILURE, "*Error*: invalid PREV_PIX checksum in ", field->filename); bufdata = field->compress_buf; QFREAD(bufdata, FBSIZE, field->file, field->filename); if (bswapflag) swapbytes(bufdata, 2, 3); curval = (int)*(short *)bufdata; npix = (int)*(short *)(bufdata+=2)-1; field->compress_checkval = (int)(*(short *)(bufdata+=2)); bufdata+=4; } if ((dval=(int)*(bufdata++))==-128) { if (bswapflag) swapbytes(bufdata, 2, 1); memcpy(&val16, bufdata, 2); curval = (int)val16; bufdata += 2; } else curval += dval; *(ptr++) = curval*bs + bz; } field->compress_curval = curval; field->compress_bufptr = bufdata; field->compress_npix = npix; break; default: error(EXIT_FAILURE,"*Internal Error*: unknown compression mode in ", "readdata()"); } return; } /******************************** readidata *********************************/ /* read and convert input data stream in FLAGTYPE (unsigned int) format. */ void readidata(picstruct *field, FLAGTYPE *ptr, int size) { static char bufdata0[DATA_BUFSIZE]; char *bufdata; short val16; int i, bowl, spoonful, npix, curval, dval; switch(field->compress_type) { /*-- Uncompressed image */ case ICOMPRESS_NONE: bowl = DATA_BUFSIZE/field->bytepix; spoonful = size0; size -= spoonful) { if (spoonful>size) spoonful = size; bufdata = bufdata0; QFREAD(bufdata, spoonful*field->bytepix, field->file, field->filename); switch(field->bitpix) { case BP_BYTE: for (i=spoonful; i--;) *(ptr++) = (FLAGTYPE)*((unsigned char *)bufdata++); break; case BP_SHORT: if (bswapflag) swapbytes(bufdata, 2, spoonful); for (i=spoonful; i--; bufdata += sizeof(USHORT)) *(ptr++) = (FLAGTYPE)*((USHORT *)bufdata); break; case BP_LONG: if (bswapflag) swapbytes(bufdata, 4, spoonful); for (i=spoonful; i--; bufdata += sizeof(ULONG)) *(ptr++) = (FLAGTYPE)*((ULONG *)bufdata); break; case BP_FLOAT: case BP_DOUBLE: error(EXIT_FAILURE,"*Error*: I was expecting integers in ", field->filename); break; default: error(EXIT_FAILURE,"*FATAL ERROR*: unknown BITPIX type in ", "readdata()"); break; } } break; /*-- Compressed image */ case ICOMPRESS_BASEBYTE: bufdata = field->compress_bufptr; curval = field->compress_curval; npix = field->compress_npix; while (size--) { if (!(npix--)) { if (curval != field->compress_checkval) error(EXIT_FAILURE, "*Error*: invalid BASEBYTE checksum in ", field->filename); bufdata = field->compress_buf; QFREAD(bufdata, FBSIZE, field->file, field->filename); curval = 0; if (bswapflag) swapbytes(bufdata, 4, 1); field->compress_checkval = *((int *)bufdata); bufdata += 4; if (bswapflag) swapbytes(bufdata, 2, 1); npix = (int)(*((short *)bufdata))-1; bufdata+=2; } if ((dval=(int)*(bufdata++))==-128) { if (bswapflag) swapbytes(bufdata, 2, 1); memcpy(&val16, bufdata, 2); dval = (int)val16; if (dval==-32768) { bufdata += 2; if (bswapflag) swapbytes(bufdata, 4, 1); memcpy(&dval,bufdata,4); bufdata += 4; } else bufdata += 2; } *(ptr++) = (FLAGTYPE)dval; curval += dval; } field->compress_curval = curval; field->compress_bufptr = bufdata; field->compress_npix = npix; break; case ICOMPRESS_PREVPIX: bufdata = field->compress_bufptr; curval = field->compress_curval; npix = field->compress_npix; while (size--) { if (!(npix--)) { if (curval != field->compress_checkval) error(EXIT_FAILURE, "*Error*: invalid PREV_PIX checksum in ", field->filename); bufdata = field->compress_buf; QFREAD(bufdata, FBSIZE, field->file, field->filename); if (bswapflag) swapbytes(bufdata, 2, 3); curval = (int)*(short *)bufdata; npix = (int)*(short *)(bufdata+=2)-1; field->compress_checkval = (int)(*(short *)(bufdata+=2)); bufdata+=4; } if ((dval=(int)*(bufdata++))==-128) { if (bswapflag) swapbytes(bufdata, 2, 1); memcpy(&val16, bufdata, 2); curval = (int)val16; bufdata += 2; } else curval += dval; *(ptr++) = (FLAGTYPE)curval; } field->compress_curval = curval; field->compress_bufptr = bufdata; field->compress_npix = npix; break; default: error(EXIT_FAILURE,"*Internal Error*: unknown compression mode in ", "readdata()"); } return; } /******************************* readimagehead *******************************/ /* extract some data from the FITS-file header */ void readimagehead(picstruct *field) { int j,l, n; char wstr1[TNX_MAXCHARS], wstr2[TNX_MAXCHARS], st[80], str[80], *buf, *point; /* Open the file */ if (!(field->file = fopen(field->filename, "rb"))) error(EXIT_FAILURE,"*Error*: cannot open ", field->filename); /* Go directly to the right extension */ if (field->mefpos) { QFSEEK(field->file, field->mefpos, SEEK_SET, field->filename); } buf = readfitshead(field->file, field->filename, &n); if(FITSTOI("NAXIS ", 0) < 2) error(EXIT_FAILURE, field->filename, " does NOT contain 2D-data!"); /*---------------------------- Basic keywords ------------------------------*/ field->bitpix = FITSTOI("BITPIX ", 0); if (field->bitpix != BP_BYTE && field->bitpix != BP_SHORT && field->bitpix != BP_LONG && field->bitpix != BP_FLOAT && field->bitpix != BP_DOUBLE) error(EXIT_FAILURE, "Sorry, I don't know that kind of data.", ""); field->bytepix = (field->bitpix>0?field->bitpix:-field->bitpix)>>3; field->width = FITSTOI("NAXIS1 ", 0); field->height = FITSTOI("NAXIS2 ", 0); field->npix = (KINGSIZE_T)field->width*field->height; field->bscale = FITSTOF("BSCALE ", 1.0); field->bzero = FITSTOF("BZERO ", 0.0); field->bitsgn = FITSTOI("BITSGN ", 1); if (field->bitsgn && prefs.fitsunsigned_flag) field->bitsgn = 0; FITSTOS("OBJECT ", field->ident, "Unnamed"); /*----------------------------- Compression --------------------------------*/ if (fitsread(buf, "IMAGECOD", st, H_STRING, T_STRING)==RETURN_OK) { if (!strcmp(st, "NONE")) field->compress_type = ICOMPRESS_NONE; else if (!strcmp(st, "BASEBYTE")) field->compress_type = ICOMPRESS_BASEBYTE; else if (!strcmp(st, "PREV_PIX")) field->compress_type = ICOMPRESS_PREVPIX; else warning("Compression skipped: unknown IMAGECOD parameter:", st); } /*----------------------------- Astrometry ---------------------------------*/ /* Presently, astrometry is done only on the measurement and detect images */ if (field->flags&(MEASURE_FIELD|DETECT_FIELD)) { astromstruct *as; double drota, s; int naxis; QCALLOC(as, astromstruct, 1); field->astrom = as; naxis = as->naxis = 2; for (l=0; lctype[l], str, 8); sprintf(str, "CUNIT%-3d", l+1); FITSTOS(str, str, "deg"); strncpy(as->cunit[l], str, 32); sprintf(str, "CRVAL%-3d", l+1); as->crval[l] = FITSTOF(str, 0.0); sprintf(str, "CRPIX%-3d", l+1); as->crpix[l] = FITSTOF(str, 1.0); sprintf(str, "CDELT%-3d", l+1); as->cdelt[l] = FITSTOF(str, 1.0); if (fabs(as->cdelt[l]) < 1/BIG) error(EXIT_FAILURE, "*Error*: CDELT parameters out of range in ", field->filename); } if (fitsnfind(buf, "CD1_1", n)) { /*---- If CD keywords exist, use them for the linear mapping terms... */ for (l=0; lpc[l*naxis+j] = FITSTOF(str, l==j?1.0:0.0)/as->cdelt[l]; } } else if (fitsnfind(buf, "PC001001", n)) /*---- ...If PC keywords exist, use them for the linear mapping terms... */ for (l=0; lpc[l*naxis+j] = FITSTOF(str, l==j?1.0:0.0); } else { /*---- ...otherwise take the obsolete CROTA2 parameter */ s = as->cdelt[1]/as->cdelt[0]; drota = FITSTOF("CROTA2 ", 0.0); as->pc[3] = as->pc[0] = cos(drota*DEG); as->pc[1] = -(as->pc[2] = sin(drota*DEG)); as->pc[1] *= s; as->pc[2] /= s; } QMALLOC(as->wcs, struct wcsprm, 1); /*-- Test if the WCS is recognized and a celestial pair is found */ if (prefs.world_flag && !wcsset(as->naxis,(const char(*)[9])as->ctype, as->wcs) && as->wcs->flag<999) { char *pstr; double date; int biss, dpar[3]; as->wcs_flag = 1; /*---- Coordinate reference frame */ /*---- Search for an observation date expressed in Julian days */ date = FITSTOF("MJD-OBS ", -1.0); /*---- Precession date (defined from Ephemerides du Bureau des Longitudes) */ /*---- in Julian years from 2000.0 */ if (date>0.0) as->equinox = 2000.0 - (MJD2000 - date)/365.25; else { /*------ Search for an observation date expressed in "civil" format */ FITSTOS("DATE-OBS", str, ""); if (*str) { /*-------- Decode DATE-OBS format: DD/MM/YY or YYYY-MM-DD */ for (l=0; l<3 && (pstr = strtok(l?NULL:str,"/- ")); l++) dpar[l] = atoi(pstr); if (l<3 || !dpar[0] || !dpar[1] || !dpar[2]) { /*---------- If DATE-OBS value corrupted or incomplete, assume 2000-1-1 */ warning("Invalid DATE-OBS value in header: ", str); dpar[0] = 2000; dpar[1] = 1; dpar[2] = 1; } else if (strchr(str, '/') && dpar[0]<32 && dpar[2]<100) { j = dpar[0]; dpar[0] = dpar[2]+1900; dpar[2] = j; } biss = (dpar[0]%4)?0:1; /*-------- Convert date to MJD */ date = -678956 + (365*dpar[0]+dpar[0]/4) - biss + ((dpar[1]>2?((int)((dpar[1]+1)*30.6)-63+biss) :((dpar[1]-1)*(63+biss))/2) + dpar[2]); as->equinox = 2000.0 - (MJD2000 - date)/365.25; } else /*-------- Well if really no date is found */ as->equinox = 2000.0; } if (field->flags&MEASURE_FIELD) prefs.epoch = as->equinox; FITSTOS("RADECSYS", str, as->equinox<1984.0? "FK4": (as->equinox<1999.9999? "FK5" : "ICRS")); if (!strcmp(str, "ICRS")) { as->radecsys = RDSYS_ICRS; as->equinox = FITSTOF("EQUINOX ", 2000.0); } else if (!strcmp(str, "FK5")) { as->radecsys = RDSYS_FK5; as->equinox = FITSTOF("EQUINOX ", FITSTOF("EPOCH ", 2000.0)); if (field->flags&MEASURE_FIELD) sprintf(prefs.coosys, "eq_FK5"); } else if (!strcmp(str, "FK4")) { if (as->equinox == 2000.0) as->equinox = FITSTOF("EQUINOX ", FITSTOF("EPOCH ", 1950.0)); as->radecsys = RDSYS_FK4; warning("FK4 precession formulae not yet implemented:\n", " Astrometry may be slightly inaccurate"); } else if (!strcmp(str, "FK4-NO-E")) { if (as->equinox == 2000.0) as->equinox = FITSTOF("EQUINOX ", FITSTOF("EPOCH ", 1950.0)); as->radecsys = RDSYS_FK4_NO_E; warning("FK4 precession formulae not yet implemented:\n", " Astrometry may be slightly inaccurate"); } else if (!strcmp(str, "GAPPT")) { as->radecsys = RDSYS_GAPPT; warning("GAPPT reference frame not yet implemented:\n", " Astrometry may be slightly inaccurate"); } else { warning("Using ICRS instead of unknown astrometric reference frame: ", str); as->radecsys = RDSYS_ICRS; as->equinox = FITSTOF("EQUINOX ", 2000.0); } /*---- Projection parameters */ if (!strcmp(as->wcs->pcode, "TNX")) { /*---- IRAF's TNX projection: decode these #$!?@#!! WAT parameters */ if (fitsfind(buf, "WAT?????") != RETURN_ERROR) { /*-------- First we need to concatenate strings */ pstr = wstr1; sprintf(str, "WAT1_001"); for (j=2; fitsread(buf,str,pstr,H_STRINGS,T_STRING)==RETURN_OK; j++) { sprintf(str, "WAT1_%03d", j); pstr += strlen(pstr); } pstr = wstr2; sprintf(str, "WAT2_001"); for (j=2; fitsread(buf,str,pstr,H_STRINGS,T_STRING)==RETURN_OK; j++) { sprintf(str, "WAT2_%03d", j); pstr += strlen(pstr); } /*-------- LONGPOLE defaulted to 180 deg if not found */ if ((pstr = strstr(wstr1, "longpole")) || (pstr = strstr(wstr2, "longpole"))) pstr = strpbrk(pstr, "1234567890-+."); as->longpole = pstr? atof(pstr) : 999.0; as->latpole = 999.0; /*-------- RO defaulted to 180/PI if not found */ if ((pstr = strstr(wstr1, "ro")) || (pstr = strstr(wstr2, "ro"))) pstr = strpbrk(pstr, "1234567890-+."); as->r0 = pstr? atof(pstr) : 0.0; /*-------- Read the remaining TNX parameters */ if ((pstr = strstr(wstr1, "lngcor")) || (pstr = strstr(wstr2, "lngcor"))) as->tnx_lngcor = read_tnxaxis(pstr); if (!as->tnx_lngcor) error(EXIT_FAILURE, "*Error*: incorrect TNX parameters in ", field->filename); if ((pstr = strstr(wstr1, "latcor")) || (pstr = strstr(wstr2, "latcor"))) as->tnx_latcor = read_tnxaxis(pstr); if (!as->tnx_latcor) error(EXIT_FAILURE, "*Error*: incorrect TNX parameters in ", field->filename); } } else { as->longpole = FITSTOF("LONGPOLE", 999.0); as->latpole = FITSTOF("LATPOLE ", 999.0); if (fitsnfind(buf, "PROJP1 ", n)) for (l=0; l<10; l++) { sprintf(str, "PROJP%-3d", l); as->projp[l] = FITSTOF(str, 0.0); } } } else { /*---- No need to keep memory allocated for a useless WCS structure */ free(as->wcs); as->wcs_flag = 0; } } /*---------------------------------------------------------------------------*/ field->fitshead = buf; field->fitsheadsize = n*FBSIZE; return; } /******************************* readfitshead ********************************/ /* read data from the FITS-file header */ char *readfitshead(FILE *file, char *filename, int *nblock) { int n; char *buf; if (!(buf=(char *)malloc((size_t)FBSIZE))) error(EXIT_FAILURE, "*Error*: Not enough memory in ", "readfitshead()"); /* Find the number of FITS blocks of the header while reading it */ QFREAD(buf, FBSIZE, file, filename); if (strncmp(buf, "SIMPLE ", 8)) { /* Ugly but necessary patch to handle this stupid DeNIS compressed format! */ if (strncmp(buf, "XTENSION", 8)) error(EXIT_FAILURE, filename, " is NOT a FITS file!"); /* else { memset(buf, ' ', 80); strncpy(buf, "SIMPLE = T / Decompressed by SExtractor", 59); } */ } for (n=1; !fitsnfind(buf,"END ", n); n++) { if (!(buf=(char *)realloc(buf, (size_t)(FBSIZE*(n+1))))) error(EXIT_FAILURE, "*Error*: Not enough memory in ", "readfitshead()"); QFREAD(buf+n*FBSIZE, FBSIZE, file, filename); } *nblock = n; return buf; }