#ifndef STIM_ENVI_H #define STIM_ENVI_H #include #include #include #include #include #include #include #include #include //#include "../image/image.h" namespace stim{ /** This class implements reading of ENVI hyperspectral files. These files can be stored in multiple orientations (including BSQ, BIP, and BIL) in order to optimize streaming speed depending on applications. Basic ENVI files are stored on disk as a large binary file with a corresponding header. Code for reading and processing ENVI header files is in the envi_header class. */ class envi{ void* file; //void pointer to the relevant file reader (bip, bsq, or bil - with appropriate data type) std::string fname; //file name used for repeated opening and closing //allocate sufficient space for a spectrum based on the data type and number of bands void* alloc_array(size_t len){ switch(header.data_type){ case envi_header::int8: return malloc(len); case envi_header::int16: case envi_header::uint16: return malloc(2 * len); case envi_header::int32: case envi_header::uint32: case envi_header::float32: return malloc(4 * len); case envi_header::int64: case envi_header::uint64: case envi_header::float64: case envi_header::complex32: return malloc(8 * len); case envi_header::complex64: return malloc(16 * len); default: std::cout<<"ERROR stim::envi data type not recognized for spectral allocation"< inline void cast(DST* dst, SRC* src){ (*dst) = (DST)(*src); } //cast an array from type SRC to type DEST template inline void cast(DST* dst, SRC* src, size_t len){ for(size_t i = 0; i < len; i++) cast(&dst[i], &src[i]); } public: envi_header header; /// Default constructor envi(){ file = NULL; //set the file pointer to NULL } envi(std::string filename, std::string headername) : envi(){ header.load(headername); fname = filename; //save the filename allocate(); } //used to test if the current ENVI file is valid operator bool(){ if (header.interleave == envi_header::BSQ) { //if the infile is bsq file if (header.data_type == envi_header::float32) return ((bsq*)file)->is_open(); else if (header.data_type == envi_header::float64) return ((bsq*)file)->is_open(); else std::cout << "ERROR: unidentified data type" << std::endl; } else if (header.interleave == envi_header::BIL) { //if the infile is bil file if (header.data_type == envi_header::float32) return ((bil*)file)->is_open(); else if (header.data_type == envi_header::float64) return ((bil*)file)->is_open(); else std::cout << "ERROR: unidentified data type" << std::endl; } else if (header.interleave == envi_header::BIP) { //if the infile is bip file if (header.data_type == envi_header::float32) return ((bip*)file)->is_open(); else if (header.data_type == envi_header::float64) return ((bip*)file)->is_open(); else std::cout << "ERROR: unidentified data type" << std::endl; } else { std::cout << "ERROR: unidentified file type" << std::endl; exit(1); } return false; } //test to determine if the specified file is an ENVI file static bool is_envi(std::string fname, std::string hname = ""){ stim::filename data_file(fname); stim::filename header_file; if(hname == ""){ //if the header isn't provided header_file = data_file; //assume that it's the same name as the data file, with a .hdr extension header_file = header_file.extension("hdr"); } else header_file = hname; //otherwise load the passed header stim::envi_header H; if(H.load(header_file) == false) //load the header file, if it doesn't load return false return false; size_t targetBytes = H.data_bytes(); //get the number of bytes that SHOULD be in the data file size_t bytes = stim::file_size(fname); if (bytes != targetBytes) { std::cout << "ERROR: File size mismatch. Based on the header, a " << targetBytes << " byte file was expected. The data file contains " << bytes << " bytes." << std::endl; return false; //if the data doesn't match the header, return false } return true; //otherwise everything looks fine } void* malloc_spectrum(){ return alloc_array(header.bands); } void* malloc_band(){ return alloc_array(header.samples * header.lines); } void set_buffer_frac(double memfrac = 0.5){ if(header.interleave == envi_header::BSQ){ //if the infile is bsq file if(header.data_type ==envi_header::float32) ((bsq*)file)->set_buffer_frac(memfrac); else if(header.data_type == envi_header::float64) ((bsq*)file)->set_buffer_frac(memfrac); else std::cout<<"ERROR: unidentified data type"<*)file)->set_buffer_frac(memfrac); else if(header.data_type == envi_header::float64) ((bil*)file)->set_buffer_frac(memfrac); else std::cout<<"ERROR: unidentified data type"<*)file)->set_buffer_frac(memfrac); else if(header.data_type == envi_header::float64) ((bip*)file)->set_buffer_frac(memfrac); else std::cout<<"ERROR: unidentified data type"<*)file)->set_buffer_raw(bytes); else if(header.data_type == envi_header::float64) ((bsq*)file)->set_buffer_raw(bytes); else std::cout<<"ERROR: unidentified data type"<*)file)->set_buffer_raw(bytes); else if(header.data_type == envi_header::float64) ((bil*)file)->set_buffer_raw(bytes); else std::cout<<"ERROR: unidentified data type"<*)file)->set_buffer_raw(bytes); else if(header.data_type == envi_header::float64) ((bip*)file)->set_buffer_raw(bytes); else std::cout<<"ERROR: unidentified data type"<*)file)->reset_progress(); else if(header.data_type == envi_header::float64) ((bsq*)file)->reset_progress(); else std::cout<<"ERROR: unidentified data type"<*)file)->reset_progress(); else if(header.data_type == envi_header::float64) ((bil*)file)->reset_progress(); else std::cout<<"ERROR: unidentified data type"<*)file)->reset_progress(); else if(header.data_type == envi_header::float64) ((bip*)file)->reset_progress(); else std::cout<<"ERROR: unidentified data type"<*)file)->get_progress(); else if(header.data_type == envi_header::float64) return ((bsq*)file)->get_progress(); else std::cout<<"ERROR: unidentified data type"<*)file)->get_progress(); else if(header.data_type == envi_header::float64) return ((bil*)file)->get_progress(); else std::cout<<"ERROR: unidentified data type"<*)file)->get_progress(); else if(header.data_type == envi_header::float64) return ((bip*)file)->get_progress(); else std::cout<<"ERROR: unidentified data type"<*)file)->get_data_rate(); else if(header.data_type == envi_header::float64) return ((bsq*)file)->get_data_rate(); else std::cout<<"ERROR: unidentified data type"<*)file)->get_data_rate(); else if(header.data_type == envi_header::float64) return ((bil*)file)->get_data_rate(); else std::cout<<"ERROR: unidentified data type"<*)file)->get_data_rate(); else if(header.data_type == envi_header::float64) return ((bip*)file)->get_data_rate(); else std::cout<<"ERROR: unidentified data type"<(); else if(header.data_type == envi_header::float64) file = new bsq(); } else if(header.interleave == envi_header::BIP){ if(header.data_type ==envi_header::float32) file = new bip(); else if(header.data_type == envi_header::float64) file = new bip(); } else if(header.interleave == envi_header::BIL){ if(header.data_type ==envi_header::float32) file = new bil(); else if(header.data_type == envi_header::float64) file = new bil(); } } /// Open a previously opened ENVI file bool open(stim::iotype io = stim::io_in){ //load the file if(header.interleave == envi_header::BSQ) { //if the infile is bsq file if(header.data_type == envi_header::float32) { return ((bsq*)file)->open(fname, header.samples, header.lines, header.bands, header.header_offset, header.wavelength); } else if(header.data_type == envi_header::float64) { return ((bsq*)file)->open(fname, header.samples, header.lines, header.bands, header.header_offset, header.wavelength); } else { std::cout << "ERROR: The specified data format (" << header.data_type << ") is not supported" << std::endl; return false; } } else if(header.interleave == envi_header::BIL) { //if the infile is bil file if(header.data_type == envi_header::float32) { return ((bil*)file)->open(fname, header.samples, header.lines, header.bands, header.header_offset, header.wavelength); } else if(header.data_type == envi_header::float64) { return ((bil*)file)->open(fname, header.samples, header.lines, header.bands, header.header_offset, header.wavelength); } { std::cout << "ERROR: The specified data format (" << header.data_type << ") is not supported" << std::endl; return false; } } else if(header.interleave == envi_header::BIP) { //if the infile is bip file if(header.data_type == envi_header::float32) { return ((bip*)file)->open(fname, header.samples, header.lines, header.bands, header.header_offset, header.wavelength); } else if(header.data_type == envi_header::float64) { return ((bip*)file)->open(fname, header.samples, header.lines, header.bands, header.header_offset, header.wavelength); } { std::cout << "ERROR: The specified data format (" << header.data_type << ") is not supported" << std::endl; return false; } } return true; } /// Open an Agilent binary file as an ENVI stream bool open_agilent(std::string filename){ fname = filename; //store the file name //Open the file temporarily to get the header information FILE* f = fopen(filename.c_str(), "r"); //open the binary file for reading if(f == NULL) return false; //return false if no file is opened fseek(f, 9, SEEK_SET); //seek to the number of bands short b; //allocate space for the number of bands size_t nread = fread(&b, sizeof(short), 1, f); //read the number of bands if(nread != 1){ std::cout<<"Error reading band number from Agilent file."< threshold (preventing division by small numbers) bool ratio(std::string outfile, double band, unsigned char* mask = NULL, bool PROGRESS = false){ header.save(outfile + ".hdr"); if(header.interleave == envi_header::BSQ){ //if the infile is bsq file if(header.data_type ==envi_header::float32) return ((bsq*)file)->ratio(outfile, band, mask, PROGRESS); else if(header.data_type == envi_header::float64) return ((bsq*)file)->ratio(outfile,band, mask, PROGRESS); else std::cout<<"ERROR: unidentified data type"<*)file)->ratio(outfile, band, mask, PROGRESS); else if(header.data_type == envi_header::float64) return ((bil*)file)->ratio(outfile,band, mask, PROGRESS); else std::cout<<"ERROR: unidentified data type"<*)file)->ratio(outfile, band, mask, PROGRESS); else if(header.data_type == envi_header::float64) return ((bip*)file)->ratio(outfile,band, mask, PROGRESS); else std::cout<<"ERROR: unidentified data type"<*)file)->normalize(outfile, mask, PROGRESS); else if(header.data_type == envi_header::float64) ((bsq*)file)->normalize(outfile, mask, PROGRESS); else std::cout<<"ERROR: unidentified data type"<*)file)->normalize(outfile, mask, PROGRESS); else if(header.data_type == envi_header::float64) ((bil*)file)->normalize(outfile, mask, PROGRESS); else std::cout<<"ERROR: unidentified data type"<*)file)->normalize(outfile, mask, PROGRESS); else if(header.data_type == envi_header::float64) ((bip*)file)->normalize(outfile, mask, PROGRESS); else std::cout<<"ERROR: unidentified data type"< bandlist, unsigned char* MASK = NULL, bool PROGRESS = false) { stim::envi_header new_header = header; //copy all of the data from the current header file to the new one new_header.bands = bandlist.size(); //the number of bands in the new file is equal to the number of bands provided by the user new_header.wavelength = bandlist; //the wavelength values in the output file are the same as those specified by the user new_header.band_names.empty(); //no band names will be provided in the output file new_header.save(outfile + ".hdr"); //save the output header file if (header.interleave == envi_header::BSQ) { //if the infile is bip file if (header.data_type == envi_header::float32) return ((bsq*)file)->select(outfile, bandlist, MASK, PROGRESS); else if (header.data_type == envi_header::float64) return ((bsq*)file)->select(outfile, bandlist, MASK, PROGRESS); else std::cout << "ERROR: unidentified data type" << std::endl; } else if (header.interleave == envi_header::BIL) { //if the infile is bip file if (header.data_type == envi_header::float32) return ((bil*)file)->select(outfile, bandlist, MASK, PROGRESS); else if (header.data_type == envi_header::float64) return ((bil*)file)->select(outfile, bandlist, MASK, PROGRESS); else std::cout << "ERROR: unidentified data type" << std::endl; } else if (header.interleave == envi_header::BIP) { //if the infile is bip file if (header.data_type == envi_header::float32) return ((bip*)file)->select(outfile, bandlist, MASK, PROGRESS); else if (header.data_type == envi_header::float64) return ((bip*)file)->select(outfile, bandlist, MASK, PROGRESS); else std::cout << "ERROR: unidentified data type" << std::endl; } return false; } /// Performs piecewise linear baseline correction of a hyperspectral file/ /// @param outfile is the file name for the baseline corrected output /// @param w is a list of band labels to serve as baseline points (zero values) bool baseline(std::string outfile, std::vector w, unsigned char* mask = NULL, bool PROGRESS = false){ header.save(outfile + ".hdr"); if(header.interleave == envi_header::BSQ){ //if the infile is bsq file if(header.data_type ==envi_header::float32) return ((bsq*)file)->baseline(outfile, w, mask, PROGRESS); else if(header.data_type == envi_header::float64) return ((bsq*)file)->baseline(outfile,w, mask, PROGRESS); else{ std::cout<<"ERROR: unidentified data type"<*)file)->baseline(outfile, w, mask, PROGRESS); else if(header.data_type == envi_header::float64) return ((bil*)file)->baseline(outfile, w, mask, PROGRESS); else{ std::cout<<"ERROR: unidentified data type"<*)file)->baseline(outfile, w, mask, PROGRESS); else if(header.data_type == envi_header::float64) return ((bip*)file)->baseline(outfile, w, mask, PROGRESS); else{ std::cout<<"ERROR: unidentified data type"< bands, unsigned char* mask, int cuda_device = 0, bool PROGRESS = false) { if(header.interleave == envi_header::BSQ){ //if the infile is bsq file std::cout<<"ERROR: BSQ projection not supported"<*)file)->project(outfile, center, basis, M, mask, cuda_device, PROGRESS); else if(header.data_type == envi_header::float64) ((bip*)file)->project(outfile, center, basis, M, mask, cuda_device, PROGRESS); else{ std::cout<<"ERROR: unidentified data type"<*)file)->inverse(outfile, center, basis, B, C, PROGRESS); else if(header.data_type == envi_header::float64) ((bip*)file)->inverse(outfile, center, basis, B, C, PROGRESS); else{ std::cout<<"ERROR: unidentified data type"< BIL ((bsq*)file)->bil(outfile, PROGRESS, VERBOSE, OPTIMIZATION); else if(interleave == envi_header::BIP){ //ERROR //std::cout<<"ERROR: conversion from BSQ to BIP isn't practical; use BSQ->BIL->BIP instead"<*)file)->bip(outfile, PROGRESS, VERBOSE, OPTIMIZATION); //exit(1); } } else if(header.data_type == envi_header::float64){ //if the data type is float if(interleave == envi_header::BSQ){ //ERROR std::cout<<"ERROR: is already BSQ file"< BIL ((bsq*)file)->bil(outfile, PROGRESS, OPTIMIZATION); else if(interleave == envi_header::BIP){ //ERROR //std::cout<<"ERROR: conversion from BSQ to BIP isn't practical; use BSQ->BIL->BIP instead"<*)file)->bip(outfile, PROGRESS, OPTIMIZATION); //exit(1); } } else{ std::cout<<"ERROR: unidentified data type"< BSQ ((bil*)file)->bsq(outfile, PROGRESS); else if(interleave == envi_header::BIP) //BIL -> BIP ((bil*)file)->bip(outfile, PROGRESS); } else if(header.data_type == envi_header::float64){ if(interleave == envi_header::BIL){ //ERROR std::cout<<"ERROR: is already BIL file"< BSQ ((bil*)file)->bsq(outfile, PROGRESS); else if(interleave == envi_header::BIP) //BIL -> BIP ((bil*)file)->bip(outfile, PROGRESS); } else{ std::cout<<"ERROR: unidentified data type"< BIL ((bip*)file)->bil(outfile, PROGRESS); else if(interleave == envi_header::BSQ){ //ERROR std::cout<<"ERROR: conversion from BIP to BSQ isn't practical; use BIP->BIL->BSQ instead"<*)file)->bip(outfile, PROGRESS); exit(1); } } else if(header.data_type == envi_header::float64){ if(interleave == envi_header::BIP){ //ERROR std::cout<<"ERROR: is already BIP file"< BIL ((bip*)file)->bil(outfile, PROGRESS); else if(interleave == envi_header::BSQ){ //ERROR std::cout<<"ERROR: conversion from BIP to BSQ isn't practical; use BIP->BIL->BSQ instead"<*)file)->bip(outfile, PROGRESS); exit(1); } } else{ std::cout<<"ERROR: unidentified data type"<*)file)->build_mask(out_mask, mask_band, lower, upper, mask, PROGRESS); else if(header.data_type == envi_header::float64) return ((bsq*)file)->build_mask(out_mask, mask_band, lower, upper, mask, PROGRESS); else std::cout<<"ERROR: unidentified data type"<*)file)->build_mask(out_mask, mask_band, lower, upper, mask, PROGRESS); else if(header.data_type == envi_header::float64) return ((bil*)file)->build_mask(out_mask, mask_band, lower, upper, mask, PROGRESS); else std::cout<<"ERROR: unidentified data type"<*)file)->build_mask(out_mask, mask_band, lower, upper, mask, PROGRESS); else if(header.data_type == envi_header::float64) return ((bip*)file)->build_mask(out_mask, mask_band, lower, upper, mask, PROGRESS); else std::cout<<"ERROR: unidentified data type"<*)file)->mask_finite(out_mask, mask, PROGRESS); else if(header.data_type == envi_header::float64) ((bsq*)file)->mask_finite(out_mask, mask, PROGRESS); else std::cout<<"ERROR: unidentified data type"<*)file)->mask_finite(out_mask, mask, PROGRESS); else if(header.data_type == envi_header::float64) ((bil*)file)->mask_finite(out_mask, mask, PROGRESS); else std::cout<<"ERROR: unidentified data type"<*)file)->mask_finite(out_mask, mask, PROGRESS); else if(header.data_type == envi_header::float64) ((bip*)file)->mask_finite(out_mask, mask, PROGRESS); else std::cout<<"ERROR: unidentified data type"<*)file)->apply_mask(outfile, p, PROGRESS); else if (header.data_type == envi_header::float64) ((bsq*)file)->apply_mask(outfile, p, PROGRESS); else std::cout << "ERROR: unidentified data type" << std::endl; } else if (header.interleave == envi_header::BIL){ //if the infile is bil file if (header.data_type == envi_header::float32) ((bil*)file)->apply_mask(outfile, p, PROGRESS); else if (header.data_type == envi_header::float64) ((bil*)file)->apply_mask(outfile, p, PROGRESS); else std::cout << "ERROR: unidentified data type" << std::endl; } else if (header.interleave == envi_header::BIP){ //if the infile is bip file if (header.data_type == envi_header::float32) ((bip*)file)->apply_mask(outfile, p, PROGRESS); else if (header.data_type == envi_header::float64) ((bip*)file)->apply_mask(outfile, p, PROGRESS); else std::cout << "ERROR: unidentified data type" << std::endl; } else{ std::cout << "ERROR: unidentified file type" << std::endl; exit(1); } header.save(outfile + ".hdr"); } /// Copies all spectra corresponding to nonzero values of a mask into a pre-allocated matrix of size (P x B) /// where P is the number of masked pixels and B is the number of bands. The allocated memory can be accessed /// using the following indexing: i = b*P + p /// @param matrix is the destination for the pixel data /// @param p is the mask bool sift(void* matrix, unsigned char* p = NULL, bool PROGRESS = false){ if (header.interleave == envi_header::BSQ){ //if the infile is bsq file if (header.data_type == envi_header::float32) return ((bsq*)file)->sift((float*)matrix, p, PROGRESS); else if (header.data_type == envi_header::float64) return ((bsq*)file)->sift((double*)matrix, p, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } if (header.interleave == envi_header::BIP){ if (header.data_type == envi_header::float32) return ((bip*)file)->sift((float*)matrix, p, PROGRESS); else if (header.data_type == envi_header::float64) return ((bip*)file)->sift((double*)matrix, p, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } if (header.interleave == envi_header::BIL){ if (header.data_type == envi_header::float32) return ((bil*)file)->sift((float*)matrix, p, PROGRESS); else if (header.data_type == envi_header::float64) return ((bil*)file)->sift((double*)matrix, p, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } return false; } /// Saves in an array only those spectra corresponding to nonzero values of the mask. /// @param outfile is the name of the sifted output file /// @param p is the mask bool sift(std::string outfile, unsigned char* p, bool PROGRESS = false) { //calculate the number of non-zero values in the mask unsigned long long nnz = 0; unsigned long long npixels = header.lines * header.samples; for(unsigned long long i = 0; i < npixels; i++) if( p[i] > 0 ) nnz++; //create a new header envi_header new_header = header; //if a BIL file is sifted, it's saved as a BIP if(header.interleave == envi_header::BIL) new_header.interleave = envi_header::BIP; //set the number of lines to 1 (this is a matrix with 1 line and N samples) new_header.lines = 1; new_header.samples = nnz; new_header.save(outfile + ".hdr"); if (header.interleave == envi_header::BSQ){ //if the infile is bsq file if (header.data_type == envi_header::float32) return ((bsq*)file)->sift(outfile, p, PROGRESS); else if (header.data_type == envi_header::float64) return ((bsq*)file)->sift(outfile, p, PROGRESS); else std::cout << "ERROR: unidentified data type" << std::endl; } else if (header.interleave == envi_header::BIL){ //if the infile is bil file if (header.data_type == envi_header::float32) return ((bil*)file)->sift(outfile, p, PROGRESS); else if (header.data_type == envi_header::float64) return ((bil*)file)->sift(outfile, p, PROGRESS); else std::cout << "ERROR: unidentified data type" << std::endl; } else if (header.interleave == envi_header::BIP){ //if the infile is bip file if (header.data_type == envi_header::float32) return ((bip*)file)->sift(outfile, p, PROGRESS); else if (header.data_type == envi_header::float64) return ((bip*)file)->sift(outfile, p, PROGRESS); else std::cout << "ERROR: unidentified data type" << std::endl; } else{ std::cout << "ERROR: unidentified file type" << std::endl; exit(1); } return false; } bool unsift(std::string outfile, unsigned char* mask, unsigned long long samples, unsigned long long lines, bool PROGRESS = false){ //create a new header envi_header new_header = header; //set the number of lines and samples in the output file (that's all that changes) new_header.lines = lines; new_header.samples = samples; new_header.save(outfile + ".hdr"); if (header.interleave == envi_header::BSQ){ //if the infile is bsq file if (header.data_type == envi_header::float32) return ((bsq*)file)->unsift(outfile, mask, samples, lines, PROGRESS); else if (header.data_type == envi_header::float64) return ((bsq*)file)->unsift(outfile, mask, samples, lines, PROGRESS); else std::cout << "ERROR: unidentified data type" << std::endl; } else if (header.interleave == envi_header::BIL){ //if the infile is bil file std::cout << "ERROR in stim::envi::unsift - BIL files aren't supported yet" << std::endl; } else if (header.interleave == envi_header::BIP){ //if the infile is bip file if (header.data_type == envi_header::float32) return ((bip*)file)->unsift(outfile, mask, samples, lines, PROGRESS); else if (header.data_type == envi_header::float64) return ((bip*)file)->unsift(outfile, mask, samples, lines, PROGRESS); else std::cout << "ERROR: unidentified data type" << std::endl; } else{ std::cout << "ERROR: unidentified file type" << std::endl; } return 0; } /// Compute the ratio of two baseline-corrected peaks. The result is stored in a pre-allocated array. /// @param lb1 is the label value for the left baseline point for the first peak (numerator) /// @param rb1 is the label value for the right baseline point for the first peak (numerator) /// @param pos1 is the label value for the first peak (numerator) position /// @param lb2 is the label value for the left baseline point for the second peak (denominator) /// @param rb2 is the label value for the right baseline point for the second peak (denominator) /// @param pos2 is the label value for the second peak (denominator) position /// @param result is a pointer to a pre-allocated array at least X * Y * sizeof(T) in size bool ph_to_ph(void * result, double lb1, double rb1, double pos1, double lb2, double rb2, double pos2, unsigned char* mask){ if(header.interleave == envi_header::BSQ){ //if the infile is bsq file if(header.data_type ==envi_header::float32) return ((bsq*)file)->ph_to_ph((float*)result, lb1, rb1, pos1, lb2, rb2, pos2, mask); else if(header.data_type == envi_header::float64) return ((bsq*)file)->ph_to_ph((double*)result, lb1, rb1, pos1, lb2, rb2, pos2, mask); else std::cout<<"envi::ph_to_ph ERROR - unidentified data type"<*)file)->ph_to_ph((float*)result, lb1, rb1, pos1, lb2, rb2, pos2, mask); else if(header.data_type == envi_header::float64) return ((bil*)file)->ph_to_ph((double*)result, lb1, rb1, pos1, lb2, rb2, pos2, mask); else std::cout<<"envi::ph_to_ph ERROR - unidentified data type"<*)file)->ph_to_ph((float*)result, lb1, rb1, pos1, lb2, rb2, pos2, mask); else if(header.data_type == envi_header::float64) return ((bip*)file)->ph_to_ph((double*)result, lb1, rb1, pos1, lb2, rb2, pos2, mask); else std::cout<<"envi::ph_to_ph ERROR - unidentified data type"<*)file)->pa_to_ph((float*)result, lb1, rb1, lab1, rab1, lb2, rb2, pos, mask); else if(header.data_type == envi_header::float64) return ((bsq*)file)->pa_to_ph((double*)result, lb1, rb1, lab1, rab1, lb2, rb2, pos, mask); else std::cout<<"ERROR: unidentified data type"<*)file)->pa_to_ph((float*)result, lb1, rb1, lab1, rab1, lb2, rb2, pos, mask); else if(header.data_type == envi_header::float64) return ((bil*)file)->pa_to_ph((double*)result, lb1, rb1, lab1, rab1, lb2, rb2, pos, mask); else std::cout<<"ERROR: unidentified data type"<*)file)->pa_to_ph((float*)result, lb1, rb1, lab1, rab1, lb2, rb2, pos, mask); else if(header.data_type == envi_header::float64) return ((bip*)file)->pa_to_ph((double*)result, lb1, rb1, lab1, rab1, lb2, rb2, pos, mask); else std::cout<<"ERROR: unidentified data type"<*)file)->pa_to_pa((float*)result, lb1, rb1, lab1, rab1, lb2, rb2, lab2, rab2, mask); else if(header.data_type == envi_header::float64) return ((bsq*)file)->pa_to_pa((double*)result, lb1, rb1, lab1, rab1, lb2, rb2, lab2, rab2, mask); else std::cout<<"ERROR: unidentified data type"<*)file)->pa_to_pa((float*)result, lb1, rb1, lab1, rab1, lb2, rb2, lab2, rab2, mask); else if(header.data_type == envi_header::float64) return ((bil*)file)->pa_to_pa((double*)result, lb1, rb1, lab1, rab1, lb2, rb2, lab2, rab2, mask); else std::cout<<"ERROR: unidentified data type"<*)file)->pa_to_pa((float*)result, lb1, rb1, lab1, rab1, lb2, rb2, lab2, rab2, mask); else if(header.data_type == envi_header::float64) return ((bip*)file)->pa_to_pa((double*)result, lb1, rb1, lab1, rab1, lb2, rb2, lab2, rab2, mask); else std::cout<<"ERROR: unidentified data type"<*)file)->centroid((float*)result, lb1, rb1, lab1, rab1, mask); else if(header.data_type == envi_header::float64) return ((bsq*)file)->centroid((double*)result, lb1, rb1, lab1, rab1, mask); else std::cout<<"ERROR: unidentified data type"<*)file)->centroid((float*)result, lb1, rb1, lab1, rab1, mask); else if(header.data_type == envi_header::float64) return ((bil*)file)->centroid((double*)result, lb1, rb1, lab1, rab1, mask); else std::cout<<"ERROR: unidentified data type"<*)file)->centroid((float*)result, lb1, rb1, lab1, rab1, mask); else if(header.data_type == envi_header::float64) return ((bip*)file)->centroid((double*)result, lb1, rb1, lab1, rab1, mask); else std::cout<<"ERROR: unidentified data type"<*)file)->close(); else if(header.data_type == envi_header::float64) ((bsq*)file)->close(); else{ std::cout<<"ERROR: unidentified data type"<*)file)->close(); else if(header.data_type == envi_header::float64) ((bil*)file)->close(); else{ std::cout<<"ERROR: unidentified data type"<*)file)->close(); else if(header.data_type == envi_header::float64) ((bip*)file)->close(); else{ std::cout<<"ERROR: unidentified data type"<*)file)->pixel((float*)p, n); else if(header.data_type == envi_header::float64) return ((bsq*)file)->pixel((double*)p, n); else{ std::cout<<"ERROR: unidentified data type"<*)file)->pixel((float*)p, n); else if(header.data_type == envi_header::float64) return ((bil*)file)->pixel((double*)p, n); else{ std::cout<<"ERROR: unidentified data type"<*)file)->pixel((float*)p, n); else if(header.data_type == envi_header::float64) return ((bip*)file)->pixel((double*)p, n); else{ std::cout<<"ERROR: unidentified data type"<*)file)->band((float*)ptr, wavelength, PROGRESS); else if (header.data_type == envi_header::float64) return ((bsq*)file)->band((double*)ptr, wavelength, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } else if (header.interleave == envi_header::BIL){ if (header.data_type == envi_header::float32) return ((bil*)file)->band((float*)ptr, wavelength, PROGRESS); else if (header.data_type == envi_header::float64) return ((bil*)file)->band((double*)ptr, wavelength, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } else if (header.interleave == envi_header::BIP){ if (header.data_type == envi_header::float32) return ((bip*)file)->band((float*)ptr, wavelength, PROGRESS); else if (header.data_type == envi_header::float64) return ((bip*)file)->band((double*)ptr, wavelength, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } return false; } void band_bounds(double wavelength, size_t& low, size_t& high) { if (header.interleave == envi_header::BSQ) { //if the infile is bsq file if (header.data_type == envi_header::float32) ((bsq*)file)->band_bounds(wavelength, low, high); else if (header.data_type == envi_header::float64) ((bsq*)file)->band_bounds(wavelength, low, high); else { std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } else if (header.interleave == envi_header::BIL) { if (header.data_type == envi_header::float32) ((bil*)file)->band_bounds(wavelength, low, high); else if (header.data_type == envi_header::float64) ((bil*)file)->band_bounds(wavelength, low, high); else { std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } else if (header.interleave == envi_header::BIP) { if (header.data_type == envi_header::float32) ((bip*)file)->band_bounds(wavelength, low, high); else if (header.data_type == envi_header::float64) ((bip*)file)->band_bounds(wavelength, low, high); else { std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } } // Retrieve a spectrum at the specified 1D location /// @param ptr is a pointer to pre-allocated memory of size B*sizeof(T) /// @param x is the 1D coordinate of the spectrum template void spectrum(T* ptr, size_t n, bool PROGRESS = false){ void* temp = alloc_array(header.bands); //allocate space for the output array if(header.interleave == envi_header::BSQ){ //if the infile is bsq file if(header.data_type ==envi_header::float32){ ((bsq*)file)->spectrum((float*)temp, n, PROGRESS); cast(ptr, (float*)temp, header.bands); } else if (header.data_type == envi_header::float64){ ((bsq*)file)->spectrum((double*)temp, n, PROGRESS); cast(ptr, (double*)temp, header.bands); } else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } else if (header.interleave == envi_header::BIL){ if (header.data_type == envi_header::float32){ ((bil*)file)->spectrum((float*)temp, n, PROGRESS); cast(ptr, (float*)temp, header.bands); } else if (header.data_type == envi_header::float64){ ((bil*)file)->spectrum((double*)temp, n, PROGRESS); cast(ptr, (double*)temp, header.bands); } else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } else if (header.interleave == envi_header::BIP){ if (header.data_type == envi_header::float32){ ((bip*)file)->spectrum((float*)temp, n, PROGRESS); float test = ((float*)temp)[0]; cast(ptr, (float*)temp, header.bands); } else if (header.data_type == envi_header::float64){ ((bip*)file)->spectrum((double*)temp, n, PROGRESS); cast(ptr, (double*)temp, header.bands); } else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } free(temp); } /// Retrieve a spectrum from the specified (x, y) location /// @param ptr is a pointer to pre-allocated memory of size B*sizeof(T) /// @param x is the x-coordinate of the spectrum /// @param y is the y-coordinate of the spectrum template void spectrum(T* ptr, size_t x, size_t y, bool PROGRESS = false){ spectrum(ptr, y * header.samples + x, PROGRESS); } /// Retrieve a single band (based on index) and stores it in pre-allocated memory. /// @param p is a pointer to an allocated region of memory at least X * Y * sizeof(T) in size. /// @param page <= B is the integer number of the band to be copied. bool band_index(void* ptr, unsigned long long b){ if (header.interleave == envi_header::BSQ){ //if the infile is bsq file if (header.data_type == envi_header::float32) return ((bsq*)file)->band_index((float*)ptr, b); else if (header.data_type == envi_header::float64) return ((bsq*)file)->band_index((double*)ptr, b); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } else if (header.interleave == envi_header::BIL){ if (header.data_type == envi_header::float32) return ((bil*)file)->band_index((float*)ptr, b); else if (header.data_type == envi_header::float64) return ((bil*)file)->band_index((double*)ptr, b); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } else if (header.interleave == envi_header::BIP){ if (header.data_type == envi_header::float32) return ((bip*)file)->band_index((float*)ptr, b); else if (header.data_type == envi_header::float64) return ((bip*)file)->band_index((double*)ptr, b); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } return false; } /// Calculate the mean value for all masked (or valid) pixels in a band and returns the average spectrum /// @param p is a pointer to pre-allocated memory of size [B * sizeof(T)] that stores the mean spectrum /// @param mask is a pointer to memory of size [X * Y] that stores the mask value at each pixel location bool mean_spectrum(double * p, double* std, unsigned char* mask, bool PROGRESS = false){ if (header.interleave == envi_header::BSQ){ if (header.data_type == envi_header::float32) return ((bsq*)file)->mean_spectrum(p, std, mask, PROGRESS); else if (header.data_type == envi_header::float64) return ((bsq*)file)->mean_spectrum(p, std, mask, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } else if (header.interleave == envi_header::BIL){ if (header.data_type == envi_header::float32) return ((bil*)file)->mean_spectrum(p, std, mask, PROGRESS); else if (header.data_type == envi_header::float64) return ((bil*)file)->mean_spectrum(p, std, mask, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } else if (header.interleave == envi_header::BIP){ if (header.data_type == envi_header::float32) return ((bip*)file)->mean_spectrum(p, std, mask, PROGRESS); else if (header.data_type == envi_header::float64) return ((bip*)file)->mean_spectrum(p, std, mask, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } return false; } /// Calculate the mean value for all masked (or valid) pixels in a band and returns the average spectrum /// @param p is a pointer to pre-allocated memory of size [B * sizeof(T)] that stores the mean spectrum /// @param mask is a pointer to memory of size [X * Y] that stores the mask value at each pixel location bool median_spectrum(double* m, unsigned char* mask, bool PROGRESS = false){ if (header.interleave == envi_header::BSQ){ if (header.data_type == envi_header::float32) return ((bsq*)file)->median_spectrum(m, mask, PROGRESS); else if (header.data_type == envi_header::float64) return ((bsq*)file)->median_spectrum(m, mask, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } else{ std::cout<<"ERROR: median calculation is only supported for BSQ interleave types. Convert to process."<*)file)->co_matrix(co, avg, mask, cuda_device, PROGRESS); else if (header.data_type == envi_header::float64) return ((bil*)file)->co_matrix(co, avg, mask, cuda_device, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } else if (header.interleave == envi_header::BIP){ if (header.data_type == envi_header::float32) return ((bip*)file)->co_matrix(co, avg, mask, cuda_device, PROGRESS); else if (header.data_type == envi_header::float64) return ((bip*)file)->co_matrix(co, avg, mask, cuda_device, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } return false; } /// Calculate the covariance of noise matrix for all masked pixels in the image. /// @param co is a pointer to pre-allocated memory of size [B * B] that stores the resulting covariance matrix /// @param avg is a pointer to memory of size B that stores the average spectrum /// @param mask is a pointer to memory of size [X * Y] that stores the mask value at each pixel location bool coNoise_matrix(double* coN, double* avg, unsigned char* mask, int cuda_device = 0, bool PROGRESS = false){ if (header.interleave == envi_header::BSQ){ std::cout<<"ERROR: calculating the covariance matrix of noise for a BSQ file is impractical; convert to BIP first"<*)file)->coNoise_matrix(coN, avg, mask, cuda_device, PROGRESS); else if (header.data_type == envi_header::float64) return ((bip*)file)->coNoise_matrix(coN, avg, mask, cuda_device, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } return false; } /// Crop a region of the image and save it to a new file. /// @param outfile is the file name for the new cropped image /// @param x0 is the lower-left x pixel coordinate to be included in the cropped image /// @param y0 is the lower-left y pixel coordinate to be included in the cropped image /// @param x1 is the upper-right x pixel coordinate to be included in the cropped image /// @param y1 is the upper-right y pixel coordinate to be included in the cropped image bool crop(std::string outfile, unsigned long long x0, unsigned long long y0, unsigned long long x1, unsigned long long y1, unsigned long long b0, unsigned long long b1, bool PROGRESS = false){ //save the header for the cropped file stim::envi_header new_header = header; new_header.samples = x1 - x0 + 1; new_header.lines = y1 - y0 + 1; new_header.bands = b1 - b0 + 1; std::vector::const_iterator first = new_header.wavelength.begin() + b0; std::vector::const_iterator last = new_header.wavelength.begin() + b1 + 1; new_header.wavelength = std::vector(first, last); new_header.save(outfile + ".hdr"); if (header.interleave == envi_header::BSQ){ if (header.data_type == envi_header::float32) return ((bsq*)file)->crop(outfile, x0, y0, x1, y1, b0, b1, PROGRESS); else if (header.data_type == envi_header::float64) return ((bsq*)file)->crop(outfile, x0, y0, x1, y1, b0, b1, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } else if (header.interleave == envi_header::BIL){ if (header.data_type == envi_header::float32) return ((bil*)file)->crop(outfile, x0, y0, x1, y1, b0, b1, PROGRESS); else if (header.data_type == envi_header::float64) return ((bil*)file)->crop(outfile, x0, y0, x1, y1, b0, b1, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } else if (header.interleave == envi_header::BIP){ if (header.data_type == envi_header::float32) return ((bip*)file)->crop(outfile, x0, y0, x1, y1, b0, b1, PROGRESS); else if (header.data_type == envi_header::float64) return ((bip*)file)->crop(outfile, x0, y0, x1, y1, b0, b1, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } return false; } void subimages(std::string outfile, size_t nx, size_t ny, unsigned char* mask, bool PROGRESS = false){ size_t nnz = 0; //initialize the number of subimages to zero for(size_t i = 0; i < header.lines * header.samples; i++) //for each pixel in the mask if(mask[i]) nnz++; //if the pixel is valid, add a subimage //save the header for the cropped file stim::envi_header new_header = header; new_header.samples = nx; //calculate the width of the output image (concatenated subimages) new_header.lines = nnz * ny; //calculate the height of the output image (height of subimages) if (header.interleave == envi_header::BSQ){ if (header.data_type == envi_header::float32) ((bsq*)file)->subimages(outfile, nx, ny, mask, PROGRESS); else if (header.data_type == envi_header::float64) ((bsq*)file)->subimages(outfile, nx, ny, mask, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } else if (header.interleave == envi_header::BIL){ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } else if (header.interleave == envi_header::BIP){ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } new_header.save(outfile + ".hdr"); //save the header for the output file } /// Remove a list of bands from the ENVI file /// @param outfile is the file name for the output hyperspectral image (with trimmed bands) /// @param b is an array of bands to be eliminated void trim(std::string outfile, std::vector trimmed, bool PROGRESS = false){ envi_header h = header; h.bands = header.bands - trimmed.size(); //calculate the new number of bands if(header.wavelength.size() != 0) h.wavelength.resize(h.bands); if(header.band_names.size() != 0) h.band_names.resize(h.bands); size_t it = 0; //allocate an index into the trimmed bands array size_t i = 0; for(size_t b = 0; b < header.bands; b++){ //for each band if(b != trimmed[it]){ if(h.wavelength.size()) h.wavelength[i] = header.wavelength[b]; if(h.band_names.size()) h.band_names[i] = header.band_names[i]; i++; } else it++; } h.save(outfile + ".hdr"); if (header.interleave == envi_header::BSQ){ if (header.data_type == envi_header::float32) return ((bsq*)file)->trim(outfile, trimmed, PROGRESS); else if (header.data_type == envi_header::float64) return ((bsq*)file)->trim(outfile, trimmed, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } else if (header.interleave == envi_header::BIL){ if (header.data_type == envi_header::float32) return ((bil*)file)->trim(outfile, trimmed, PROGRESS); else if (header.data_type == envi_header::float64) return ((bil*)file)->trim(outfile, trimmed, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } else if (header.interleave == envi_header::BIP){ if (header.data_type == envi_header::float32) return ((bip*)file)->trim(outfile, trimmed, PROGRESS); else if (header.data_type == envi_header::float64) return ((bip*)file)->trim(outfile, trimmed, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } } /// Combine two ENVI images along the Y axis /// @param outfile is the combined file to be output /// @param C is the ENVI object for the image to be combined void combine(std::string outfile, envi C, long long x, long long y, bool PROGRESS = false){ envi_header h = header; long long left = std::min(0, x); //calculate the left edge of the final image long long right = std::max((long long)header.samples, C.header.samples + x); //calculate the right edge of the final image long long top = std::min(0, y); //calculate the top edge of the final image long long bottom = std::max((long long)header.lines, C.header.lines + y); //calculate the bottom edge of the final image h.samples = right - left; h.lines = bottom - top; h.save(outfile + ".hdr"); if (header.interleave == envi_header::BSQ){ if (header.data_type == envi_header::float32) ((bsq*)file)->combine(outfile, (bsq*)C.file, x, y, PROGRESS); else if (header.data_type == envi_header::float64) ((bsq*)file)->combine(outfile, (bsq*)C.file, x, y, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } else if (header.interleave == envi_header::BIL){ if (header.data_type == envi_header::float32) ((bil*)file)->combine(outfile, (bil*)C.file, x, y, PROGRESS); else if (header.data_type == envi_header::float64) ((bil*)file)->combine(outfile, (bil*)C.file, x, y, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } else if (header.interleave == envi_header::BIP){ if (header.data_type == envi_header::float32) ((bip*)file)->combine(outfile, (bip*)C.file, x, y, PROGRESS); else if (header.data_type == envi_header::float64) ((bip*)file)->combine(outfile, (bip*)C.file, x, y, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } } void append(std::string outfile, envi C, bool PROGRESS = false) { if (C.header.samples != header.samples || //verify that the images are the same size C.header.lines != header.lines) { std::cout << "ERROR - appended images must be the same size: input = [" << header.samples << " x " << header.lines << "], output = [" << C.header.samples << " x " << C.header.lines << "]" << std::endl; exit(1); } if (C.header.interleave != header.interleave) { std::cout << "ERROR - appended images must have the same interleave format" << std::endl; exit(1); } stim::envi_header new_header = header; //create a header for the output image new_header.bands = header.bands + C.header.bands; //calculate the number of bands in the new image if (header.wavelength.size() != 0 && C.header.wavelength.size() != 0) { //if both files contain wavelength information for (size_t b = 0; b < C.header.wavelength.size(); b++) new_header.wavelength.push_back(C.header.wavelength[b]); //append the wavelength labels to the new header array } else new_header.wavelength.clear(); if (header.band_names.size() != 0 && C.header.band_names.size() != 0) { //if both files contain band name information for (size_t b = 0; b < C.header.band_names.size(); b++) new_header.band_names.push_back(C.header.band_names[b]); //append the wavelength labels to the new header array } else new_header.wavelength.clear(); new_header.save(outfile + ".hdr"); //save the output if (header.interleave == envi_header::BSQ) { if (header.data_type == envi_header::float32) ((bsq*)file)->append(outfile, (bsq*)C.file, PROGRESS); else if (header.data_type == envi_header::float64) ((bsq*)file)->append(outfile, (bsq*)C.file, PROGRESS); else { std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } else if (header.interleave == envi_header::BIL) { if (header.data_type == envi_header::float32) ((bil*)file)->append(outfile, (bil*)C.file, PROGRESS); else if (header.data_type == envi_header::float64) ((bil*)file)->append(outfile, (bil*)C.file, PROGRESS); else { std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } else if (header.interleave == envi_header::BIP) { if (header.data_type == envi_header::float32) ((bip*)file)->append(outfile, (bip*)C.file, PROGRESS); else if (header.data_type == envi_header::float64) ((bip*)file)->append(outfile, (bip*)C.file, PROGRESS); else { std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } } /// Convolve the given band range with a kernel specified by a vector of coefficients. /// @param outfile is the combined file to be output /// @param c is an array of coefficients /// @param start is the band to start processing (the first coefficient starts here) /// @param nbands is the number of bands to process /// @param center is the index for the center coefficient for the kernel (used to set the wavelengths in the output file) void convolve(std::string outfile, std::vector C, size_t start, size_t end, size_t center = 0, unsigned char* mask = NULL, bool PROGRESS = false){ size_t nbands = end - start + 1; envi_header h = header; //copy the current header h.bands = nbands; //set the number of new bands if(header.wavelength.size() != 0){ h.wavelength.resize(nbands); //set the number of wavelengths to the number of bands for(size_t b = 0; b < nbands; b++) h.wavelength[b] = header.wavelength[b+center]; } if(header.band_names.size() != 0){ h.band_names.resize(nbands); for(size_t b = 0; b < nbands; b++) h.band_names[b] = header.band_names[b+center]; } h.save(outfile + ".hdr"); //save the new header if (header.interleave == envi_header::BSQ){ if (header.data_type == envi_header::float32) ((bsq*)file)->convolve(outfile, C, start, end, mask, PROGRESS); else if (header.data_type == envi_header::float64) ((bsq*)file)->convolve(outfile, C, start, end, mask, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } else if (header.interleave == envi_header::BIL){ if (header.data_type == envi_header::float32) ((bil*)file)->convolve(outfile, C, start, end, mask, PROGRESS); else if (header.data_type == envi_header::float64) ((bil*)file)->convolve(outfile, C, start, end, mask, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } else if (header.interleave == envi_header::BIP){ if (header.data_type == envi_header::float32) ((bip*)file)->convolve(outfile, C, start, end, mask, PROGRESS); else if (header.data_type == envi_header::float64) ((bip*)file)->convolve(outfile, C, start, end, mask, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } } /// Approximates the nth derivative of the spectra to the specified order /// @param outfile is the file where the derivative approximation will be saved /// @n is the derivative to be calculated /// @order is the order of the error (must be even) void deriv(std::string outfile, size_t d, size_t order, unsigned char* mask = NULL, bool PROGRESS = false){ header.save(outfile + ".hdr"); if (header.interleave == envi_header::BSQ){ if (header.data_type == envi_header::float32) ((bsq*)file)->deriv(outfile, d, order, header.wavelength, mask, PROGRESS); else if (header.data_type == envi_header::float64) ((bsq*)file)->deriv(outfile, d, order, header.wavelength, mask, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } else if (header.interleave == envi_header::BIL){ if (header.data_type == envi_header::float32) ((bil*)file)->deriv(outfile, d, order, header.wavelength, mask, PROGRESS); else if (header.data_type == envi_header::float64) ((bil*)file)->deriv(outfile, d, order, header.wavelength, mask, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } else if (header.interleave == envi_header::BIP){ if (header.data_type == envi_header::float32) ((bip*)file)->deriv(outfile, d, order, header.wavelength, mask, PROGRESS); else if (header.data_type == envi_header::float64) ((bip*)file)->deriv(outfile, d, order, header.wavelength, mask, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } exit(1); } void multiply(std::string outfile, double v, unsigned char* mask = NULL, bool PROGRESS = false){ header.save(outfile + ".hdr"); if (header.interleave == envi_header::BSQ){ if (header.data_type == envi_header::float32) ((bsq*)file)->multiply(outfile, v, mask, PROGRESS); else if (header.data_type == envi_header::float64) ((bsq*)file)->multiply(outfile, v, mask, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } else if (header.interleave == envi_header::BIL){ if (header.data_type == envi_header::float32) ((bil*)file)->multiply(outfile, v, mask, PROGRESS); else if (header.data_type == envi_header::float64) ((bil*)file)->multiply(outfile, v, mask, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } else if (header.interleave == envi_header::BIP){ if (header.data_type == envi_header::float32) ((bip*)file)->multiply(outfile, v, mask, PROGRESS); else if (header.data_type == envi_header::float64) ((bip*)file)->multiply(outfile, v, mask, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } exit(1); } void add(std::string outfile, double v, unsigned char* mask = NULL, bool PROGRESS = false){ header.save(outfile + ".hdr"); if (header.interleave == envi_header::BSQ){ if (header.data_type == envi_header::float32) ((bsq*)file)->add(outfile, v, mask, PROGRESS); else if (header.data_type == envi_header::float64) ((bsq*)file)->add(outfile, v, mask, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } else if (header.interleave == envi_header::BIL){ if (header.data_type == envi_header::float32) ((bil*)file)->add(outfile, v, mask, PROGRESS); else if (header.data_type == envi_header::float64) ((bil*)file)->add(outfile, v, mask, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } else if (header.interleave == envi_header::BIP){ if (header.data_type == envi_header::float32) ((bip*)file)->add(outfile, v, mask, PROGRESS); else if (header.data_type == envi_header::float64) ((bip*)file)->add(outfile, v, mask, PROGRESS); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } exit(1); } void fft(std::string outfile, double band_min, double band_max, size_t samples = 0, void* ratio = NULL, size_t rx = 0, size_t ry = 0, bool PROGRESS = false, int cuda_device = 0){ if(samples == 0) samples = header.bands; //double B = (double)header.bands; double delta = header.wavelength[1] - header.wavelength[0]; //calculate spacing in the current domain double span = samples * delta; //calculate the span in the current domain double fft_delta = 1.0 / span; //calculate the span in the FFT domain double fft_max = fft_delta * samples/2; //calculate the maximum range of the FFT if(band_max > fft_max) band_max = fft_max; //the user gave a band outside of the FFT range, reset the band to the maximum available size_t start_i = (size_t)std::ceil(band_min / fft_delta); //calculate the first band to store size_t size_i = (size_t)std::floor(band_max / fft_delta) - start_i + 1; //calculate the number of bands to store size_t end_i = start_i + size_i - 1; //last band number envi_header new_header = header; new_header.bands = size_i; new_header.set_wavelengths(start_i * fft_delta, fft_delta); new_header.wavelength_units = "inv_" + header.wavelength_units; new_header.save(outfile + ".hdr"); if (header.interleave == envi_header::BIP){ if (header.data_type == envi_header::float32) ((bip*)file)->fft(outfile, start_i, end_i, samples, (float*)ratio, rx, ry, PROGRESS, cuda_device); else if (header.data_type == envi_header::float64) ((bip*)file)->fft(outfile, start_i, end_i, samples, (double*)ratio, rx, ry, PROGRESS, cuda_device); else{ std::cout << "ERROR: unidentified data type" << std::endl; exit(1); } } else{ std::cout<<"ERROR: only BIP files supported for FFT"<