From e8eb202fd18514f4a6ecb0e7343d9c3c0060cbc0 Mon Sep 17 00:00:00 2001 From: David Mayerich Date: Wed, 8 Oct 2014 17:08:27 -0500 Subject: [PATCH] added a new ENVI interface --- envi/bil.h | 8 ++++---- envi/binary.h | 2 +- envi/bip.h | 11 ++++++++--- envi/bsq.h | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------------------- envi/envi.h | 484 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- envi/envi_header.h | 164 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------------------------------------------------------- 6 files changed, 226 insertions(+), 536 deletions(-) diff --git a/envi/bil.h b/envi/bil.h index bd4186a..b5c0715 100644 --- a/envi/bil.h +++ b/envi/bil.h @@ -1,7 +1,7 @@ #ifndef STIM_BIL_H #define STIM_BIL_H -#include "../envi/envi.h" +#include "../envi/envi_header.h" #include "../envi/binary.h" #include #include @@ -14,7 +14,7 @@ class bil: public binary { protected: - envi header; + envi_header header; public: @@ -353,7 +353,7 @@ public: target.write(reinterpret_cast(p), S); //write a band data into target file } - header.interleave = rts::envi::BSQ; //change the type of file in header file + header.interleave = rts::envi_header::BSQ; //change the type of file in header file header.save(headername); free(p); @@ -387,7 +387,7 @@ public: target.write(reinterpret_cast(q), S); //write a band data into target file } - header.interleave = rts::envi::BIP; //change the type of file in header file + header.interleave = rts::envi_header::BIP; //change the type of file in header file header.save(headername); free(p); diff --git a/envi/binary.h b/envi/binary.h index 7008ff9..f01fa42 100644 --- a/envi/binary.h +++ b/envi/binary.h @@ -3,7 +3,7 @@ #ifndef RTS_BINARY_H #define RTS_BINARY_H -#include "../envi/envi.h" +#include "../envi/envi_header.h" #include "../math/vector.h" #include #include diff --git a/envi/bip.h b/envi/bip.h index 8a1e1c2..b2541fb 100644 --- a/envi/bip.h +++ b/envi/bip.h @@ -1,4 +1,7 @@ -#include "../envi/envi.h" +#ifndef STIM_BIP_H +#define STIM_BIP_H + +#include "../envi/envi_header.h" #include "../envi/bil.h" #include "../envi/binary.h" #include @@ -12,7 +15,7 @@ class bip: public binary { protected: - envi header; + envi_header header; public: @@ -463,7 +466,7 @@ public: target.write(reinterpret_cast(q), S); //write a band data into target file } - header.interleave = rts::envi::BIL; //change the type of file in header file + header.interleave = rts::envi_header::BIL; //change the type of file in header file header.save(headername); free(p); @@ -480,3 +483,5 @@ public: }; } + +#endif diff --git a/envi/bsq.h b/envi/bsq.h index fc69d37..4a9140b 100644 --- a/envi/bsq.h +++ b/envi/bsq.h @@ -1,7 +1,12 @@ -#include "../envi/envi.h" +#ifndef STIM_BSQ_H +#define STIM_BSQ_H + +#include "../envi/envi_header.h" #include "../envi/binary.h" +#include "../envi/bil.h" #include #include +#include namespace rts{ @@ -11,31 +16,38 @@ class bsq: public binary { protected: - envi header; + //envi_header header; + + std::vector w; //band wavelengths public: using binary::open; using binary::file; using binary::getSlice; + using binary::R; //open a file, given the file and its header's names - bool open(std::string filename, std::string headername){ + bool open(std::string filename, unsigned int X, unsigned int Y, unsigned int B, unsigned int header_offset, std::vector wavelengths){ - if (header.load(headername)==false){ + /*if (header.load(headername)==false){ std::cout<<"ERROR: unable to load header file: "<(header.samples, header.lines, header.bands), header.header_offset); - return true; + //copy the wavelengths to the BSQ file structure + 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){ - if (page >= header.bands){ //make sure the bank number is right + if (page >= R[2]){ //make sure the bank number is right std::cout<<"ERROR: page out of range"< wavelength ){ + if ( w[page] > wavelength ){ band_index(p, page); return true; } - while( header.wavelength[page] < wavelength ) + while( w[page] < wavelength ) { page++; //if wavelength is larger than the last wavelength in header file - if (page == header.bands) { - getSlice(p, 2, header.bands-1); + if (page == R[2]) { + getSlice(p, 2, R[2]-1); return true; } } - if ( wavelength < header.wavelength[page] ) + if ( wavelength < w[page] ) { p1=(T*)malloc( XY * sizeof(T)); //memory allocation p2=(T*)malloc( XY * sizeof(T)); band_index(p1, page - 1); band_index(p2, page ); for(unsigned i=0; i < XY; i++){ - double r = (double) (wavelength - header.wavelength[page-1]) / (double) (header.wavelength[page] - header.wavelength[page-1]); + double r = (double) (wavelength - w[page-1]) / (double) (w[page] - w[page-1]); p[i] = (p2[i] - p1[i]) * r + p1[i]; } } @@ -93,16 +105,16 @@ public: unsigned int i; - if ( x >= header.samples || y >= header.lines){ //make sure the sample and line number is right + 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"<= bi && cii != B - 1) { + if( w[cii] >= bi && cii != B - 1) { //if the high band is now on the last BL point? if (control != N-1) { @@ -177,20 +189,20 @@ public: } //if the last BL point on the last band of the file? - else if ( wls[control] < header.wavelength[B - 1]) { + else if ( wls[control] < w[B - 1]) { std::swap(a, b); //swap the baseline band pointers memset(b, (char)0, S); //clear the high band ai = bi; - bi = header.wavelength[B - 1]; + bi = w[B - 1]; } } //get the current band band_index(c, cii); - ci = header.wavelength[cii]; + ci = w[cii]; //perform the baseline correction for(unsigned i=0; i < XY; i++){ @@ -202,7 +214,7 @@ public: } - header.save(headername); //save the new header file + //header.save(headername); //save the new header file free(a); free(b); @@ -214,8 +226,9 @@ public: // normalize the BSQ file bool normalize(std::string outname, double band) { - unsigned int B = header.bands; //calculate the number of bands - unsigned int XY = header.samples * header.lines; //calculate the number of pixels in a band + std::cout<<"NORMALIZE A BSQ FILE"<(c), S); //write normalized data into destination } - header.save(headername); //save the new header file + //header.save(headername); //save the new header file free(b); free(c); @@ -272,8 +285,8 @@ public: bool bil(std::string outname) { //simplify image resolution - unsigned int L = header.samples * header.bands * sizeof(T); //calculate the number of bytes of a ZX slice - unsigned int jump = (header.lines - 1) * header.samples * sizeof(T); + unsigned int L = R[0] * R[1] * sizeof(T); //calculate the number of bytes of a ZX slice + unsigned int jump = (R[1] - 1) * R[0] * sizeof(T); std::ofstream target(outname.c_str(), std::ios::binary); std::string headername = outname + ".hdr"; @@ -281,18 +294,18 @@ public: T * p; //pointer to the current spectrum p = (T*)malloc(L); - for ( unsigned i = 0; i < header.lines; i++) + for ( unsigned i = 0; i < R[1]; i++) { - file.seekg(header.samples * i * sizeof(T), std::ios::beg); - for ( unsigned j = 0; j < header.bands; j++ ) + file.seekg(R[0] * i * sizeof(T), std::ios::beg); + for ( unsigned j = 0; j < R[2]; j++ ) { - file.read((char *)(p + j * header.samples), sizeof(T) * header.samples); + file.read((char *)(p + j * R[0]), sizeof(T) * R[0]); file.seekg(jump, std::ios::cur); //go to the next band } target.write(reinterpret_cast(p), L); //write XZ slice data into target file } - header.interleave = rts::envi::BIL; //change the type of file in header file - header.save(headername); + //header.interleave = rts::envi_header::BIL; //change the type of file in header file + //header.save(headername); free(p); target.close(); @@ -308,4 +321,6 @@ public: }; } +#endif + diff --git a/envi/envi.h b/envi/envi.h index b0775a3..671692a 100644 --- a/envi/envi.h +++ b/envi/envi.h @@ -1,409 +1,75 @@ -#ifndef ENVI_HEADER_H -#define ENVI_HEADER_H - -#include -#include -#include -#include -#include -#include - -//information from an ENVI header file -//A good resource can be found here: http://www.exelisvis.com/docs/enviheaderfiles.html - -namespace rts{ - -struct envi -{ - enum dataType {dummy0, int8, int16, int32, float32, float64, complex32, dummy7, dummy8, complex64, dummy10, dummy11, uint16, uint32, int64, uint64}; - enum interleaveType {BIP, BIL, BSQ}; //bip = Z,X,Y; bil = X,Z,Y; bsq = X,Y,Z - enum endianType {endianLittle, endianBig}; - - std::string name; - - std::string description; - - unsigned int samples; //x-axis - unsigned int lines; //y-axis - unsigned int bands; //spectral axis - unsigned int header_offset; //header offset for binary file (in bytes) - std::string file_type; //should be "ENVI Standard" - - envi::dataType data_type; //data representation; common value is 4 (32-bit float) - - - envi::interleaveType interleave; - - std::string sensor_type; //not really used - - envi::endianType byte_order; //little = least significant bit first (most systems) - - double x_start, y_start; //coordinates of the upper-left corner of the image - std::string wavelength_units; //stored wavelength units - std::string z_plot_titles[2]; - - double pixel_size[2]; //pixel size along X and Y - - std::vector band_names; //name for each band in the image - std::vector wavelength; //wavelength for each band - - void init(){ - name = ""; - - //specify default values for a new or empty ENVI file - samples = 0; - lines = 0; - bands = 0; - header_offset = 0; - data_type = float32; - interleave = BSQ; - byte_order = endianLittle; - x_start = y_start = 0; - pixel_size[0] = pixel_size[1] = 1; - - //strings - file_type = "ENVI Standard"; - sensor_type = "Unknown"; - wavelength_units = "Unknown"; - z_plot_titles[0] = z_plot_titles[1] = "Unknown"; - } - - envi(){ - init(); - } - envi(std::string name){ - init(); - load(name); - } - - std::string trim(std::string line){ - //trims whitespace from the beginning and end of line - unsigned int start_i, end_i; - for(start_i=0; start_i < line.length(); start_i++) - if(line[start_i] != 32) - { - break; - } - - for(end_i = line.length()-1; end_i >= start_i; end_i--) - if(line[end_i] != ' ') - { - break; - } - - return line.substr(start_i, end_i - start_i+1); - } - - - std::string get_token(std::string line){ - //returns a variable name; in this case we look for the '=' sign - size_t i = line.find_first_of('='); - - std::string result; - if(i != std::string::npos) - result = trim(line.substr(0, i-1)); - - return result; - } - - std::string get_data_str(std::string line){ - size_t i = line.find_first_of('='); - - std::string result; - if(i != std::string::npos) - result = trim(line.substr(i+1)); - else - { - std::cout<<"ENVI Header error - data not found for token: "< get_string_seq(std::string token, std::string sequence) - { - //this function returns a sequence of comma-delimited strings - std::vector result; - - std::string entry; - size_t i; - do - { - i = sequence.find_first_of(','); - entry = sequence.substr(0, i); - sequence = sequence.substr(i+1); - result.push_back(trim(entry)); - }while(i != std::string::npos); - - return result; - } - - std::vector get_double_seq(std::string token, std::string sequence) - { - //this function returns a sequence of comma-delimited strings - std::vector result; - std::string entry; - size_t i; - do - { - i = sequence.find_first_of(','); - entry = sequence.substr(0, i); - sequence = sequence.substr(i+1); - result.push_back(atof(entry.c_str())); - //std::cout<>line; - if(line != "ENVI") - { - std::cout<<"ENVI Header Error: The header doesn't appear to be an ENVI file. The first line should be 'ENVI'."< pxsize = get_double_seq(token, string_sequence); - pixel_size[0] = pxsize[0]; - pixel_size[1] = pxsize[1]; - } - else if(token == "z plot titles") - { - std::string string_sequence = get_brace_str(token, line, file); - std::vector titles = get_string_seq(token, string_sequence); - z_plot_titles[0] = titles[0]; - z_plot_titles[1] = titles[1]; - } - - else if(token == "samples") - samples = atoi(get_data_str(line).c_str()); - else if(token == "lines") - lines = atoi(get_data_str(line).c_str()); - else if(token == "bands") - bands = atoi(get_data_str(line).c_str()); - else if(token == "header offset") - header_offset = atoi(get_data_str(line).c_str()); - else if(token == "file type") - file_type = get_data_str(line); - else if(token == "data type") - data_type = (dataType)atoi(get_data_str(line).c_str()); - else if(token == "interleave") - { - std::string interleave_str = get_data_str(line); - if(interleave_str == "bip") - interleave = BIP; - else if(interleave_str == "bil") - interleave = BIL; - else if(interleave_str == "bsq") - interleave = BSQ; - } - else if(token == "sensor type") - sensor_type = get_data_str(line); - else if(token == "byte order") - byte_order = (endianType)atoi(get_data_str(line).c_str()); - else if(token == "x start") - x_start = atof(get_data_str(line).c_str()); - else if(token == "y start") - y_start = atof(get_data_str(line).c_str()); - else if(token == "wavelength units") - wavelength_units = get_data_str(line); - - //get the next line - getline(file, line); - } - - //make sure the number of bands matches the number of wavelengths - unsigned int wavelengths = wavelength.size(); - if(bands != wavelengths) - { - std::cout<<"ENVI Header Error -- Number of wavelengths doesn't match the number of bands. Bands = "< 0) - { - outfile<<"band names = {"<()); + + exit(1); //if the function hasn't already returned, we don't handle this state + + } + + bool open(std::string filename, std::string headername){ + + //allocate memory + allocate(); + + //load the header + header.load(headername); + + //load the file + if(header.interleave == envi_header::BSQ) + if(header.data_type ==envi_header::float32) + return ((bsq*)file)->open(filename, header.samples, header.lines, header.bands, header.header_offset, header.wavelength); + + //handle other permutations..... + + exit(1); + } + + bool normalize(std::string outfile, double band){ + + if(header.interleave == envi_header::BSQ) + if(header.data_type ==envi_header::float32) + return ((bsq*)file)->normalize(outfile, band); + + exit(1); + } + + bool save_header(std::string filename){ + + //save the header file here + header.save(filename); + + return true; + } + + + + + +}; + +} //end namespace rts + +#endif diff --git a/envi/envi_header.h b/envi/envi_header.h index 7b39482..7c939f7 100644 --- a/envi/envi_header.h +++ b/envi/envi_header.h @@ -1,24 +1,24 @@ -#ifndef ENVI_HEADER_H -#define ENVI_HEADER_H - +#ifndef ENVI_HEADER_H +#define ENVI_HEADER_H + #include -#include +#include #include -#include -#include -#include - +#include +#include +#include + //information from an ENVI header file -//A good resource can be found here: http://www.exelisvis.com/docs/enviheaderfiles.html - -namespace Envi -{ - enum dataType {dummy0, int8, int16, int32, float32, float64, complex32, dummy7, dummy8, complex64, dummy10, dummy11, uint16, uint32, int64, uint64}; - enum interleaveType {BIP, BIL, BSQ}; //bip = Z,X,Y; bil = X,Z,Y; bsq = X,Y,Z - enum endianType {endianLittle, endianBig}; -} -struct EnviHeader +//A good resource can be found here: http://www.exelisvis.com/docs/enviheaderfiles.html + +namespace rts{ + +struct envi_header { + enum dataType {dummy0, int8, int16, int32, float32, float64, complex32, dummy7, dummy8, complex64, dummy10, dummy11, uint16, uint32, int64, uint64}; + enum interleaveType {BIP, BIL, BSQ}; //bip = Z,X,Y; bil = X,Z,Y; bsq = X,Y,Z + enum endianType {endianLittle, endianBig}; + std::string name; std::string description; @@ -27,16 +27,16 @@ struct EnviHeader unsigned int lines; //y-axis unsigned int bands; //spectral axis unsigned int header_offset; //header offset for binary file (in bytes) - std::string file_type; //should be "ENVI Standard" - - Envi::dataType data_type; //data representation; common value is 4 (32-bit float) + std::string file_type; //should be "ENVI Standard" + + envi_header::dataType data_type; //data representation; common value is 4 (32-bit float) - Envi::interleaveType interleave; + envi_header::interleaveType interleave; std::string sensor_type; //not really used - Envi::endianType byte_order; //little = least significant bit first (most systems) + envi_header::endianType byte_order; //little = least significant bit first (most systems) double x_start, y_start; //coordinates of the upper-left corner of the image std::string wavelength_units; //stored wavelength units @@ -47,18 +47,17 @@ struct EnviHeader std::vector band_names; //name for each band in the image std::vector wavelength; //wavelength for each band - EnviHeader() - { - name = ""; + void init(){ + name = ""; //specify default values for a new or empty ENVI file samples = 0; lines = 0; bands = 0; header_offset = 0; - data_type = Envi::float32; - interleave = Envi::BSQ; - byte_order = Envi::endianLittle; + data_type = float32; + interleave = BSQ; + byte_order = endianLittle; x_start = y_start = 0; pixel_size[0] = pixel_size[1] = 1; @@ -69,8 +68,15 @@ struct EnviHeader z_plot_titles[0] = z_plot_titles[1] = "Unknown"; } - std::string trim(std::string line) - { + envi_header(){ + init(); + } + envi_header(std::string name){ + init(); + load(name); + } + + std::string trim(std::string line){ //trims whitespace from the beginning and end of line unsigned int start_i, end_i; for(start_i=0; start_i < line.length(); start_i++) @@ -89,8 +95,7 @@ struct EnviHeader } - std::string get_token(std::string line) - { + std::string get_token(std::string line){ //returns a variable name; in this case we look for the '=' sign size_t i = line.find_first_of('='); @@ -101,8 +106,7 @@ struct EnviHeader return result; } - std::string get_data_str(std::string line) - { + std::string get_data_str(std::string line){ size_t i = line.find_first_of('='); std::string result; @@ -187,15 +191,15 @@ struct EnviHeader std::vector get_double_seq(std::string token, std::string sequence) { //this function returns a sequence of comma-delimited strings - std::vector result; + std::vector result; std::string entry; size_t i; do { i = sequence.find_first_of(','); - entry = sequence.substr(0, i); + entry = sequence.substr(0, i); sequence = sequence.substr(i+1); - result.push_back(atof(entry.c_str())); + result.push_back(atof(entry.c_str())); //std::cout<