#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; } //create mask file bool mask(unsigned char* p, double mask_band, double threshold){ T* temp = (T*)malloc(R[0] * R[1] * sizeof(T)); //allocate memory for the certain band band(temp, mask_band); for (unsigned int i = 0; i < R[0] * R[1]; i++) { if (temp[i] < threshold) p[i] = 0; else p[i] = 255; } return true; } //close the file bool close(){ file.close(); return true; } }; } #endif