Commit e8eb202fd18514f4a6ecb0e7343d9c3c0060cbc0

Authored by David Mayerich
1 parent 6aa04ba2

added a new ENVI interface

1 #ifndef STIM_BIL_H 1 #ifndef STIM_BIL_H
2 #define STIM_BIL_H 2 #define STIM_BIL_H
3 3
4 -#include "../envi/envi.h" 4 +#include "../envi/envi_header.h"
5 #include "../envi/binary.h" 5 #include "../envi/binary.h"
6 #include <cstring> 6 #include <cstring>
7 #include <utility> 7 #include <utility>
@@ -14,7 +14,7 @@ class bil: public binary&lt;T&gt; { @@ -14,7 +14,7 @@ class bil: public binary&lt;T&gt; {
14 14
15 protected: 15 protected:
16 16
17 - envi header; 17 + envi_header header;
18 18
19 public: 19 public:
20 20
@@ -353,7 +353,7 @@ public: @@ -353,7 +353,7 @@ public:
353 target.write(reinterpret_cast<const char*>(p), S); //write a band data into target file 353 target.write(reinterpret_cast<const char*>(p), S); //write a band data into target file
354 } 354 }
355 355
356 - header.interleave = rts::envi::BSQ; //change the type of file in header file 356 + header.interleave = rts::envi_header::BSQ; //change the type of file in header file
357 header.save(headername); 357 header.save(headername);
358 358
359 free(p); 359 free(p);
@@ -387,7 +387,7 @@ public: @@ -387,7 +387,7 @@ public:
387 target.write(reinterpret_cast<const char*>(q), S); //write a band data into target file 387 target.write(reinterpret_cast<const char*>(q), S); //write a band data into target file
388 } 388 }
389 389
390 - header.interleave = rts::envi::BIP; //change the type of file in header file 390 + header.interleave = rts::envi_header::BIP; //change the type of file in header file
391 header.save(headername); 391 header.save(headername);
392 392
393 free(p); 393 free(p);
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 #ifndef RTS_BINARY_H 3 #ifndef RTS_BINARY_H
4 #define RTS_BINARY_H 4 #define RTS_BINARY_H
5 5
6 -#include "../envi/envi.h" 6 +#include "../envi/envi_header.h"
7 #include "../math/vector.h" 7 #include "../math/vector.h"
8 #include <fstream> 8 #include <fstream>
9 #include <sys/stat.h> 9 #include <sys/stat.h>
1 -#include "../envi/envi.h" 1 +#ifndef STIM_BIP_H
  2 +#define STIM_BIP_H
  3 +
  4 +#include "../envi/envi_header.h"
2 #include "../envi/bil.h" 5 #include "../envi/bil.h"
3 #include "../envi/binary.h" 6 #include "../envi/binary.h"
4 #include <cstring> 7 #include <cstring>
@@ -12,7 +15,7 @@ class bip: public binary&lt;T&gt; { @@ -12,7 +15,7 @@ class bip: public binary&lt;T&gt; {
12 15
13 protected: 16 protected:
14 17
15 - envi header; 18 + envi_header header;
16 19
17 public: 20 public:
18 21
@@ -463,7 +466,7 @@ public: @@ -463,7 +466,7 @@ public:
463 target.write(reinterpret_cast<const char*>(q), S); //write a band data into target file 466 target.write(reinterpret_cast<const char*>(q), S); //write a band data into target file
464 } 467 }
465 468
466 - header.interleave = rts::envi::BIL; //change the type of file in header file 469 + header.interleave = rts::envi_header::BIL; //change the type of file in header file
467 header.save(headername); 470 header.save(headername);
468 471
469 free(p); 472 free(p);
@@ -480,3 +483,5 @@ public: @@ -480,3 +483,5 @@ public:
480 483
481 }; 484 };
482 } 485 }
  486 +
  487 +#endif
1 -#include "../envi/envi.h" 1 +#ifndef STIM_BSQ_H
  2 +#define STIM_BSQ_H
  3 +
  4 +#include "../envi/envi_header.h"
2 #include "../envi/binary.h" 5 #include "../envi/binary.h"
  6 +#include "../envi/bil.h"
3 #include <cstring> 7 #include <cstring>
4 #include <utility> 8 #include <utility>
  9 +#include <vector>
5 10
6 namespace rts{ 11 namespace rts{
7 12
@@ -11,31 +16,38 @@ class bsq: public binary&lt;T&gt; { @@ -11,31 +16,38 @@ class bsq: public binary&lt;T&gt; {
11 16
12 protected: 17 protected:
13 18
14 - envi header; 19 + //envi_header header;
  20 +
  21 + std::vector<double> w; //band wavelengths
15 22
16 public: 23 public:
17 24
18 using binary<T>::open; 25 using binary<T>::open;
19 using binary<T>::file; 26 using binary<T>::file;
20 using binary<T>::getSlice; 27 using binary<T>::getSlice;
  28 + using binary<T>::R;
21 29
22 //open a file, given the file and its header's names 30 //open a file, given the file and its header's names
23 - bool open(std::string filename, std::string headername){ 31 + bool open(std::string filename, unsigned int X, unsigned int Y, unsigned int B, unsigned int header_offset, std::vector<double> wavelengths){
24 32
25 - if (header.load(headername)==false){ 33 + /*if (header.load(headername)==false){
26 std::cout<<"ERROR: unable to load header file: "<<headername<<std::endl; 34 std::cout<<"ERROR: unable to load header file: "<<headername<<std::endl;
27 return false; 35 return false;
28 - } 36 + }*/
29 37
30 - open(filename, vec<unsigned int>(header.samples, header.lines, header.bands), header.header_offset);  
31 - return true; 38 + //copy the wavelengths to the BSQ file structure
  39 + w = wavelengths;
  40 +
  41 + return open(filename, vec<unsigned int>(X, Y, B), header_offset);
  42 +
  43 + return false;
32 44
33 } 45 }
34 46
35 //save one band of the file into the memory, and return the pointer 47 //save one band of the file into the memory, and return the pointer
36 bool band_index( T * p, unsigned int page){ 48 bool band_index( T * p, unsigned int page){
37 49
38 - if (page >= header.bands){ //make sure the bank number is right 50 + if (page >= R[2]){ //make sure the bank number is right
39 std::cout<<"ERROR: page out of range"<<std::endl; 51 std::cout<<"ERROR: page out of range"<<std::endl;
40 return false; 52 return false;
41 } 53 }
@@ -46,7 +58,7 @@ public: @@ -46,7 +58,7 @@ public:
46 58
47 bool getBand( T * p, double wavelength){ 59 bool getBand( T * p, double wavelength){
48 60
49 - unsigned int XY = header.samples * header.lines; //calculate the number of pixels in a band 61 + unsigned int XY = R[0] * R[1]; //calculate the number of pixels in a band
50 62
51 unsigned page=0; //bands around the wavelength 63 unsigned page=0; //bands around the wavelength
52 T * p1; 64 T * p1;
@@ -55,28 +67,28 @@ public: @@ -55,28 +67,28 @@ public:
55 //get the bands numbers around the wavelength 67 //get the bands numbers around the wavelength
56 68
57 //if wavelength is smaller than the first one in header file 69 //if wavelength is smaller than the first one in header file
58 - if ( header.wavelength[page] > wavelength ){ 70 + if ( w[page] > wavelength ){
59 band_index(p, page); 71 band_index(p, page);
60 return true; 72 return true;
61 } 73 }
62 74
63 - while( header.wavelength[page] < wavelength ) 75 + while( w[page] < wavelength )
64 { 76 {
65 page++; 77 page++;
66 //if wavelength is larger than the last wavelength in header file 78 //if wavelength is larger than the last wavelength in header file
67 - if (page == header.bands) {  
68 - getSlice(p, 2, header.bands-1); 79 + if (page == R[2]) {
  80 + getSlice(p, 2, R[2]-1);
69 return true; 81 return true;
70 } 82 }
71 } 83 }
72 - if ( wavelength < header.wavelength[page] ) 84 + if ( wavelength < w[page] )
73 { 85 {
74 p1=(T*)malloc( XY * sizeof(T)); //memory allocation 86 p1=(T*)malloc( XY * sizeof(T)); //memory allocation
75 p2=(T*)malloc( XY * sizeof(T)); 87 p2=(T*)malloc( XY * sizeof(T));
76 band_index(p1, page - 1); 88 band_index(p1, page - 1);
77 band_index(p2, page ); 89 band_index(p2, page );
78 for(unsigned i=0; i < XY; i++){ 90 for(unsigned i=0; i < XY; i++){
79 - double r = (double) (wavelength - header.wavelength[page-1]) / (double) (header.wavelength[page] - header.wavelength[page-1]); 91 + double r = (double) (wavelength - w[page-1]) / (double) (w[page] - w[page-1]);
80 p[i] = (p2[i] - p1[i]) * r + p1[i]; 92 p[i] = (p2[i] - p1[i]) * r + p1[i];
81 } 93 }
82 } 94 }
@@ -93,16 +105,16 @@ public: @@ -93,16 +105,16 @@ public:
93 105
94 unsigned int i; 106 unsigned int i;
95 107
96 - if ( x >= header.samples || y >= header.lines){ //make sure the sample and line number is right 108 + if ( x >= R[0] || y >= R[1]){ //make sure the sample and line number is right
97 std::cout<<"ERROR: sample or line out of range"<<std::endl; 109 std::cout<<"ERROR: sample or line out of range"<<std::endl;
98 return false; 110 return false;
99 } 111 }
100 112
101 - file.seekg((x + y * header.samples) * sizeof(T), std::ios::beg); //point to the certain sample and line  
102 - for (i = 0; i < header.bands; i++) 113 + file.seekg((x + y * R[0]) * sizeof(T), std::ios::beg); //point to the certain sample and line
  114 + for (i = 0; i < R[3]; i++)
103 { 115 {
104 file.read((char *)(p + i), sizeof(T)); 116 file.read((char *)(p + i), sizeof(T));
105 - file.seekg((header.lines * header.samples - 1) * sizeof(T), std::ios::cur); //go to the next band 117 + file.seekg((R[1] * R[0] - 1) * sizeof(T), std::ios::cur); //go to the next band
106 } 118 }
107 119
108 return true; 120 return true;
@@ -118,8 +130,8 @@ public: @@ -118,8 +130,8 @@ public:
118 std::string headername = outname + ".hdr"; //the header file name 130 std::string headername = outname + ".hdr"; //the header file name
119 131
120 //simplify image resolution 132 //simplify image resolution
121 - unsigned int B = header.bands; //calculate the number of bands  
122 - unsigned int XY = header.samples * header.lines; //calculate the number of pixels in a band 133 + unsigned int B = R[2]; //calculate the number of bands
  134 + unsigned int XY = R[0] * R[1]; //calculate the number of pixels in a band
123 unsigned int S = XY * sizeof(T); //calculate the number of bytes in a band 135 unsigned int S = XY * sizeof(T); //calculate the number of bytes in a band
124 136
125 double ai, bi; //stores the two baseline points wavelength surrounding the current band 137 double ai, bi; //stores the two baseline points wavelength surrounding the current band
@@ -142,11 +154,11 @@ public: @@ -142,11 +154,11 @@ public:
142 154
143 155
144 //initialize lownum, highnum, low, high 156 //initialize lownum, highnum, low, high
145 - ai=header.wavelength[0]; 157 + ai=w[0];
146 158
147 //if no baseline point is specified at band 0, 159 //if no baseline point is specified at band 0,
148 //set the baseline point at band 0 to 0 160 //set the baseline point at band 0 to 0
149 - if(wls[0] != header.wavelength[0]){ 161 + if(wls[0] != w[0]){
150 bi = wls[control]; 162 bi = wls[control];
151 memset(a, (char)0, S); 163 memset(a, (char)0, S);
152 } 164 }
@@ -163,7 +175,7 @@ public: @@ -163,7 +175,7 @@ public:
163 for(unsigned cii = 0; cii < B; cii++){ 175 for(unsigned cii = 0; cii < B; cii++){
164 176
165 //update baseline points, if necessary 177 //update baseline points, if necessary
166 - if( header.wavelength[cii] >= bi && cii != B - 1) { 178 + if( w[cii] >= bi && cii != B - 1) {
167 //if the high band is now on the last BL point? 179 //if the high band is now on the last BL point?
168 if (control != N-1) { 180 if (control != N-1) {
169 181
@@ -177,20 +189,20 @@ public: @@ -177,20 +189,20 @@ public:
177 189
178 } 190 }
179 //if the last BL point on the last band of the file? 191 //if the last BL point on the last band of the file?
180 - else if ( wls[control] < header.wavelength[B - 1]) { 192 + else if ( wls[control] < w[B - 1]) {
181 193
182 std::swap(a, b); //swap the baseline band pointers 194 std::swap(a, b); //swap the baseline band pointers
183 195
184 memset(b, (char)0, S); //clear the high band 196 memset(b, (char)0, S); //clear the high band
185 197
186 ai = bi; 198 ai = bi;
187 - bi = header.wavelength[B - 1]; 199 + bi = w[B - 1];
188 } 200 }
189 } 201 }
190 202
191 //get the current band 203 //get the current band
192 band_index(c, cii); 204 band_index(c, cii);
193 - ci = header.wavelength[cii]; 205 + ci = w[cii];
194 206
195 //perform the baseline correction 207 //perform the baseline correction
196 for(unsigned i=0; i < XY; i++){ 208 for(unsigned i=0; i < XY; i++){
@@ -202,7 +214,7 @@ public: @@ -202,7 +214,7 @@ public:
202 214
203 } 215 }
204 216
205 - header.save(headername); //save the new header file 217 + //header.save(headername); //save the new header file
206 218
207 free(a); 219 free(a);
208 free(b); 220 free(b);
@@ -214,8 +226,9 @@ public: @@ -214,8 +226,9 @@ public:
214 // normalize the BSQ file 226 // normalize the BSQ file
215 bool normalize(std::string outname, double band) 227 bool normalize(std::string outname, double band)
216 { 228 {
217 - unsigned int B = header.bands; //calculate the number of bands  
218 - unsigned int XY = header.samples * header.lines; //calculate the number of pixels in a band 229 + std::cout<<"NORMALIZE A BSQ FILE"<<std::endl;
  230 + unsigned int B = R[2]; //calculate the number of bands
  231 + unsigned int XY = R[0] * R[1]; //calculate the number of pixels in a band
219 unsigned int S = XY * sizeof(T); //calculate the number of bytes in a band 232 unsigned int S = XY * sizeof(T); //calculate the number of bytes in a band
220 233
221 std::ofstream target(outname.c_str(), std::ios::binary); //open the target binary file 234 std::ofstream target(outname.c_str(), std::ios::binary); //open the target binary file
@@ -239,7 +252,7 @@ public: @@ -239,7 +252,7 @@ public:
239 target.write(reinterpret_cast<const char*>(c), S); //write normalized data into destination 252 target.write(reinterpret_cast<const char*>(c), S); //write normalized data into destination
240 } 253 }
241 254
242 - header.save(headername); //save the new header file 255 + //header.save(headername); //save the new header file
243 256
244 free(b); 257 free(b);
245 free(c); 258 free(c);
@@ -272,8 +285,8 @@ public: @@ -272,8 +285,8 @@ public:
272 bool bil(std::string outname) 285 bool bil(std::string outname)
273 { 286 {
274 //simplify image resolution 287 //simplify image resolution
275 - unsigned int L = header.samples * header.bands * sizeof(T); //calculate the number of bytes of a ZX slice  
276 - unsigned int jump = (header.lines - 1) * header.samples * sizeof(T); 288 + unsigned int L = R[0] * R[1] * sizeof(T); //calculate the number of bytes of a ZX slice
  289 + unsigned int jump = (R[1] - 1) * R[0] * sizeof(T);
277 290
278 std::ofstream target(outname.c_str(), std::ios::binary); 291 std::ofstream target(outname.c_str(), std::ios::binary);
279 std::string headername = outname + ".hdr"; 292 std::string headername = outname + ".hdr";
@@ -281,18 +294,18 @@ public: @@ -281,18 +294,18 @@ public:
281 T * p; //pointer to the current spectrum 294 T * p; //pointer to the current spectrum
282 p = (T*)malloc(L); 295 p = (T*)malloc(L);
283 296
284 - for ( unsigned i = 0; i < header.lines; i++) 297 + for ( unsigned i = 0; i < R[1]; i++)
285 { 298 {
286 - file.seekg(header.samples * i * sizeof(T), std::ios::beg);  
287 - for ( unsigned j = 0; j < header.bands; j++ ) 299 + file.seekg(R[0] * i * sizeof(T), std::ios::beg);
  300 + for ( unsigned j = 0; j < R[2]; j++ )
288 { 301 {
289 - file.read((char *)(p + j * header.samples), sizeof(T) * header.samples); 302 + file.read((char *)(p + j * R[0]), sizeof(T) * R[0]);
290 file.seekg(jump, std::ios::cur); //go to the next band 303 file.seekg(jump, std::ios::cur); //go to the next band
291 } 304 }
292 target.write(reinterpret_cast<const char*>(p), L); //write XZ slice data into target file 305 target.write(reinterpret_cast<const char*>(p), L); //write XZ slice data into target file
293 } 306 }
294 - header.interleave = rts::envi::BIL; //change the type of file in header file  
295 - header.save(headername); 307 + //header.interleave = rts::envi_header::BIL; //change the type of file in header file
  308 + //header.save(headername);
296 309
297 free(p); 310 free(p);
298 target.close(); 311 target.close();
@@ -308,4 +321,6 @@ public: @@ -308,4 +321,6 @@ public:
308 }; 321 };
309 } 322 }
310 323
  324 +#endif
  325 +
311 326
1 -#ifndef ENVI_HEADER_H  
2 -#define ENVI_HEADER_H  
3 -  
4 -#include <string>  
5 -#include <iostream>  
6 -#include <fstream>  
7 -#include <sstream>  
8 -#include <vector>  
9 -#include <stdlib.h>  
10 -  
11 -//information from an ENVI header file  
12 -//A good resource can be found here: http://www.exelisvis.com/docs/enviheaderfiles.html  
13 -  
14 -namespace rts{  
15 -  
16 -struct envi  
17 -{  
18 - enum dataType {dummy0, int8, int16, int32, float32, float64, complex32, dummy7, dummy8, complex64, dummy10, dummy11, uint16, uint32, int64, uint64};  
19 - enum interleaveType {BIP, BIL, BSQ}; //bip = Z,X,Y; bil = X,Z,Y; bsq = X,Y,Z  
20 - enum endianType {endianLittle, endianBig};  
21 -  
22 - std::string name;  
23 -  
24 - std::string description;  
25 -  
26 - unsigned int samples; //x-axis  
27 - unsigned int lines; //y-axis  
28 - unsigned int bands; //spectral axis  
29 - unsigned int header_offset; //header offset for binary file (in bytes)  
30 - std::string file_type; //should be "ENVI Standard"  
31 -  
32 - envi::dataType data_type; //data representation; common value is 4 (32-bit float)  
33 -  
34 -  
35 - envi::interleaveType interleave;  
36 -  
37 - std::string sensor_type; //not really used  
38 -  
39 - envi::endianType byte_order; //little = least significant bit first (most systems)  
40 -  
41 - double x_start, y_start; //coordinates of the upper-left corner of the image  
42 - std::string wavelength_units; //stored wavelength units  
43 - std::string z_plot_titles[2];  
44 -  
45 - double pixel_size[2]; //pixel size along X and Y  
46 -  
47 - std::vector<std::string> band_names; //name for each band in the image  
48 - std::vector<double> wavelength; //wavelength for each band  
49 -  
50 - void init(){  
51 - name = "";  
52 -  
53 - //specify default values for a new or empty ENVI file  
54 - samples = 0;  
55 - lines = 0;  
56 - bands = 0;  
57 - header_offset = 0;  
58 - data_type = float32;  
59 - interleave = BSQ;  
60 - byte_order = endianLittle;  
61 - x_start = y_start = 0;  
62 - pixel_size[0] = pixel_size[1] = 1;  
63 -  
64 - //strings  
65 - file_type = "ENVI Standard";  
66 - sensor_type = "Unknown";  
67 - wavelength_units = "Unknown";  
68 - z_plot_titles[0] = z_plot_titles[1] = "Unknown";  
69 - }  
70 -  
71 - envi(){  
72 - init();  
73 - }  
74 - envi(std::string name){  
75 - init();  
76 - load(name);  
77 - }  
78 -  
79 - std::string trim(std::string line){  
80 - //trims whitespace from the beginning and end of line  
81 - unsigned int start_i, end_i;  
82 - for(start_i=0; start_i < line.length(); start_i++)  
83 - if(line[start_i] != 32)  
84 - {  
85 - break;  
86 - }  
87 -  
88 - for(end_i = line.length()-1; end_i >= start_i; end_i--)  
89 - if(line[end_i] != ' ')  
90 - {  
91 - break;  
92 - }  
93 -  
94 - return line.substr(start_i, end_i - start_i+1);  
95 - }  
96 -  
97 -  
98 - std::string get_token(std::string line){  
99 - //returns a variable name; in this case we look for the '=' sign  
100 - size_t i = line.find_first_of('=');  
101 -  
102 - std::string result;  
103 - if(i != std::string::npos)  
104 - result = trim(line.substr(0, i-1));  
105 -  
106 - return result;  
107 - }  
108 -  
109 - std::string get_data_str(std::string line){  
110 - size_t i = line.find_first_of('=');  
111 -  
112 - std::string result;  
113 - if(i != std::string::npos)  
114 - result = trim(line.substr(i+1));  
115 - else  
116 - {  
117 - std::cout<<"ENVI Header error - data not found for token: "<<get_token(line)<<std::endl;  
118 - exit(1);  
119 - }  
120 - return result;  
121 - }  
122 -  
123 - std::string get_brace_str(std::string token, std::string line, std::ifstream &file)  
124 - {  
125 - //this function assembles all of the characters between curly braces  
126 - //this is how strings are defined within an ENVI file  
127 -  
128 - std::string result;  
129 -  
130 - //first, find the starting brace  
131 - size_t i;  
132 - do  
133 - {  
134 - i = line.find_first_of('{');  
135 - if(i != std::string::npos)  
136 - break;  
137 - }while(file);  
138 -  
139 - //if i is still npos, we have reached the end of the file without a brace...something is wrong  
140 - if(i == std::string::npos)  
141 - {  
142 - std::cout<<"ENVI Header error - string token declared without being defined: "<<token<<std::endl;  
143 - exit(1);  
144 - }  
145 - line = line.substr(i+1);  
146 -  
147 - //copy character data into the result string until we find a closing brace  
148 - while(file)  
149 - {  
150 - i = line.find_first_of('}');  
151 -  
152 -  
153 - if(i != std::string::npos)  
154 - {  
155 - result += line.substr(0, i);  
156 - break;  
157 - }  
158 - else  
159 - result += line;  
160 -  
161 - getline(file, line);  
162 - }  
163 -  
164 - if(i == std::string::npos)  
165 - {  
166 - std::cout<<"ENVI Header error - string token declared without a terminating '}': "<<token<<std::endl;  
167 - exit(1);  
168 - }  
169 -  
170 - return trim(result);  
171 - }  
172 -  
173 - std::vector<std::string> get_string_seq(std::string token, std::string sequence)  
174 - {  
175 - //this function returns a sequence of comma-delimited strings  
176 - std::vector<std::string> result;  
177 -  
178 - std::string entry;  
179 - size_t i;  
180 - do  
181 - {  
182 - i = sequence.find_first_of(',');  
183 - entry = sequence.substr(0, i);  
184 - sequence = sequence.substr(i+1);  
185 - result.push_back(trim(entry));  
186 - }while(i != std::string::npos);  
187 -  
188 - return result;  
189 - }  
190 -  
191 - std::vector<double> get_double_seq(std::string token, std::string sequence)  
192 - {  
193 - //this function returns a sequence of comma-delimited strings  
194 - std::vector<double> result;  
195 - std::string entry;  
196 - size_t i;  
197 - do  
198 - {  
199 - i = sequence.find_first_of(',');  
200 - entry = sequence.substr(0, i);  
201 - sequence = sequence.substr(i+1);  
202 - result.push_back(atof(entry.c_str()));  
203 - //std::cout<<entry<<" ";  
204 - }while(i != std::string::npos);  
205 -  
206 - return result;  
207 - }  
208 -  
209 - bool load(std::string filename)  
210 - {  
211 - //open the header file  
212 - std::ifstream file(filename.c_str());  
213 -  
214 - if(!file)  
215 - {  
216 - return false;  
217 - }  
218 -  
219 - //the first line should just be "ENVI"  
220 - std::string line;  
221 - file>>line;  
222 - if(line != "ENVI")  
223 - {  
224 - std::cout<<"ENVI Header Error: The header doesn't appear to be an ENVI file. The first line should be 'ENVI'."<<std::endl;  
225 - exit(1);  
226 - }  
227 -  
228 - //for each line in the file, get the token  
229 - std::string token;  
230 -  
231 - //get a line  
232 - getline(file, line);  
233 - while(file)  
234 - {  
235 -  
236 -  
237 -  
238 - //get the token  
239 - token = get_token(line);  
240 -  
241 - if(token == "description")  
242 - description = get_brace_str(token, line, file);  
243 - else if(token == "band names")  
244 - {  
245 - std::string string_sequence = get_brace_str(token, line, file);  
246 - band_names = get_string_seq(token, string_sequence);  
247 - }  
248 - else if(token == "wavelength")  
249 - {  
250 - std::string string_sequence = get_brace_str(token, line, file);  
251 - wavelength = get_double_seq(token, string_sequence);  
252 - }  
253 - else if(token == "pixel size")  
254 - {  
255 - std::string string_sequence = get_brace_str(token, line, file);  
256 - std::vector<double> pxsize = get_double_seq(token, string_sequence);  
257 - pixel_size[0] = pxsize[0];  
258 - pixel_size[1] = pxsize[1];  
259 - }  
260 - else if(token == "z plot titles")  
261 - {  
262 - std::string string_sequence = get_brace_str(token, line, file);  
263 - std::vector<std::string> titles = get_string_seq(token, string_sequence);  
264 - z_plot_titles[0] = titles[0];  
265 - z_plot_titles[1] = titles[1];  
266 - }  
267 -  
268 - else if(token == "samples")  
269 - samples = atoi(get_data_str(line).c_str());  
270 - else if(token == "lines")  
271 - lines = atoi(get_data_str(line).c_str());  
272 - else if(token == "bands")  
273 - bands = atoi(get_data_str(line).c_str());  
274 - else if(token == "header offset")  
275 - header_offset = atoi(get_data_str(line).c_str());  
276 - else if(token == "file type")  
277 - file_type = get_data_str(line);  
278 - else if(token == "data type")  
279 - data_type = (dataType)atoi(get_data_str(line).c_str());  
280 - else if(token == "interleave")  
281 - {  
282 - std::string interleave_str = get_data_str(line);  
283 - if(interleave_str == "bip")  
284 - interleave = BIP;  
285 - else if(interleave_str == "bil")  
286 - interleave = BIL;  
287 - else if(interleave_str == "bsq")  
288 - interleave = BSQ;  
289 - }  
290 - else if(token == "sensor type")  
291 - sensor_type = get_data_str(line);  
292 - else if(token == "byte order")  
293 - byte_order = (endianType)atoi(get_data_str(line).c_str());  
294 - else if(token == "x start")  
295 - x_start = atof(get_data_str(line).c_str());  
296 - else if(token == "y start")  
297 - y_start = atof(get_data_str(line).c_str());  
298 - else if(token == "wavelength units")  
299 - wavelength_units = get_data_str(line);  
300 -  
301 - //get the next line  
302 - getline(file, line);  
303 - }  
304 -  
305 - //make sure the number of bands matches the number of wavelengths  
306 - unsigned int wavelengths = wavelength.size();  
307 - if(bands != wavelengths)  
308 - {  
309 - std::cout<<"ENVI Header Error -- Number of wavelengths doesn't match the number of bands. Bands = "<<bands<<", Wavelengths = "<<wavelength.size()<<std::endl;  
310 - exit(1);  
311 - }  
312 -  
313 - //close the file  
314 - file.close();  
315 -  
316 - //set the file name  
317 - name = filename;  
318 -  
319 - return true;  
320 - }  
321 -  
322 - void save(std::string filename)  
323 - {  
324 - //open a file  
325 - std::ofstream outfile(filename.c_str());  
326 -  
327 - //write the ENVI type identifier  
328 - outfile<<"ENVI"<<std::endl;  
329 -  
330 - //output all of the data  
331 - outfile<<"description = {"<<std::endl;  
332 - outfile<<" "<<description<<"}"<<std::endl;  
333 -  
334 - outfile<<"samples = "<<samples<<std::endl;  
335 - outfile<<"lines = "<<lines<<std::endl;  
336 - outfile<<"bands = "<<bands<<std::endl;  
337 - outfile<<"header offset = "<<header_offset<<std::endl;  
338 - outfile<<"file type = "<<file_type<<std::endl;  
339 - outfile<<"data type = "<<data_type<<std::endl;  
340 - outfile<<"interleave = ";  
341 - if(interleave == BIP)  
342 - outfile<<"bip";  
343 - if(interleave == BIL)  
344 - outfile<<"bil";  
345 - if(interleave == BSQ)  
346 - outfile<<"bsq";  
347 - outfile<<std::endl;  
348 - outfile<<"sensor type = "<<sensor_type<<std::endl;  
349 - outfile<<"byte order = "<<byte_order<<std::endl;  
350 - outfile<<"x start = "<<x_start<<std::endl;  
351 - outfile<<"y start = "<<y_start<<std::endl;  
352 - outfile<<"wavelength units = "<<wavelength_units<<std::endl;  
353 - outfile<<"z plot titles = {";  
354 - outfile<<z_plot_titles[0]<<", "<<z_plot_titles[1]<<"}"<<std::endl;  
355 - outfile<<"pixel size = {"<<pixel_size[0]<<", "<<pixel_size[1]<<", units=Meters}"<<std::endl;  
356 - if(band_names.size() > 0)  
357 - {  
358 - outfile<<"band names = {"<<std::endl;  
359 - for(unsigned int i=0; i<band_names.size(); i++)  
360 - {  
361 - outfile<<band_names[i];  
362 - if(i < band_names.size() - 1)  
363 - outfile<<", ";  
364 - }  
365 - outfile<<"}"<<std::endl;  
366 - }  
367 - outfile<<"wavelength = {"<<std::endl;  
368 - for(unsigned int i=0; i<wavelength.size()-1; i++)  
369 - outfile<<wavelength[i]<<", ";  
370 - outfile<<wavelength.back()<<"}"<<std::endl;  
371 -  
372 - outfile.close();  
373 - }  
374 -  
375 - void save()  
376 - {  
377 - //std::cout<<"ENVI Header Name: "<<name<<std::endl;  
378 - save(name);  
379 - }  
380 -  
381 - //returns the size of a single value (in bytes)  
382 - unsigned int valsize()  
383 - {  
384 - switch(data_type)  
385 - {  
386 - case int8: //1 = 8-bit byte  
387 - return 1;  
388 - case int16: //16-bit signed integer  
389 - case uint16: //16-bit unsigned integer  
390 - return 2;  
391 - case int32: //32-bit signed long integer  
392 - case float32: //32-bit floating point  
393 - case uint32: //32-bit unsigned long integer  
394 - return 4;  
395 - case float64: //64-bit double-precision floating point  
396 - case complex32: //32-bit complex value  
397 - case int64: //64-bit signed long integer  
398 - case uint64: //64-bit unsigned long integer  
399 - return 8;  
400 - case complex64: //64-bit complex value  
401 - return 16;  
402 - default:  
403 - return 0;  
404 - }  
405 -  
406 - }  
407 -}; //end EnviHeader  
408 -}  
409 -#endif 1 +#ifndef STIM_ENVI_H
  2 +#define STIM_ENVI_H
  3 +
  4 +#include "../envi/envi_header.h"
  5 +#include "../envi/bsq.h"
  6 +#include "../envi/bip.h"
  7 +#include "../envi/bil.h"
  8 +
  9 +namespace rts{
  10 +
  11 +//container class for an ENVI binary file reader
  12 +class envi{
  13 +
  14 + envi_header header;
  15 +
  16 + void* file; //void pointer to the relevant file reader (bip, bsq, or bil - with appropriate data type)
  17 +
  18 +public:
  19 +
  20 + bool allocate(){
  21 +
  22 + file = NULL; //set file to a NULL pointer
  23 +
  24 + if(header.interleave == envi_header::BSQ)
  25 + if(header.data_type ==envi_header::float32)
  26 + return(file = new bsq<float>());
  27 +
  28 + exit(1); //if the function hasn't already returned, we don't handle this state
  29 +
  30 + }
  31 +
  32 + bool open(std::string filename, std::string headername){
  33 +
  34 + //allocate memory
  35 + allocate();
  36 +
  37 + //load the header
  38 + header.load(headername);
  39 +
  40 + //load the file
  41 + if(header.interleave == envi_header::BSQ)
  42 + if(header.data_type ==envi_header::float32)
  43 + return ((bsq<float>*)file)->open(filename, header.samples, header.lines, header.bands, header.header_offset, header.wavelength);
  44 +
  45 + //handle other permutations.....
  46 +
  47 + exit(1);
  48 + }
  49 +
  50 + bool normalize(std::string outfile, double band){
  51 +
  52 + if(header.interleave == envi_header::BSQ)
  53 + if(header.data_type ==envi_header::float32)
  54 + return ((bsq<float>*)file)->normalize(outfile, band);
  55 +
  56 + exit(1);
  57 + }
  58 +
  59 + bool save_header(std::string filename){
  60 +
  61 + //save the header file here
  62 + header.save(filename);
  63 +
  64 + return true;
  65 + }
  66 +
  67 +
  68 +
  69 +
  70 +
  71 +};
  72 +
  73 +} //end namespace rts
  74 +
  75 +#endif
envi/envi_header.h
1 -#ifndef ENVI_HEADER_H  
2 -#define ENVI_HEADER_H  
3 - 1 +#ifndef ENVI_HEADER_H
  2 +#define ENVI_HEADER_H
  3 +
4 #include <string> 4 #include <string>
5 -#include <iostream> 5 +#include <iostream>
6 #include <fstream> 6 #include <fstream>
7 -#include <sstream>  
8 -#include <vector>  
9 -#include <stdlib.h>  
10 - 7 +#include <sstream>
  8 +#include <vector>
  9 +#include <stdlib.h>
  10 +
11 //information from an ENVI header file 11 //information from an ENVI header file
12 -//A good resource can be found here: http://www.exelisvis.com/docs/enviheaderfiles.html  
13 -  
14 -namespace Envi  
15 -{  
16 - enum dataType {dummy0, int8, int16, int32, float32, float64, complex32, dummy7, dummy8, complex64, dummy10, dummy11, uint16, uint32, int64, uint64};  
17 - enum interleaveType {BIP, BIL, BSQ}; //bip = Z,X,Y; bil = X,Z,Y; bsq = X,Y,Z  
18 - enum endianType {endianLittle, endianBig};  
19 -}  
20 -struct EnviHeader 12 +//A good resource can be found here: http://www.exelisvis.com/docs/enviheaderfiles.html
  13 +
  14 +namespace rts{
  15 +
  16 +struct envi_header
21 { 17 {
  18 + enum dataType {dummy0, int8, int16, int32, float32, float64, complex32, dummy7, dummy8, complex64, dummy10, dummy11, uint16, uint32, int64, uint64};
  19 + enum interleaveType {BIP, BIL, BSQ}; //bip = Z,X,Y; bil = X,Z,Y; bsq = X,Y,Z
  20 + enum endianType {endianLittle, endianBig};
  21 +
22 std::string name; 22 std::string name;
23 23
24 std::string description; 24 std::string description;
@@ -27,16 +27,16 @@ struct EnviHeader @@ -27,16 +27,16 @@ struct EnviHeader
27 unsigned int lines; //y-axis 27 unsigned int lines; //y-axis
28 unsigned int bands; //spectral axis 28 unsigned int bands; //spectral axis
29 unsigned int header_offset; //header offset for binary file (in bytes) 29 unsigned int header_offset; //header offset for binary file (in bytes)
30 - std::string file_type; //should be "ENVI Standard"  
31 -  
32 - Envi::dataType data_type; //data representation; common value is 4 (32-bit float) 30 + std::string file_type; //should be "ENVI Standard"
  31 +
  32 + envi_header::dataType data_type; //data representation; common value is 4 (32-bit float)
33 33
34 34
35 - Envi::interleaveType interleave; 35 + envi_header::interleaveType interleave;
36 36
37 std::string sensor_type; //not really used 37 std::string sensor_type; //not really used
38 38
39 - Envi::endianType byte_order; //little = least significant bit first (most systems) 39 + envi_header::endianType byte_order; //little = least significant bit first (most systems)
40 40
41 double x_start, y_start; //coordinates of the upper-left corner of the image 41 double x_start, y_start; //coordinates of the upper-left corner of the image
42 std::string wavelength_units; //stored wavelength units 42 std::string wavelength_units; //stored wavelength units
@@ -47,18 +47,17 @@ struct EnviHeader @@ -47,18 +47,17 @@ struct EnviHeader
47 std::vector<std::string> band_names; //name for each band in the image 47 std::vector<std::string> band_names; //name for each band in the image
48 std::vector<double> wavelength; //wavelength for each band 48 std::vector<double> wavelength; //wavelength for each band
49 49
50 - EnviHeader()  
51 - {  
52 - name = ""; 50 + void init(){
  51 + name = "";
53 52
54 //specify default values for a new or empty ENVI file 53 //specify default values for a new or empty ENVI file
55 samples = 0; 54 samples = 0;
56 lines = 0; 55 lines = 0;
57 bands = 0; 56 bands = 0;
58 header_offset = 0; 57 header_offset = 0;
59 - data_type = Envi::float32;  
60 - interleave = Envi::BSQ;  
61 - byte_order = Envi::endianLittle; 58 + data_type = float32;
  59 + interleave = BSQ;
  60 + byte_order = endianLittle;
62 x_start = y_start = 0; 61 x_start = y_start = 0;
63 pixel_size[0] = pixel_size[1] = 1; 62 pixel_size[0] = pixel_size[1] = 1;
64 63
@@ -69,8 +68,15 @@ struct EnviHeader @@ -69,8 +68,15 @@ struct EnviHeader
69 z_plot_titles[0] = z_plot_titles[1] = "Unknown"; 68 z_plot_titles[0] = z_plot_titles[1] = "Unknown";
70 } 69 }
71 70
72 - std::string trim(std::string line)  
73 - { 71 + envi_header(){
  72 + init();
  73 + }
  74 + envi_header(std::string name){
  75 + init();
  76 + load(name);
  77 + }
  78 +
  79 + std::string trim(std::string line){
74 //trims whitespace from the beginning and end of line 80 //trims whitespace from the beginning and end of line
75 unsigned int start_i, end_i; 81 unsigned int start_i, end_i;
76 for(start_i=0; start_i < line.length(); start_i++) 82 for(start_i=0; start_i < line.length(); start_i++)
@@ -89,8 +95,7 @@ struct EnviHeader @@ -89,8 +95,7 @@ struct EnviHeader
89 } 95 }
90 96
91 97
92 - std::string get_token(std::string line)  
93 - { 98 + std::string get_token(std::string line){
94 //returns a variable name; in this case we look for the '=' sign 99 //returns a variable name; in this case we look for the '=' sign
95 size_t i = line.find_first_of('='); 100 size_t i = line.find_first_of('=');
96 101
@@ -101,8 +106,7 @@ struct EnviHeader @@ -101,8 +106,7 @@ struct EnviHeader
101 return result; 106 return result;
102 } 107 }
103 108
104 - std::string get_data_str(std::string line)  
105 - { 109 + std::string get_data_str(std::string line){
106 size_t i = line.find_first_of('='); 110 size_t i = line.find_first_of('=');
107 111
108 std::string result; 112 std::string result;
@@ -187,15 +191,15 @@ struct EnviHeader @@ -187,15 +191,15 @@ struct EnviHeader
187 std::vector<double> get_double_seq(std::string token, std::string sequence) 191 std::vector<double> get_double_seq(std::string token, std::string sequence)
188 { 192 {
189 //this function returns a sequence of comma-delimited strings 193 //this function returns a sequence of comma-delimited strings
190 - std::vector<double> result; 194 + std::vector<double> result;
191 std::string entry; 195 std::string entry;
192 size_t i; 196 size_t i;
193 do 197 do
194 { 198 {
195 i = sequence.find_first_of(','); 199 i = sequence.find_first_of(',');
196 - entry = sequence.substr(0, i); 200 + entry = sequence.substr(0, i);
197 sequence = sequence.substr(i+1); 201 sequence = sequence.substr(i+1);
198 - result.push_back(atof(entry.c_str())); 202 + result.push_back(atof(entry.c_str()));
199 //std::cout<<entry<<" "; 203 //std::cout<<entry<<" ";
200 }while(i != std::string::npos); 204 }while(i != std::string::npos);
201 205
@@ -208,7 +212,7 @@ struct EnviHeader @@ -208,7 +212,7 @@ struct EnviHeader
208 std::ifstream file(filename.c_str()); 212 std::ifstream file(filename.c_str());
209 213
210 if(!file) 214 if(!file)
211 - { 215 + {
212 return false; 216 return false;
213 } 217 }
214 218
@@ -219,11 +223,11 @@ struct EnviHeader @@ -219,11 +223,11 @@ struct EnviHeader
219 { 223 {
220 std::cout<<"ENVI Header Error: The header doesn't appear to be an ENVI file. The first line should be 'ENVI'."<<std::endl; 224 std::cout<<"ENVI Header Error: The header doesn't appear to be an ENVI file. The first line should be 'ENVI'."<<std::endl;
221 exit(1); 225 exit(1);
222 - } 226 + }
223 227
224 //for each line in the file, get the token 228 //for each line in the file, get the token
225 - std::string token;  
226 - 229 + std::string token;
  230 +
227 //get a line 231 //get a line
228 getline(file, line); 232 getline(file, line);
229 while(file) 233 while(file)
@@ -272,46 +276,46 @@ struct EnviHeader @@ -272,46 +276,46 @@ struct EnviHeader
272 else if(token == "file type") 276 else if(token == "file type")
273 file_type = get_data_str(line); 277 file_type = get_data_str(line);
274 else if(token == "data type") 278 else if(token == "data type")
275 - data_type = (Envi::dataType)atoi(get_data_str(line).c_str()); 279 + data_type = (dataType)atoi(get_data_str(line).c_str());
276 else if(token == "interleave") 280 else if(token == "interleave")
277 { 281 {
278 std::string interleave_str = get_data_str(line); 282 std::string interleave_str = get_data_str(line);
279 if(interleave_str == "bip") 283 if(interleave_str == "bip")
280 - interleave = Envi::BIP; 284 + interleave = BIP;
281 else if(interleave_str == "bil") 285 else if(interleave_str == "bil")
282 - interleave = Envi::BIL; 286 + interleave = BIL;
283 else if(interleave_str == "bsq") 287 else if(interleave_str == "bsq")
284 - interleave = Envi::BSQ; 288 + interleave = BSQ;
285 } 289 }
286 else if(token == "sensor type") 290 else if(token == "sensor type")
287 sensor_type = get_data_str(line); 291 sensor_type = get_data_str(line);
288 else if(token == "byte order") 292 else if(token == "byte order")
289 - byte_order = (Envi::endianType)atoi(get_data_str(line).c_str()); 293 + byte_order = (endianType)atoi(get_data_str(line).c_str());
290 else if(token == "x start") 294 else if(token == "x start")
291 x_start = atof(get_data_str(line).c_str()); 295 x_start = atof(get_data_str(line).c_str());
292 else if(token == "y start") 296 else if(token == "y start")
293 y_start = atof(get_data_str(line).c_str()); 297 y_start = atof(get_data_str(line).c_str());
294 else if(token == "wavelength units") 298 else if(token == "wavelength units")
295 - wavelength_units = get_data_str(line);  
296 -  
297 - //get the next line 299 + wavelength_units = get_data_str(line);
  300 +
  301 + //get the next line
298 getline(file, line); 302 getline(file, line);
299 - }  
300 -  
301 - //make sure the number of bands matches the number of wavelengths  
302 - unsigned int wavelengths = wavelength.size();  
303 - if(bands != wavelengths)  
304 - {  
305 - std::cout<<"ENVI Header Error -- Number of wavelengths doesn't match the number of bands. Bands = "<<bands<<", Wavelengths = "<<wavelength.size()<<std::endl;  
306 - exit(1); 303 + }
  304 +
  305 + //make sure the number of bands matches the number of wavelengths
  306 + unsigned int wavelengths = wavelength.size();
  307 + if(bands != wavelengths)
  308 + {
  309 + std::cout<<"ENVI Header Error -- Number of wavelengths doesn't match the number of bands. Bands = "<<bands<<", Wavelengths = "<<wavelength.size()<<std::endl;
  310 + exit(1);
307 } 311 }
308 312
309 //close the file 313 //close the file
310 - file.close();  
311 -  
312 - //set the file name  
313 - name = filename;  
314 - 314 + file.close();
  315 +
  316 + //set the file name
  317 + name = filename;
  318 +
315 return true; 319 return true;
316 } 320 }
317 321
@@ -334,11 +338,11 @@ struct EnviHeader @@ -334,11 +338,11 @@ struct EnviHeader
334 outfile<<"file type = "<<file_type<<std::endl; 338 outfile<<"file type = "<<file_type<<std::endl;
335 outfile<<"data type = "<<data_type<<std::endl; 339 outfile<<"data type = "<<data_type<<std::endl;
336 outfile<<"interleave = "; 340 outfile<<"interleave = ";
337 - if(interleave == Envi::BIP) 341 + if(interleave == BIP)
338 outfile<<"bip"; 342 outfile<<"bip";
339 - if(interleave == Envi::BIL) 343 + if(interleave == BIL)
340 outfile<<"bil"; 344 outfile<<"bil";
341 - if(interleave == Envi::BSQ) 345 + if(interleave == BSQ)
342 outfile<<"bsq"; 346 outfile<<"bsq";
343 outfile<<std::endl; 347 outfile<<std::endl;
344 outfile<<"sensor type = "<<sensor_type<<std::endl; 348 outfile<<"sensor type = "<<sensor_type<<std::endl;
@@ -369,7 +373,7 @@ struct EnviHeader @@ -369,7 +373,7 @@ struct EnviHeader
369 } 373 }
370 374
371 void save() 375 void save()
372 - { 376 + {
373 //std::cout<<"ENVI Header Name: "<<name<<std::endl; 377 //std::cout<<"ENVI Header Name: "<<name<<std::endl;
374 save(name); 378 save(name);
375 } 379 }
@@ -379,27 +383,27 @@ struct EnviHeader @@ -379,27 +383,27 @@ struct EnviHeader
379 { 383 {
380 switch(data_type) 384 switch(data_type)
381 { 385 {
382 - case Envi::int8: //1 = 8-bit byte 386 + case int8: //1 = 8-bit byte
383 return 1; 387 return 1;
384 - case Envi::int16: //16-bit signed integer  
385 - case Envi::uint16: //16-bit unsigned integer 388 + case int16: //16-bit signed integer
  389 + case uint16: //16-bit unsigned integer
386 return 2; 390 return 2;
387 - case Envi::int32: //32-bit signed long integer  
388 - case Envi::float32: //32-bit floating point  
389 - case Envi::uint32: //32-bit unsigned long integer 391 + case int32: //32-bit signed long integer
  392 + case float32: //32-bit floating point
  393 + case uint32: //32-bit unsigned long integer
390 return 4; 394 return 4;
391 - case Envi::float64: //64-bit double-precision floating point  
392 - case Envi::complex32: //32-bit complex value  
393 - case Envi::int64: //64-bit signed long integer  
394 - case Envi::uint64: //64-bit unsigned long integer 395 + case float64: //64-bit double-precision floating point
  396 + case complex32: //32-bit complex value
  397 + case int64: //64-bit signed long integer
  398 + case uint64: //64-bit unsigned long integer
395 return 8; 399 return 8;
396 - case Envi::complex64: //64-bit complex value 400 + case complex64: //64-bit complex value
397 return 16; 401 return 16;
398 default: 402 default:
399 return 0; 403 return 0;
400 } 404 }
401 405
402 } 406 }
403 -}; //end EnviHeader  
404 -  
405 -#endif 407 +}; //end EnviHeader
  408 +}
  409 +#endif