Commit e8eb202fd18514f4a6ecb0e7343d9c3c0060cbc0

Authored by David Mayerich
1 parent 6aa04ba2

added a new ENVI interface

envi/bil.h
1 1 #ifndef STIM_BIL_H
2 2 #define STIM_BIL_H
3 3  
4   -#include "../envi/envi.h"
  4 +#include "../envi/envi_header.h"
5 5 #include "../envi/binary.h"
6 6 #include <cstring>
7 7 #include <utility>
... ... @@ -14,7 +14,7 @@ class bil: public binary&lt;T&gt; {
14 14  
15 15 protected:
16 16  
17   - envi header;
  17 + envi_header header;
18 18  
19 19 public:
20 20  
... ... @@ -353,7 +353,7 @@ public:
353 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 357 header.save(headername);
358 358  
359 359 free(p);
... ... @@ -387,7 +387,7 @@ public:
387 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 391 header.save(headername);
392 392  
393 393 free(p);
... ...
envi/binary.h
... ... @@ -3,7 +3,7 @@
3 3 #ifndef RTS_BINARY_H
4 4 #define RTS_BINARY_H
5 5  
6   -#include "../envi/envi.h"
  6 +#include "../envi/envi_header.h"
7 7 #include "../math/vector.h"
8 8 #include <fstream>
9 9 #include <sys/stat.h>
... ...
envi/bip.h
1   -#include "../envi/envi.h"
  1 +#ifndef STIM_BIP_H
  2 +#define STIM_BIP_H
  3 +
  4 +#include "../envi/envi_header.h"
2 5 #include "../envi/bil.h"
3 6 #include "../envi/binary.h"
4 7 #include <cstring>
... ... @@ -12,7 +15,7 @@ class bip: public binary&lt;T&gt; {
12 15  
13 16 protected:
14 17  
15   - envi header;
  18 + envi_header header;
16 19  
17 20 public:
18 21  
... ... @@ -463,7 +466,7 @@ public:
463 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 470 header.save(headername);
468 471  
469 472 free(p);
... ... @@ -480,3 +483,5 @@ public:
480 483  
481 484 };
482 485 }
  486 +
  487 +#endif
... ...
envi/bsq.h
1   -#include "../envi/envi.h"
  1 +#ifndef STIM_BSQ_H
  2 +#define STIM_BSQ_H
  3 +
  4 +#include "../envi/envi_header.h"
2 5 #include "../envi/binary.h"
  6 +#include "../envi/bil.h"
3 7 #include <cstring>
4 8 #include <utility>
  9 +#include <vector>
5 10  
6 11 namespace rts{
7 12  
... ... @@ -11,31 +16,38 @@ class bsq: public binary&lt;T&gt; {
11 16  
12 17 protected:
13 18  
14   - envi header;
  19 + //envi_header header;
  20 +
  21 + std::vector<double> w; //band wavelengths
15 22  
16 23 public:
17 24  
18 25 using binary<T>::open;
19 26 using binary<T>::file;
20 27 using binary<T>::getSlice;
  28 + using binary<T>::R;
21 29  
22 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 34 std::cout<<"ERROR: unable to load header file: "<<headername<<std::endl;
27 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 47 //save one band of the file into the memory, and return the pointer
36 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 51 std::cout<<"ERROR: page out of range"<<std::endl;
40 52 return false;
41 53 }
... ... @@ -46,7 +58,7 @@ public:
46 58  
47 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 63 unsigned page=0; //bands around the wavelength
52 64 T * p1;
... ... @@ -55,28 +67,28 @@ public:
55 67 //get the bands numbers around the wavelength
56 68  
57 69 //if wavelength is smaller than the first one in header file
58   - if ( header.wavelength[page] > wavelength ){
  70 + if ( w[page] > wavelength ){
59 71 band_index(p, page);
60 72 return true;
61 73 }
62 74  
63   - while( header.wavelength[page] < wavelength )
  75 + while( w[page] < wavelength )
64 76 {
65 77 page++;
66 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 81 return true;
70 82 }
71 83 }
72   - if ( wavelength < header.wavelength[page] )
  84 + if ( wavelength < w[page] )
73 85 {
74 86 p1=(T*)malloc( XY * sizeof(T)); //memory allocation
75 87 p2=(T*)malloc( XY * sizeof(T));
76 88 band_index(p1, page - 1);
77 89 band_index(p2, page );
78 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 92 p[i] = (p2[i] - p1[i]) * r + p1[i];
81 93 }
82 94 }
... ... @@ -93,16 +105,16 @@ public:
93 105  
94 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 109 std::cout<<"ERROR: sample or line out of range"<<std::endl;
98 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 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 120 return true;
... ... @@ -118,8 +130,8 @@ public:
118 130 std::string headername = outname + ".hdr"; //the header file name
119 131  
120 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 135 unsigned int S = XY * sizeof(T); //calculate the number of bytes in a band
124 136  
125 137 double ai, bi; //stores the two baseline points wavelength surrounding the current band
... ... @@ -142,11 +154,11 @@ public:
142 154  
143 155  
144 156 //initialize lownum, highnum, low, high
145   - ai=header.wavelength[0];
  157 + ai=w[0];
146 158  
147 159 //if no baseline point is specified at band 0,
148 160 //set the baseline point at band 0 to 0
149   - if(wls[0] != header.wavelength[0]){
  161 + if(wls[0] != w[0]){
150 162 bi = wls[control];
151 163 memset(a, (char)0, S);
152 164 }
... ... @@ -163,7 +175,7 @@ public:
163 175 for(unsigned cii = 0; cii < B; cii++){
164 176  
165 177 //update baseline points, if necessary
166   - if( header.wavelength[cii] >= bi && cii != B - 1) {
  178 + if( w[cii] >= bi && cii != B - 1) {
167 179 //if the high band is now on the last BL point?
168 180 if (control != N-1) {
169 181  
... ... @@ -177,20 +189,20 @@ public:
177 189  
178 190 }
179 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 194 std::swap(a, b); //swap the baseline band pointers
183 195  
184 196 memset(b, (char)0, S); //clear the high band
185 197  
186 198 ai = bi;
187   - bi = header.wavelength[B - 1];
  199 + bi = w[B - 1];
188 200 }
189 201 }
190 202  
191 203 //get the current band
192 204 band_index(c, cii);
193   - ci = header.wavelength[cii];
  205 + ci = w[cii];
194 206  
195 207 //perform the baseline correction
196 208 for(unsigned i=0; i < XY; i++){
... ... @@ -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 219 free(a);
208 220 free(b);
... ... @@ -214,8 +226,9 @@ public:
214 226 // normalize the BSQ file
215 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 232 unsigned int S = XY * sizeof(T); //calculate the number of bytes in a band
220 233  
221 234 std::ofstream target(outname.c_str(), std::ios::binary); //open the target binary file
... ... @@ -239,7 +252,7 @@ public:
239 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 257 free(b);
245 258 free(c);
... ... @@ -272,8 +285,8 @@ public:
272 285 bool bil(std::string outname)
273 286 {
274 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 291 std::ofstream target(outname.c_str(), std::ios::binary);
279 292 std::string headername = outname + ".hdr";
... ... @@ -281,18 +294,18 @@ public:
281 294 T * p; //pointer to the current spectrum
282 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 303 file.seekg(jump, std::ios::cur); //go to the next band
291 304 }
292 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 310 free(p);
298 311 target.close();
... ... @@ -308,4 +321,6 @@ public:
308 321 };
309 322 }
310 323  
  324 +#endif
  325 +
311 326  
... ...
envi/envi.h
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 4 #include <string>
5   -#include <iostream>
  5 +#include <iostream>
6 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 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 22 std::string name;
23 23  
24 24 std::string description;
... ... @@ -27,16 +27,16 @@ struct EnviHeader
27 27 unsigned int lines; //y-axis
28 28 unsigned int bands; //spectral axis
29 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 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 41 double x_start, y_start; //coordinates of the upper-left corner of the image
42 42 std::string wavelength_units; //stored wavelength units
... ... @@ -47,18 +47,17 @@ struct EnviHeader
47 47 std::vector<std::string> band_names; //name for each band in the image
48 48 std::vector<double> wavelength; //wavelength for each band
49 49  
50   - EnviHeader()
51   - {
52   - name = "";
  50 + void init(){
  51 + name = "";
53 52  
54 53 //specify default values for a new or empty ENVI file
55 54 samples = 0;
56 55 lines = 0;
57 56 bands = 0;
58 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 61 x_start = y_start = 0;
63 62 pixel_size[0] = pixel_size[1] = 1;
64 63  
... ... @@ -69,8 +68,15 @@ struct EnviHeader
69 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 80 //trims whitespace from the beginning and end of line
75 81 unsigned int start_i, end_i;
76 82 for(start_i=0; start_i < line.length(); start_i++)
... ... @@ -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 99 //returns a variable name; in this case we look for the '=' sign
95 100 size_t i = line.find_first_of('=');
96 101  
... ... @@ -101,8 +106,7 @@ struct EnviHeader
101 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 110 size_t i = line.find_first_of('=');
107 111  
108 112 std::string result;
... ... @@ -187,15 +191,15 @@ struct EnviHeader
187 191 std::vector<double> get_double_seq(std::string token, std::string sequence)
188 192 {
189 193 //this function returns a sequence of comma-delimited strings
190   - std::vector<double> result;
  194 + std::vector<double> result;
191 195 std::string entry;
192 196 size_t i;
193 197 do
194 198 {
195 199 i = sequence.find_first_of(',');
196   - entry = sequence.substr(0, i);
  200 + entry = sequence.substr(0, i);
197 201 sequence = sequence.substr(i+1);
198   - result.push_back(atof(entry.c_str()));
  202 + result.push_back(atof(entry.c_str()));
199 203 //std::cout<<entry<<" ";
200 204 }while(i != std::string::npos);
201 205  
... ... @@ -208,7 +212,7 @@ struct EnviHeader
208 212 std::ifstream file(filename.c_str());
209 213  
210 214 if(!file)
211   - {
  215 + {
212 216 return false;
213 217 }
214 218  
... ... @@ -219,11 +223,11 @@ struct EnviHeader
219 223 {
220 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 225 exit(1);
222   - }
  226 + }
223 227  
224 228 //for each line in the file, get the token
225   - std::string token;
226   -
  229 + std::string token;
  230 +
227 231 //get a line
228 232 getline(file, line);
229 233 while(file)
... ... @@ -272,46 +276,46 @@ struct EnviHeader
272 276 else if(token == "file type")
273 277 file_type = get_data_str(line);
274 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 280 else if(token == "interleave")
277 281 {
278 282 std::string interleave_str = get_data_str(line);
279 283 if(interleave_str == "bip")
280   - interleave = Envi::BIP;
  284 + interleave = BIP;
281 285 else if(interleave_str == "bil")
282   - interleave = Envi::BIL;
  286 + interleave = BIL;
283 287 else if(interleave_str == "bsq")
284   - interleave = Envi::BSQ;
  288 + interleave = BSQ;
285 289 }
286 290 else if(token == "sensor type")
287 291 sensor_type = get_data_str(line);
288 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 294 else if(token == "x start")
291 295 x_start = atof(get_data_str(line).c_str());
292 296 else if(token == "y start")
293 297 y_start = atof(get_data_str(line).c_str());
294 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 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 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 319 return true;
316 320 }
317 321  
... ... @@ -334,11 +338,11 @@ struct EnviHeader
334 338 outfile<<"file type = "<<file_type<<std::endl;
335 339 outfile<<"data type = "<<data_type<<std::endl;
336 340 outfile<<"interleave = ";
337   - if(interleave == Envi::BIP)
  341 + if(interleave == BIP)
338 342 outfile<<"bip";
339   - if(interleave == Envi::BIL)
  343 + if(interleave == BIL)
340 344 outfile<<"bil";
341   - if(interleave == Envi::BSQ)
  345 + if(interleave == BSQ)
342 346 outfile<<"bsq";
343 347 outfile<<std::endl;
344 348 outfile<<"sensor type = "<<sensor_type<<std::endl;
... ... @@ -369,7 +373,7 @@ struct EnviHeader
369 373 }
370 374  
371 375 void save()
372   - {
  376 + {
373 377 //std::cout<<"ENVI Header Name: "<<name<<std::endl;
374 378 save(name);
375 379 }
... ... @@ -379,27 +383,27 @@ struct EnviHeader
379 383 {
380 384 switch(data_type)
381 385 {
382   - case Envi::int8: //1 = 8-bit byte
  386 + case int8: //1 = 8-bit byte
383 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 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 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 399 return 8;
396   - case Envi::complex64: //64-bit complex value
  400 + case complex64: //64-bit complex value
397 401 return 16;
398 402 default:
399 403 return 0;
400 404 }
401 405  
402 406 }
403   -}; //end EnviHeader
404   -
405   -#endif
  407 +}; //end EnviHeader
  408 +}
  409 +#endif
... ...