#ifndef STIM_BIL_H #define STIM_BIL_H #include "../envi/envi_header.h" #include "../envi/binary.h" #include #include namespace rts{ template class bil: public binary { protected: std::vector w; //band wavelength public: using binary::open; using binary::file; using binary::R; //open a file, given the file and its header's names bool open(std::string filename, unsigned int X, unsigned int Y, unsigned int B, unsigned int header_offset, std::vector wavelengths){ w = wavelengths; return open(filename, vec(X, Y, B), header_offset); return false; } //save one band of the file into the memory, and return the pointer bool band_index( T * p, unsigned int page){ unsigned int L = R[0] * sizeof(T); //caculate the number of bytes in a sample line unsigned int jump = R[0] * (R[2] - 1) * sizeof(T); if (page >= R[2]){ //make sure the bank number is right std::cout<<"ERROR: page out of range"< wavelength ){ band_index(p, page); return true; } while( w[page] < wavelength ) { page++; //if wavelength is larger than the last wavelength in header file if (page == R[2]) { band_index(p, R[2]-1); return true; } } if ( wavelength < w[page] ) { p1=(T*)malloc(S); //memory allocation p2=(T*)malloc(S); band_index(p1, page - 1); band_index(p2, page ); for(unsigned i=0; i < XY; i++){ double r = (double) (wavelength - w[page-1]) / (double) (w[page] - w[page-1]); p[i] = (p2[i] - p1[i]) * r + p1[i]; } } else //if the wavelength is equal to a wavelength in header file { band_index(p, page); } return true; } //get YZ line from the a Y slice, Y slice data should be already IN the MEMORY bool getYZ(T* p, T* c, double wavelength) { unsigned int X = R[0]; //calculate the number of pixels in a sample unsigned int B = R[2]; unsigned int L = X * sizeof(T); unsigned page=0; //samples around the wavelength T * p1; T * p2; //get the bands numbers around the wavelength //if wavelength is smaller than the first one in header file if ( w[page] > wavelength ){ memcpy(p, c, L); return true; } while( w[page] < wavelength ) { page++; //if wavelength is larger than the last wavelength in header file if (page == B) { memcpy(p, c + (B - 1) * X, L); return true; } } if ( wavelength < w[page] ) { p1=(T*)malloc( L ); //memory allocation p2=(T*)malloc( L ); memcpy(p1, c + (page - 1) * X, L); memcpy(p2, c + page * X, L); for(unsigned i=0; i < X; i++){ double r = (double) (wavelength - w[page-1]) / (double) (w[page] - w[page-1]); p[i] = (p2[i] - p1[i]) * r + p1[i]; } } else //if the wavelength is equal to a wavelength in header file memcpy(p, c + page * X, L); return true; } //save one pixel of the BIP file into the memory, and return the pointer bool spectrum(T * p, unsigned x, unsigned y){ if ( x >= R[0] || y >= R[1]){ //make sure the sample and line number is right std::cout<<"ERROR: sample or line out of range"<= R[1]){ //make sure the line number is right std::cout<<"ERROR: line out of range"< wls){ unsigned N = wls.size(); //get the number of baseline points std::ofstream target(outname.c_str(), std::ios::binary); //open the target binary file std::string headername = outname + ".hdr"; //the header file name //simplify image resolution unsigned int ZX = R[2] * R[0]; //calculate the number of points in a Y slice unsigned int L = ZX * sizeof(T); //calculate the number of bytes of a Y slice unsigned int B = R[2]; unsigned int X = R[0]; T* c; //pointer to the current Y slice c = (T*)malloc(L); //memory allocation T* a; //pointer to the two YZ lines surrounding the current YZ line T* b; a = (T*)malloc(X * sizeof(T)); b = (T*)malloc(X * sizeof(T)); double ai, bi; //stores the two baseline points wavelength surrounding the current band double ci; //stores the current band's wavelength unsigned control; if (a == NULL || b == NULL || c == NULL){ std::cout<<"ERROR: error allocating memory"; exit(1); } // loop start correct every y slice for (unsigned k =0; k < R[1]; k++) { //get the current y slice getY(c, k); //initialize lownum, highnum, low, high ai = w[0]; control=0; //if no baseline point is specified at band 0, //set the baseline point at band 0 to 0 if(wls[0] != w[0]){ bi = wls[control]; memset(a, (char)0, X * sizeof(T) ); } //else get the low band else{ control++; getYZ(a, c, ai); bi = wls[control]; } //get the high band getYZ(b, c, bi); //correct every YZ line for(unsigned cii = 0; cii < B; cii++){ //update baseline points, if necessary if( w[cii] >= bi && cii != B - 1) { //if the high band is now on the last BL point if (control != N-1) { control++; //increment the index std::swap(a, b); //swap the baseline band pointers ai = bi; bi = wls[control]; getYZ(b, c, bi); } //if the last BL point on the last band of the file? else if ( wls[control] < w[B - 1]) { std::swap(a, b); //swap the baseline band pointers memset(b, (char)0, X * sizeof(T) ); //clear the high band ai = bi; bi = w[B - 1]; } } ci = w[cii]; unsigned jump = cii * X; //perform the baseline correction for(unsigned i=0; i < X; i++) { double r = (double) (ci - ai) / (double) (bi - ai); c[i + jump] =(T) ( c[i + jump] - (b[i] - a[i]) * r - a[i] ); } }//loop for YZ line end target.write(reinterpret_cast(c), L); //write the corrected data into destination }//loop for Y slice end free(a); free(b); free(c); target.close(); return true; } // normalize the BIL file bool normalize(std::string outname, double w) { unsigned int B = R[2]; //calculate the number of bands unsigned int Y = R[1]; unsigned int X = R[0]; unsigned int ZX = R[2] * R[0]; unsigned int XY = R[0] * R[1]; //calculate the number of pixels in a band unsigned int S = XY * sizeof(T); //calculate the number of bytes in a band unsigned int L = ZX * sizeof(T); std::ofstream target(outname.c_str(), std::ios::binary); //open the target binary file std::string headername = outname + ".hdr"; //the header file name T * c; //pointer to the current ZX slice T * b; //pointer to the standard band b = (T*)malloc( S ); //memory allocation c = (T*)malloc( L ); band(b, w); //get the certain band into memory for(unsigned j = 0; j < Y; j++) { getY(c, j); for(unsigned i = 0; i < B; i++) { for(unsigned m = 0; m < X; m++) { c[m + i * X] = c[m + i * X] / b[m + j * X]; } } target.write(reinterpret_cast(c), L); //write normalized data into destination } free(b); free(c); target.close(); return true; } //convert BIL file to BSQ file and save it bool bsq(std::string outname) { unsigned int S = R[0] * R[1] * sizeof(T); //calculate the number of bytes in a band std::ofstream target(outname.c_str(), std::ios::binary); std::string headername = outname + ".hdr"; T * p; //pointer to the current band p = (T*)malloc(S); for ( unsigned i = 0; i < R[2]; i++) { band_index(p, i); target.write(reinterpret_cast(p), S); //write a band data into target file } free(p); target.close(); return true; } //convert bil file to bip file and save it bool bip(std::string outname) { unsigned int S = R[0] * R[2] * sizeof(T); //calculate the number of bytes in a ZX slice std::ofstream target(outname.c_str(), std::ios::binary); std::string headername = outname + ".hdr"; T * p; //pointer to the current XZ slice for bil file p = (T*)malloc(S); T * q; //pointer to the current ZX slice for bip file q = (T*)malloc(S); for ( unsigned i = 0; i < R[1]; i++) { getY(p, i); for ( unsigned k = 0; k < R[2]; k++) { unsigned ks = k * R[0]; for ( unsigned j = 0; j < R[0]; j++) q[k + j * R[2]] = p[ks + j]; } target.write(reinterpret_cast(q), S); //write a band data into target file } free(p); free(q); target.close(); return true; } //providing the left and the right bound data, return baseline-corrected band height bool baseline_band(double lb, double rb, T* lp, T* rp, double wavelength, T* result){ unsigned XY = R[0] * R[1]; band(result, wavelength); //get band //perform the baseline correction double r = (double) (wavelength - lb) / (double) (rb - lb); for(unsigned i=0; i < XY; i++){ result[i] =(T) (result[i] - (rp[i] - lp[i]) * r - lp[i] ); } return true; } //untested //providing the left and the right bound wavelength, return baseline-corrected band height bool height(double lb, double rb, double bandwavelength){ T* lp; T* rp; T* result; lp = (T*) malloc(sizeof(R[0] * R[1] * sizeof(T))); //memory allocation rp = (T*) malloc(sizeof(R[0] * R[1] * sizeof(T))); heigth = (T*) malloc(sizeof(R[0] * R[1] * sizeof(T))); band(lp, lb); //get the data of the left bounbd and the right bound band(rp, rb); baseline_band(lb, rb, lp, rp, bandwavelength, result); return true; } //untested //calculate the area between two bound point(including baseline correction) bool area(double lb, double rb){ T* lp; //left band pointer T* rp; //right band pointer T* cur; //current band 1 T* cur2; //current band 2 T* result; //area result unsigned XY = R[0] * R[1]; unsigned S = XY * sizeof(T); lp = (T*) malloc(S); //memory allocation rp = (T*) malloc(S); cur = (T*) malloc(S); cur2 = (T*) malloc(S); result = (T*) malloc(S); memset(result, (char)0, S); //find the wavelenght position in the whole band unsigned int n = w.size(); unsigned int ai = 0; //left bound position unsigned int bi = n - 1; //right bound position //to make sure the left and the right bound are in the bandwidth if (lb < w[0] || rb < w[0] || lb > w[n-1] || rb >w[n-1]){ std::cout<<"ERROR: left bound or right bound out of bandwidth"< rb){ std::cout<<"ERROR: right bound should be bigger than left bound"<= w[ai]){ ai++; } while (rb <= w[bi]){ bi--; } band(lp, lb); band(rp, rb); //calculate the beginning and the ending part baseline_band(lb, rb, lp, rp, w[bi], cur); //ending part for(unsigned j = 0; j < XY; j++){ result[j] += (rb - w[bi]) * cur[j] / 2.0; } baseline_band(lb, rb, lp, rp, w[ai], cur); //beginnning part for(unsigned j = 0; j < XY; j++){ result[j] += (w[ai] - lb) * cur[j] / 2.0; } //calculate the area ai++; for(unsigned i = ai; i <= bi ;i++) { baseline_band(lb, rb, lp, rp, w[ai], cur2); for(unsigned j = 0; j < XY; j++) { result[j] += (w[ai] - w[ai-1]) * (cur[j] + cur2[j]) / 2.0; } std::swap(cur,cur2); //swap the band pointers } ///////////////for testing use std::ofstream text("area_result.txt",std::ios::out); for (unsigned i = 0; i < 640; i++) { for (unsigned j = 0; j < 384; j++) { text<