// getImageToArray: extract a sub-section from an image HDU, return array void *getImageToArray(fitsfile *fptr, int *dims, double *cens, int *odim1, int *odim2, int *bitpix, int *status){ int naxis=IDIM; int xcen, ycen, dim1, dim2, type; void *obuf; long totpix, totbytes; long naxes[IDIM], fpixel[IDIM], lpixel[IDIM], inc[IDIM]={1,1}; // get image dimensions and type fits_get_img_dim(fptr, &naxis, status); fits_get_img_size(fptr, IDIM, naxes, status); fits_get_img_type(fptr, bitpix, status); // get limits of extracted section if( dims && dims[0] && dims[1] ){ dim1 = min(dims[0], naxes[0]); dim2 = min(dims[1], naxes[1]); // read image section if( cens ){ xcen = cens[0]; ycen = cens[1]; } else { xcen = dim1/2; ycen = dim2/2; } fpixel[0] = (int)(xcen - ((dim1+1)/2) + 1); fpixel[1] = (int)(ycen - ((dim2+1)/2) + 1); lpixel[0] = (int)(xcen + (dim1/2)); lpixel[1] = (int)(ycen + (dim2/2)); } else { // read entire image fpixel[0] = 1; fpixel[1] = 1; lpixel[0] = naxes[0]; lpixel[1] = naxes[1]; } if( fpixel[0] < 1 ){ fpixel[0] = 1; } if( fpixel[0] > naxes[0] ){ fpixel[0] = naxes[0]; } if( fpixel[1] < 1 ){ fpixel[1] = 1; } if( fpixel[1] > naxes[1] ){ fpixel[1] = naxes[1]; } // section dimensions *odim1 = lpixel[0] - fpixel[0] + 1; *odim2 = lpixel[1] - fpixel[1] + 1; totpix = *odim1 * *odim2; // allocate space for the pixel array switch(*bitpix){ case 8: type = TBYTE; totbytes = totpix * sizeof(char); break; case 16: type = TSHORT; totbytes = totpix * sizeof(short); break; case -16: type = TUSHORT; totbytes = totpix * sizeof(unsigned short); break; case 32: type = TINT; totbytes = totpix * sizeof(int); break; case 64: type = TLONGLONG; totbytes = totpix * sizeof(long long); break; case -32: type = TFLOAT; totbytes = totpix * sizeof(float); break; case -64: type = TDOUBLE; totbytes = totpix * sizeof(double); break; default: return NULL; } // sanity check on memory limits if( totbytes > max_memory ){ return NULL; } // try to allocate that much memory if(!(obuf = (void *)malloc(totbytes))){ return NULL; } /* read the image section */ fits_read_subset(fptr, type, fpixel, lpixel, inc, 0, obuf, 0, status); // return pixel buffer (and section dimensions) return obuf; }
static int fits2vips_generate( VipsRegion *out, void *seq, void *a, void *b, gboolean *stop ) { VipsFits *fits = (VipsFits *) a; Rect *r = &out->valid; VipsPel *q; int z; int status; long fpixel[MAX_DIMENSIONS]; long lpixel[MAX_DIMENSIONS]; long inc[MAX_DIMENSIONS]; status = 0; VIPS_DEBUG_MSG( "fits2vips_generate: " "generating left = %d, top = %d, width = %d, height = %d\n", r->left, r->top, r->width, r->height ); /* Special case: the region we are writing to is exactly the width we * need, ie. we can read a rectangular area into it. */ if( VIPS_REGION_LSKIP( out ) == VIPS_REGION_SIZEOF_LINE( out ) ) { VIPS_DEBUG_MSG( "fits2vips_generate: block read\n" ); for( z = 0; z < MAX_DIMENSIONS; z++ ) fpixel[z] = 1; fpixel[0] = r->left + 1; fpixel[1] = r->top + 1; fpixel[2] = fits->band_select + 1; for( z = 0; z < MAX_DIMENSIONS; z++ ) lpixel[z] = 1; lpixel[0] = VIPS_RECT_RIGHT( r ); lpixel[1] = VIPS_RECT_BOTTOM( r ); lpixel[2] = fits->band_select + 1; for( z = 0; z < MAX_DIMENSIONS; z++ ) inc[z] = 1; q = VIPS_REGION_ADDR( out, r->left, r->top ); /* Break on ffgsv() for this call. */ g_mutex_lock( fits->lock ); if( fits_read_subset( fits->fptr, fits->datatype, fpixel, lpixel, inc, NULL, q, NULL, &status ) ) { vips_fits_error( status ); g_mutex_unlock( fits->lock ); return( -1 ); } g_mutex_unlock( fits->lock ); } else { int y; for( y = r->top; y < VIPS_RECT_BOTTOM( r ); y ++ ) { for( z = 0; z < MAX_DIMENSIONS; z++ ) fpixel[z] = 1; fpixel[0] = r->left + 1; fpixel[1] = y + 1; fpixel[2] = fits->band_select + 1; for( z = 0; z < MAX_DIMENSIONS; z++ ) lpixel[z] = 1; lpixel[0] = VIPS_RECT_RIGHT( r ); lpixel[1] = y + 1; lpixel[2] = fits->band_select + 1; for( z = 0; z < MAX_DIMENSIONS; z++ ) inc[z] = 1; q = VIPS_REGION_ADDR( out, r->left, y ); /* Break on ffgsv() for this call. */ g_mutex_lock( fits->lock ); if( fits_read_subset( fits->fptr, fits->datatype, fpixel, lpixel, inc, NULL, q, NULL, &status ) ) { vips_fits_error( status ); g_mutex_unlock( fits->lock ); return( -1 ); } g_mutex_unlock( fits->lock ); } } return( 0 ); }
int main(int argc, char *argv[]) { char opt, *framename, *listname, *outname, *e_outname, buffer[BUFSIZ]; int n, row, col, cX, cY, npatch, npxi, npxt, nprof; int flag_autoname, flag_verbose, status, bitmask[YAR][XAR]; long xsize, ysize, lowleft[DIM], upright[DIM], increment[DIM] = {1L, 1L}, framesize[DIM]; float mask_val, cutoff, framefragment[YAR][XAR]; struct star* patchstars; FILE *listfile; fitsfile *frame, *maskedframe; extern char *optarg; extern int opterr; framename = NULL; listname = NULL; outname = NULL; mask_val = DEFAULT_MASK; cutoff = DEFAULT_CUTOFF; flag_autoname = 1; flag_verbose = 0; opterr = 0; while ((opt=getopt(argc, argv, "f:l:o:m:c:v")) != -1) { switch (opt) { case 'f': framename = optarg; break; case 'l': listname = optarg; break; case 'o': flag_autoname = 0; outname = optarg; break; case 'm': mask_val = atof(optarg); break; case 'c': cutoff = atof(optarg); break; case 'v': flag_verbose = 1; break; default: usage(argv); } } /* check mandatory parameters: */ if (framename == NULL || listname == NULL) usage(argv); if (cutoff < 0.0) { fprintf(stderr, " WARNING: invalid cut-off value (%.1f ADU), using default (%.1f ADU)\n", cutoff, DEFAULT_CUTOFF); cutoff = DEFAULT_CUTOFF; } /* read ID and coordinates from any single-lined Daophot output, detect and skip the header if necessary: */ if ((listfile=fopen(listname, "r")) == NULL) { file_read_error(listname); } else { npatch = line_count(listfile); if (has_daophot_header(listfile) == 1) { npatch -= DAO_HEADER_SIZE; line_skip(listfile, DAO_HEADER_SIZE); } if (npatch <= 0) { fclose(listfile); fprintf(stderr, " couldn't read contents of '%s', exiting.\n\n", listname); exit(EXIT_FAILURE); } patchstars = calloc(npatch, sizeof(struct star)); if (patchstars == NULL) { fclose(listfile); memory_error(); } for (n=0; n < npatch; n++) { fgets(buffer, BUFSIZ, listfile); sscanf(buffer, "%d %lf %lf", &patchstars[n].num, &patchstars[n].X, &patchstars[n].Y); } fclose(listfile); } status = 0; fits_open_file(&frame, framename, READONLY, &status); if (status != 0) { free(patchstars); file_read_error(framename); } fits_get_img_size(frame, DIM, framesize, &status); fits_print_error(status); xsize = framesize[0]; ysize = framesize[1]; printf(" %s: %ld x %ld pixels\n", framename, xsize, ysize); printf(" %s: %d stars in the list\n", listname, npatch); printf(" mask value: %.1f ADU\n", mask_val); printf(" cut-off level: %.1f ADU\n", cutoff); if (flag_autoname == 1) { outname = expand_filename(framename, "-msk", 0, 0); if (outname == NULL) { free(patchstars); fits_close_file(frame, &status); memory_error(); } } printf(" output file: %s\n", outname); /* force cfitsio to overwrite already existing file (prepend ! to the filename) */ e_outname = prepend_bang(outname); if (e_outname == NULL) { free(patchstars); fits_close_file(frame, &status); memory_error(); } /* create output (masked) frame: */ fits_create_file(&maskedframe, e_outname, &status); fits_print_error(status); free(e_outname); if (flag_autoname == 1) /* only necessary if outname was created automatically */ free(outname); fits_copy_file(frame, maskedframe, 1, 1, 1, &status); fits_print_error(status); npxt = 0; nprof = 0; /* process the stars in the list: */ for (n=0; n < npatch; n++) { if (flag_verbose == 1) printf("\n star #%d:\n", patchstars[n].num); /* cfitsio doesn't understand fractional pixels, round the coordinates to nearest integer: */ cX = rint(patchstars[n].X); cY = rint(patchstars[n].Y); /* make sure center is in the picture, skip this star if it is not: */ if (cX < 1 || cY < 1 || cX > xsize || cY > ysize) { printf(" star #%d is outside the frame (%d,%d), skipping.\n", patchstars[n].num, cX, cY); continue; } /* * in fitsio pixel index runs from 1 to N, not from 0 to N-1. * consider XAR=21 (reading 10 pixels right and left from center), XSIZE=2044. * example 1: star with x=10. fitsio will reach and try to read pixel at x=0, ILLEGAL. * example 2: star with x=2034. fitsio will reach and try to read pixel at x=2044, LEGAL. * we have to use LESS OR EQUAL when checking lower and left boundary, * for upper and right boundary only using GREATER is fine */ else if (cX <= (XAR-1)/2 || cY <= (YAR-1)/2 || cX > xsize-(XAR-1)/2 || cY > ysize-(YAR-1)/2) { printf(" star #%d is too close to the edge or partially outside the frame (%d,%d), skipping.\n", patchstars[n].num, cX, cY); continue; } if (flag_verbose == 1) printf(" coordinates of star #%d center in current frame: (%d,%d)\n", patchstars[n].num, cX, cY); /* compute the coordinates of lower left and upper right pixel: */ lowleft[0] = cX - (XAR-1)/2; lowleft[1] = cY - (YAR-1)/2; upright[0] = cX + (XAR-1)/2; upright[1] = cY + (YAR-1)/2; /* load frame fragment with the star into table: */ fits_read_subset(frame, TFLOAT, lowleft, upright, increment, 0, framefragment, 0, &status); fits_print_error(status); /* initialise the bitmask with zeros: */ for (row=0; row < YAR; row++) for (col=0; col < XAR; col++) bitmask[row][col] = 0; /* detect holes and write to bitmask: */ for (row=YAR-1; row >= 0; row--) examine_row(framefragment, bitmask, row, cutoff); for (col=0; col < XAR; col++) examine_col(framefragment, bitmask, col, cutoff); npxi = apply_bitmask(framefragment, bitmask, mask_val); npxt += npxi; if (npxi > 0) ++nprof; if (flag_verbose == 1) { printf("\n"); print_bitmask(bitmask); printf("\n star %d: %d pixels masked\n", patchstars[n].num, npxi); } /* write the modified frame subsection to output frame: */ fits_write_subset(maskedframe, TFLOAT, lowleft, upright, framefragment, &status); fits_print_error(status); } printf(" %d pixels were masked in %d stars.\n", npxt, nprof); fits_close_file(frame, &status); fits_print_error(status); fits_close_file(maskedframe, &status); fits_print_error(status); free(patchstars); return 0; }
void readFITS(const std::string& fitsname, cv::Mat& cvImage) { fitsfile *fptr = nullptr; int status(0); char err_text[100]; //READONLY, READWRITE fits_open_file(&fptr, fitsname.c_str(), READONLY, &status); if (status) { fits_report_error(stdout, status); fits_get_errstatus(status,err_text); fptr = nullptr; std::cout << "readFITS: Unable to open the fits file." << std::endl; throw CustomException("readFITS: Unable to open the fits file."); } //turn off scaling so we read the raw pixel value double bscale_ = 1.0, bzero_ = 0.0; fits_set_bscale(fptr, bscale_, bzero_, &status); int bitpix, naxis; int maxdim(3); long naxes[] = {1,1, 1}; fits_get_img_param(fptr, maxdim, &bitpix, &naxis, naxes, &status); if (status) { fits_report_error(stdout, status); fits_get_errstatus(status,err_text); fptr = nullptr; std::cout << "readFITS: Unable to get params from FITS." << std::endl; throw CustomException("readFITS: Unable to get params from FITS."); } if(naxis == 2) { // TBYTE, TSBYTE, TSHORT, TUSHORT, TINT, TUINT, TLONG, TLONGLONG, TULONG, TFLOAT, TDOUBLE long fpixel[] = {1, 1}; long lpixel[] = {naxes[0], naxes[1]}; long inc[] = {1, 1}; long nelements = naxes[0] * naxes[1]; double *array = new double[nelements]; fits_read_subset(fptr, TDOUBLE, fpixel, lpixel, inc, nullptr, array, nullptr, &status); if (status) { fits_report_error(stdout, status); fits_get_errstatus(status,err_text); fptr = nullptr; delete[] array; throw CustomException("readFITS: Unable to read the fits file."); } //it seems cfitsio interprets image axes in the oppsite way of opencv cvImage = cv::Mat(naxes[1], naxes[0], cv::DataType<double>::type, array); fits_close_file(fptr, &status); if (status) { fits_report_error(stdout, status); fits_get_errstatus(status,err_text); fptr = nullptr; delete[] array; throw CustomException("readFITS: Cannot close fits file."); } } if(naxis == 3) { // TBYTE, TSBYTE, TSHORT, TUSHORT, TINT, TUINT, TLONG, TLONGLONG, TULONG, TFLOAT, TDOUBLE long layer = 29; //Only consider the first layer long fpixel[] = {1, 1, layer}; long lpixel[] = {naxes[0], naxes[1], layer}; long inc[] = {1, 1, 1}; long nelements = naxes[0] * naxes[1]; double *array = new double[nelements]; fits_read_subset(fptr, TDOUBLE, fpixel, lpixel, inc, nullptr, array, nullptr, &status); if (status) { fits_report_error(stdout, status); fits_get_errstatus(status,err_text); fptr = nullptr; delete[] array; throw CustomException("readFITS: Unable to read the fits file."); } //it seems cfitsio interprets image axes in the oppsite way of opencv cvImage = cv::Mat(naxes[1], naxes[0], cv::DataType<double>::type, array); fits_close_file(fptr, &status); if (status) { fits_report_error(stdout, status); fits_get_errstatus(status,err_text); fptr = nullptr; delete[] array; throw CustomException("readFITS: Cannot close fits file."); } } }
std::string read_image_3D(std::string pathname_3D, float *&array_2D_real, float *&array_2D_imag, int &naxis_2D, long *&naxes_2D) { TRACE_ENTER(); // open FITS image file in READONLY mode fitsfile *fptr; int status = 0; fits_open_image(&fptr, pathname_3D.c_str(), READONLY, &status); if (status != 0) { return FORMAT_STATUS(status); } // read number of HDUs in the file int nhdus = 0; fits_get_num_hdus(fptr, &nhdus, &status); if (status != 0) { return FORMAT_STATUS(status); } // we expect only one HDU in the file if (nhdus != 1) { std::ostringstream exit_oss; exit_oss << "nhdus is " << nhdus << ", not 1"; TRACE_ERROR(exit_oss.str()); return exit_oss.str(); } // read the type of the HDU int hdutype = 0; fits_movabs_hdu(fptr, nhdus, &hdutype, &status); if (status != 0) { return FORMAT_STATUS(status); } // we expect the HDU to be an image if (hdutype != IMAGE_HDU) { std::ostringstream exit_oss; exit_oss << "hdutype is " << hdutype << ", not IMAGE_HDU"; TRACE_ERROR(exit_oss.str()); return exit_oss.str(); } // read the type of data in the HDU int bitpix = 0; fits_get_img_type (fptr, &bitpix, &status); if (status != 0) { return FORMAT_STATUS(status); } // we expect the data to be floats if (bitpix != FLOAT_IMG) { std::ostringstream exit_oss; exit_oss << "bitpix is " << bitpix << ", not FLOAT_IMG"; TRACE_ERROR(exit_oss.str()); return exit_oss.str(); } // get the number of dimensions in the image int naxis_3D = 0; fits_get_img_dim (fptr, &naxis_3D, &status); if (status != 0) { return FORMAT_STATUS(status); } naxis_2D = naxis_3D-1; // we expect 3 dimensions in the image if (naxis_3D != 3) { std::ostringstream exit_oss; exit_oss << "naxis_3D is " << naxis_3D << ", not 3"; TRACE_ERROR(exit_oss.str()); return exit_oss.str(); } // get the size of each dimension in the image long *naxes_3D = new long[naxis_3D]; int maxdim = naxis_3D; fits_get_img_size(fptr, maxdim, naxes_3D, &status); if (status != 0) { return FORMAT_STATUS(status); } naxes_2D = new long[naxis_2D]; for (int i = 0; i < naxis_2D; i++) { naxes_2D[i] = naxes_3D[i]; } // we expect two sub-images in the third dimension if (naxes_3D[2] != 2) { std::ostringstream exit_oss; exit_oss << "naxes_2D[2] is " << naxes_2D[2] << ", not 2"; TRACE_ERROR (exit_oss.str()); return exit_oss.str(); } // fits_read_subset long *fpixel = new long[naxis_3D]; for (int i = 0; i < naxis_3D; i++) { fpixel[i] = 1; } long *lpixel = new long[naxis_3D]; for (int i = 0; i < naxis_3D; i++) { lpixel[i] = naxes_3D[i]; } long *inc = new long[naxis_3D]; for (int i = 0; i < naxis_3D; i++) { inc[i] = 1; } float nulval = 0; long nelements_2D = 1; for (int i = 0; i < naxis_2D; i++) { nelements_2D = nelements_2D*naxes_2D[i]; } int anynul = 0; // read array_2D_real array_2D_real = new float[nelements_2D]; fpixel[2] = 1; lpixel[2] = 1; fits_read_subset(fptr, TFLOAT, fpixel, lpixel, inc, &nulval, array_2D_real, &anynul, &status); // read array_2D_imag array_2D_imag = new float[nelements_2D]; fpixel[2] = 2; lpixel[2] = 2; fits_read_subset(fptr, TFLOAT, fpixel, lpixel, inc, &nulval, array_2D_imag, &anynul, &status); // free arrays delete [] inc; delete [] lpixel; delete [] fpixel; // test read result if (status != 0) { return FORMAT_STATUS(status); } // close the FITS image file fits_close_file(fptr, &status); if (status != 0) { return FORMAT_STATUS(status); } return "READ_OK"; }
std::string read_image(std::string pathname, float *&array, int &naxis, long *&naxes) { TRACE_ENTER(); // open FITS image file in READONLY mode fitsfile *fptr; int status = 0; fits_open_image(&fptr, pathname.c_str(), READONLY, &status); if (status != 0) { return FORMAT_STATUS(status); } // read number of HDUs in the file int nhdus = 0; fits_get_num_hdus(fptr, &nhdus, &status); if (status != 0) { return FORMAT_STATUS(status); } // we expect only one HDU in the file if (nhdus != 1) { std::ostringstream exit_oss; exit_oss << "nhdus is " << nhdus << ", not 1"; TRACE_ERROR(exit_oss.str()); return exit_oss.str(); } // read the type of the HDU int hdutype = 0; fits_movabs_hdu(fptr, nhdus, &hdutype, &status); if (status != 0) { return FORMAT_STATUS(status); } // we expect the HDU to be an image if (hdutype != IMAGE_HDU) { std::ostringstream exit_oss; exit_oss << "hdutype is " << hdutype << ", not IMAGE_HDU"; TRACE_ERROR(exit_oss.str()); return exit_oss.str(); } // read the type of data in the HDU int bitpix = 0; fits_get_img_type (fptr, &bitpix, &status); if (status != 0) { return FORMAT_STATUS(status); } // we expect the data to be floats if (bitpix != FLOAT_IMG) { std::ostringstream exit_oss; exit_oss << "bitpix is " << bitpix << ", not FLOAT_IMG"; TRACE_ERROR(exit_oss.str()); return exit_oss.str(); } // get the number of dimensions in the image naxis = 0; fits_get_img_dim (fptr, &naxis, &status); if (status != 0) { return FORMAT_STATUS(status); } // we expect 2 or 3 dimensions in the image if ((naxis < 2) || (naxis > 3)) { std::ostringstream exit_oss; exit_oss << "naxis is " << naxis << ", neither 2 nor 3"; TRACE_ERROR(exit_oss.str()); return exit_oss.str(); } // get the size of each dimension in the image naxes = new long[naxis]; int maxdim = naxis; fits_get_img_size(fptr, maxdim, naxes, &status); if (status != 0) { return FORMAT_STATUS(status); } // fits_read_subset long *fpixel = new long[naxis]; for (int i = 0; i < naxis; i++) { fpixel[i] = 1; } long *lpixel = new long[naxis]; for (int i = 0; i < naxis; i++) { lpixel[i] = naxes[i]; } long *inc = new long[naxis]; for (int i = 0; i < naxis; i++) { inc[i] = 1; } float nulval = 0; long nelements = 1; for (int i = 0; i < naxis; i++) { nelements = nelements * naxes[i]; } array = new float[nelements]; int anynul = 0; fits_read_subset(fptr, TFLOAT, fpixel, lpixel, inc, &nulval, array, &anynul, &status); delete [] inc; delete [] lpixel; delete [] fpixel; if (status != 0) { return FORMAT_STATUS(status); } // close the FITS image file fits_close_file(fptr, &status); if (status != 0) { return FORMAT_STATUS(status); } return "READ_OK"; }
// getImageToArray: extract a sub-section from an image HDU, return array void *getImageToArray(fitsfile *fptr, int *dims, double *cens, char *slice, int *odim1, int *odim2, int *bitpix, int *status){ int i, naxis; int xcen, ycen, dim1, dim2, type; int tstatus = 0; int doscale = 0; void *obuf; long totpix, totbytes; long naxes[IDIM], fpixel[IDIM], lpixel[IDIM], inc[IDIM]; double bscale = 1.0; double bzero = 0.0; char comment[81]; char *s, *tslice; int nslice, idx, iaxis0, iaxis1; int iaxes[2] = {0, 1}; int saxes[IDIM] = {0, 0, 0, 0}; // seed buffers for(i=0; i<IDIM; i++){ naxes[i] = 0; fpixel[i] = 1; lpixel[i] = 1; inc[i] = 1; } // get image dimensions and type fits_get_img_dim(fptr, &naxis, status); fits_get_img_size(fptr, min(IDIM,naxis), naxes, status); fits_get_img_type(fptr, bitpix, status); if( naxis < 2 ){ *status = BAD_DIMEN; return NULL; } // parse slice string into primary axes and slice axes if( slice && *slice ){ tslice = (char *)strdup(slice); for(s=(char *)strtok(tslice, " :,"), nslice=0, idx=0; (s != NULL) && (nslice < IDIM); s=(char *)strtok(NULL," :,"), nslice++){ if( !strcmp(s, "*") ){ if( idx < 2 ){ iaxes[idx++] = nslice; } } else { saxes[nslice] = atoi(s); if( (saxes[nslice] < 1) || (saxes[nslice] > naxes[nslice]) ){ *status = SEEK_ERROR; return NULL; } } } free(tslice); } // convenience variables for the primary axis indexes iaxis0 = iaxes[0]; iaxis1 = iaxes[1]; // get limits of extracted section if( dims && dims[0] && dims[1] ){ dim1 = min(dims[0], naxes[iaxis0]); dim2 = min(dims[1], naxes[iaxis1]); // read image section if( cens ){ xcen = cens[0]; ycen = cens[1]; } else { xcen = dim1/2; ycen = dim2/2; } fpixel[iaxis0] = (int)(xcen - (dim1+1)/2); fpixel[iaxis1] = (int)(ycen - (dim2+1)/2); lpixel[iaxis0] = (int)(xcen + (dim1/2)); lpixel[iaxis1] = (int)(ycen + (dim2/2)); } else { // read entire image fpixel[iaxis0] = 1; fpixel[iaxis1] = 1; lpixel[iaxis0] = naxes[iaxis0]; lpixel[iaxis1] = naxes[iaxis1]; } // stay within image limits fpixel[iaxis0] = max(fpixel[iaxis0], 1); fpixel[iaxis0] = min(fpixel[iaxis0], naxes[iaxis0]); lpixel[iaxis0] = max(lpixel[iaxis0], 1); lpixel[iaxis0] = min(lpixel[iaxis0], naxes[iaxis0]); fpixel[iaxis1] = max(fpixel[iaxis1], 1); fpixel[iaxis1] = min(fpixel[iaxis1], naxes[iaxis0]); lpixel[iaxis1] = max(lpixel[iaxis1], 1); lpixel[iaxis1] = min(lpixel[iaxis1], naxes[iaxis0]); // for sliced dimensions, set first and last pixel to the specified slice for(i=0; i<min(IDIM,naxis); i++){ if( saxes[i] ){ // 1 pixel slice in this dimension fpixel[i] = saxes[i]; lpixel[i] = saxes[i]; // stay within image limits fpixel[i] = max(fpixel[i], 1); fpixel[i] = min(fpixel[i], naxes[i]); lpixel[i] = max(lpixel[i], 1); lpixel[i] = min(lpixel[i], naxes[i]); } } // section dimensions *odim1 = lpixel[iaxis0] - fpixel[iaxis0] + 1; *odim2 = lpixel[iaxis1] - fpixel[iaxis1] + 1; totpix = *odim1 * *odim2; // make sure we have an image with valid dimensions size if( totpix <= 1 ){ *status = NEG_AXIS; return NULL; } // are we scaling? fits_read_key(fptr, TDOUBLE, "BSCALE", &bscale, comment, &tstatus); if( tstatus != VALUE_UNDEFINED ){ fits_read_key(fptr, TDOUBLE, "BZERO", &bzero, comment, &tstatus); } if( (bscale != 1.0) || (bzero != 0.0) ){ doscale = 1; } // allocate space for the pixel array switch(*bitpix){ case 8: if( doscale ){ // scaled data has to be float *bitpix = -32; type = TFLOAT; totbytes = totpix * sizeof(float); } else { type = TBYTE; totbytes = totpix * sizeof(char); } break; case 16: if( doscale ){ // scaled data has to be float *bitpix = -32; type = TFLOAT; totbytes = totpix * sizeof(float); } else { type = TSHORT; totbytes = totpix * sizeof(short); } break; case -16: if( doscale ){ // scaled data has to be float *bitpix = -32; type = TFLOAT; totbytes = totpix * sizeof(float); } else { type = TUSHORT; totbytes = totpix * sizeof(unsigned short); } break; case 32: if( doscale ){ // scaled data has to be float *bitpix = -32; type = TFLOAT; totbytes = totpix * sizeof(float); } else { type = TINT; totbytes = totpix * sizeof(int); } break; case 64: if( doscale ){ // scaled data has to be float *bitpix = -32; type = TFLOAT; totbytes = totpix * sizeof(float); } else { type = TLONGLONG; totbytes = totpix * sizeof(long long); } break; case -32: type = TFLOAT; totbytes = totpix * sizeof(float); break; case -64: type = TDOUBLE; totbytes = totpix * sizeof(double); break; default: return NULL; } #if EM // sanity check on memory limits if( totbytes > max_memory ){ *status = MEMORY_ALLOCATION; return NULL; } #endif // try to allocate that much memory if(!(obuf = (void *)malloc(totbytes))){ *status = MEMORY_ALLOCATION; return NULL; } /* read the image section */ fits_read_subset(fptr, type, fpixel, lpixel, inc, 0, obuf, 0, status); // return pixel buffer (and section dimensions) return obuf; }