static void write_data_to_file(pi16u * buf, struct metadata * md, char * prepend, lua_State *L) { fitsfile *ff; int status = 0, retcode = 0; long naxes[2] = {2048, 2048}; char outdir[STR_BUF_SIZE]; char outfile[STR_BUF_SIZE]; float bscale1 = 1.0, bzero32768 = 32768.0; SYSTEMTIME str_t; /* Create output directory */ GetLocalTime(&str_t); sprintf_s(outdir, STR_BUF_SIZE, "%s\\%4d%s%2d", path_prefix, str_t.wYear, months[str_t.wMonth], str_t.wDay); if(!DirectoryExists((LPCTSTR) outdir)) { printf("Creating directory %s\n", outdir); if(!mkdir(outdir)) { lua_pushstring(L,"Could not create path\n"); lua_error(L); return; } } sprintf_s(outfile, STR_BUF_SIZE, "!%s\\%s%4.4d%2.2d%2.2d_%2.2i_%2.2i_%2.2i.fits", outdir, prepend, str_t.wYear, str_t.wMonth, str_t.wDay, str_t.wHour, str_t.wMinute, str_t.wSecond); /* FITS housekeeping */ retcode = fits_create_file(&ff, outfile, &status); if(retcode) { lua_pushstring(L,"Could not create FITS file\n"); fits_report_error(stderr, status); lua_error(L); return; } retcode = fits_create_img(ff, SHORT_IMG , // bitpix 2, // naxis naxes, // naxes &status); if(retcode) { lua_pushstring(L,"Could not create image \n"); fits_report_error(stderr, status); lua_error(L); fits_close_file(ff, &status); return; } // Following line is required to handle ushort, see: // "Support for Unsigned Integers and Signed Bytes" in // cfitsio manual fits_write_key(ff, TFLOAT, "BSCALE", &bscale1, NULL, &status); fits_write_key(ff, TFLOAT, "BZERO", &bzero32768, NULL, &status); fits_set_bscale(ff, 1, //BSCALE Factor 32768, // BZERO factor &status); fits_write_key(ff, TDOUBLE, "EXPTIME", &md->exptime, "Exposure time in s", &status); fits_write_key(ff, TDOUBLE, "ADCSPEED", &md->adcspeed, "Readout speed in MHz", &status); fits_write_key(ff, TDOUBLE, "TEMP", &md->temp, "Detector temp in deg C", &status); fits_write_key(ff, TINT, "BITDEPTH", &md->bitdepth, "Bit depth", &status); fits_write_key(ff, TINT, "GAIN_SET", &md->gain, "1: low, 2: medium, 3: high gain", &status); fits_write_key(ff, TINT, "ADC", &md->adc, "1: Low noise, 2: high capacity", &status); fits_write_key(ff, TINT, "MODEL", &md->id->model, "PI Model #", &status); fits_write_key(ff, TINT, "INTERFC", &md->id->computer_interface, "PI Computer Interface", &status); fits_write_key(ff, TSTRING, "SNSR_NM", &md->id->sensor_name, "PI sensor name", &status); fits_write_key(ff, TSTRING, "SER_NO", &md->id->serial_number, "PI serial #", &status); retcode = fits_write_img(ff, TUSHORT, // (T)ype is unsigned short (USHORT) 1, // Copy from [0, 0] but fits format is indexed by 1 naxes[0] * naxes[1], // Number of elements buf, &status); if(retcode && status==412) { printf("Overflow\n"); } else if(retcode) { lua_pushstring(L,"Could not copy data over \n"); fits_report_error(stderr, status); lua_error(L); fits_close_file(ff, &status); return; } fits_close_file(ff, &status); printf("Wrote '%s'.\n", outfile); }
int main(int argc, char *argv[]) { fitsfile *infptr, *outfptr; /* FITS file pointers defined in fitsio.h */ int status = 0, ii = 1, iteration = 0, single = 0, hdupos; int hdutype, bitpix, bytepix, naxis = 0, nkeys, datatype = 0, anynul; long naxes[9] = {1, 1, 1, 1, 1, 1, 1, 1, 1}; long first, totpix = 0, npix; double *array, bscale = 1.0, bzero = 0.0, nulval = 0.; char card[81]; if (argc != 3) { printf("\n"); printf("Usage: imcopy inputImage outputImage[compress]\n"); printf("\n"); printf("Copy an input image to an output image, optionally compressing\n"); printf("or uncompressing the image in the process. If the [compress]\n"); printf("qualifier is appended to the output file name then the input image\n"); printf("will be compressed using the tile-compressed format. In this format,\n"); printf("the image is divided into rectangular tiles and each tile of pixels\n"); printf("is compressed and stored in a variable-length row of a binary table.\n"); printf("If the [compress] qualifier is omitted, and the input image is\n"); printf("in tile-compressed format, then the output image will be uncompressed.\n"); printf("\n"); printf("If an extension name or number is appended to the input file name, \n"); printf("enclosed in square brackets, then only that single extension will be\n"); printf("copied to the output file. Otherwise, every extension in the input file\n"); printf("will be processed in turn and copied to the output file.\n"); printf("\n"); printf("Examples:\n"); printf("\n"); printf("1) imcopy image.fit 'cimage.fit[compress]'\n"); printf("\n"); printf(" This compresses the input image using the default parameters, i.e.,\n"); printf(" using the Rice compression algorithm and using row by row tiles.\n"); printf("\n"); printf("2) imcopy cimage.fit image2.fit\n"); printf("\n"); printf(" This uncompress the image created in the first example.\n"); printf(" image2.fit should be identical to image.fit if the image\n"); printf(" has an integer datatype. There will be small differences\n"); printf(" in the pixel values if it is a floating point image.\n"); printf("\n"); printf("3) imcopy image.fit 'cimage.fit[compress GZIP 100,100;4]'\n"); printf("\n"); printf(" This compresses the input image using the following parameters:\n"); printf(" GZIP compression algorithm;\n"); printf(" 100 X 100 pixel compression tiles;\n"); printf(" noise_bits = 4 (only used with floating point images)\n"); printf("\n"); printf("The full syntax of the compression qualifier is:\n"); printf(" [compress ALGORITHM TDIM1,TDIM2,...; NOISE_BITS]\n"); printf("where the allowed ALGORITHM values are Rice, GZIP, PLIO, \n"); printf("and TDIMn is the size of the compression tile in each dimension,\n"); printf("and NOISE_BITS = 1, 2, 3, or 4 and controls the amount of noise\n"); printf("suppression when compressing floating point images. \n"); printf("\n"); printf("Note that it may be necessary to enclose the file names\n"); printf("in single quote characters on the Unix command line.\n"); return(0); } /* Open the input file and create output file */ fits_open_file(&infptr, argv[1], READONLY, &status); fits_create_file(&outfptr, argv[2], &status); if (status != 0) { fits_report_error(stderr, status); return(status); } fits_get_hdu_num(infptr, &hdupos); /* Get the current HDU position */ /* Copy only a single HDU if a specific extension was given */ if (hdupos != 1 || strchr(argv[1], '[')) single = 1; for (; !status; hdupos++) /* Main loop through each extension */ { fits_get_hdu_type(infptr, &hdutype, &status); if (hdutype == IMAGE_HDU) { /* get image dimensions and total number of pixels in image */ for (ii = 0; ii < 9; ii++) naxes[ii] = 1; fits_get_img_param(infptr, 9, &bitpix, &naxis, naxes, &status); totpix = naxes[0] * naxes[1] * naxes[2] * naxes[3] * naxes[4] * naxes[5] * naxes[6] * naxes[7] * naxes[8]; } if (hdutype != IMAGE_HDU || naxis == 0 || totpix == 0) { /* just copy tables and null images */ fits_copy_hdu(infptr, outfptr, 0, &status); } else { /* Explicitly create new image, to support compression */ fits_create_img(outfptr, bitpix, naxis, naxes, &status); if (status) { fits_report_error(stderr, status); return(status); } /* copy all the user keywords (not the structural keywords) */ fits_get_hdrspace(infptr, &nkeys, NULL, &status); for (ii = 1; ii <= nkeys; ii++) { fits_read_record(infptr, ii, card, &status); if (fits_get_keyclass(card) > TYP_CMPRS_KEY) fits_write_record(outfptr, card, &status); } switch(bitpix) { case BYTE_IMG: datatype = TBYTE; break; case SHORT_IMG: datatype = TSHORT; break; case LONG_IMG: datatype = TINT; break; case FLOAT_IMG: datatype = TFLOAT; break; case DOUBLE_IMG: datatype = TDOUBLE; break; } bytepix = abs(bitpix) / 8; npix = totpix; iteration = 0; /* try to allocate memory for the entire image */ /* use double type to force memory alignment */ array = (double *) calloc(npix, bytepix); /* if allocation failed, divide size by 2 and try again */ while (!array && iteration < 10) { iteration++; npix = npix / 2; array = (double *) calloc(npix, bytepix); } if (!array) { printf("Memory allocation error\n"); return(0); } /* turn off any scaling so that we copy the raw pixel values */ fits_set_bscale(infptr, bscale, bzero, &status); fits_set_bscale(outfptr, bscale, bzero, &status); first = 1; while (totpix > 0 && !status) { /* read all or part of image then write it back to the output file */ fits_read_img(infptr, datatype, first, npix, &nulval, array, &anynul, &status); fits_write_img(outfptr, datatype, first, npix, array, &status); totpix = totpix - npix; first = first + npix; } free(array); } if (single) break; /* quit if only copying a single HDU */ fits_movrel_hdu(infptr, 1, NULL, &status); /* try to move to next HDU */ } if (status == END_OF_FILE) status = 0; /* Reset after normal error */ fits_close_file(outfptr, &status); fits_close_file(infptr, &status); /* if error occurred, print out error message */ if (status) fits_report_error(stderr, status); return(status); }
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."); } } }