#ifndef RTS_ENVI_H #define RTS_ENVI_H #include #include #include #include /* This is a class for reading and writing ENVI binary files. This class will be updated as needed. What this class CAN currently do: *) Write band images to a BSQ file. *) Append band images to a BSQ file. */ //information from an ENVI header file //A good resource can be found here: http://www.exelisvis.com/docs/enviheaderfiles.html struct EnviHeader { 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" unsigned int data_type; //data representation; common value is 4 (32-bit float) enum interleaveType {BIP, BIL, BSQ}; //bip = Z,X,Y; bil = X,Z,Y; bsq = X,Y,Z interleaveType interleave; std::string sensor_type; //not really used enum endianType {endianLittle, endianBig}; 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 EnviHeader() { name = ""; //specify default values for a new or empty ENVI file samples = 0; lines = 0; bands = 0; header_offset = 0; data_type = 4; 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"; } std::string trim(std::string line) { //trims whitespace from the beginning and end of line 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())); }while(i != std::string::npos); return result; } void load(std::string filename) { name = filename; //open the header file std::ifstream file(name.c_str()); if(!file) { std::cout<<"ENVI header file not found: "< 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 = 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); } //close the file file.close(); } void save(std::string filename) { //open a file std::ofstream outfile(filename.c_str()); //write the ENVI type identifier outfile<<"ENVI"< 0) { outfile<<"band names = {"<