#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 stim{ 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; 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_header::dataType data_type; //data representation; common value is 4 (32-bit float) envi_header::interleaveType interleave; std::string sensor_type; //not really used 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 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_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++) if(line[start_i] != 32) { break; } for(end_i = line.length()-1; end_i >= start_i; end_i--) if(line[end_i] != ' ' && line[end_i] != '\r') { 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(wavelengths && bands != wavelengths) { std::cout<<"ENVI Header Error -- Number of wavelengths doesn't match the number of bands. Bands = "< 0) { outfile<<"band names = {"<