Commit dc8eb8aa7ab000475a4728408c5a69f1e5540e96
1 parent
6a46c8ff
added band trimming to ENVI objects
Showing
5 changed files
with
216 additions
and
0 deletions
Show diff stats
stim/envi/bil.h
... | ... | @@ -1098,6 +1098,35 @@ public: |
1098 | 1098 | return true; |
1099 | 1099 | } |
1100 | 1100 | |
1101 | + /// Remove a list of bands from the ENVI file | |
1102 | + | |
1103 | + /// @param outfile is the file name for the output hyperspectral image (with trimmed bands) | |
1104 | + /// @param b is an array of bands to be eliminated | |
1105 | + void trim(std::string outfile, std::vector<size_t> band_array, bool PROGRESS = false){ | |
1106 | + std::ofstream out(outfile.c_str(), std::ios::binary); //open the output file for writing | |
1107 | + file.seekg(0, std::ios::beg); //move to the beginning of the input file | |
1108 | + | |
1109 | + size_t Xb = X() * sizeof(T); //calculate the number of bytes in a line | |
1110 | + T* line = (T*)malloc(Xb); //allocate space for a line | |
1111 | + | |
1112 | + size_t i; //create an index into the band array | |
1113 | + for(size_t y = 0; y < Y(); y++){ //for each Y plane | |
1114 | + i = 0; | |
1115 | + for(size_t b = 0; b < Z(); b++){ //for each band | |
1116 | + if(b != band_array[i]){ //if this band isn't trimmed | |
1117 | + file.read((char*)line, Xb); //read a line | |
1118 | + out.write((char*)line, Xb); //write the line | |
1119 | + } | |
1120 | + else{ | |
1121 | + file.seekg(Xb, std::ios::cur); //if this band is trimmed, skip it | |
1122 | + i++; | |
1123 | + } | |
1124 | + } | |
1125 | + if(PROGRESS) progress = (double)(y+1) / (double)Y() * 100; | |
1126 | + } | |
1127 | + free(line); | |
1128 | + } | |
1129 | + | |
1101 | 1130 | |
1102 | 1131 | /// Close the file. |
1103 | 1132 | bool close(){ | ... | ... |
stim/envi/bip.h
... | ... | @@ -1179,6 +1179,43 @@ public: |
1179 | 1179 | return true; |
1180 | 1180 | } |
1181 | 1181 | |
1182 | + /// Remove a list of bands from the ENVI file | |
1183 | + | |
1184 | + /// @param outfile is the file name for the output hyperspectral image (with trimmed bands) | |
1185 | + /// @param b is an array of bands to be eliminated | |
1186 | + void trim(std::string outfile, std::vector<size_t> band_array, bool PROGRESS = false){ | |
1187 | + | |
1188 | + std::ofstream out(outfile.c_str(), std::ios::binary); //open the output file for writing | |
1189 | + file.seekg(0, std::ios::beg); //move to the beginning of the input file | |
1190 | + | |
1191 | + size_t B = Z(); //calculate the number of elements in a spectrum | |
1192 | + size_t Bdst = Z() - band_array.size(); //calculate the number of elements in an output spectrum | |
1193 | + size_t Bb = B * sizeof(T); //calculate the number of bytes in a spectrum | |
1194 | + size_t XY = X() * Y(); //calculate the number of pixels in the image | |
1195 | + T* src = (T*)malloc(Bb); //allocate space to store an input spectrum | |
1196 | + T* dst = (T*)malloc(Bdst * sizeof(T)); //allocate space to store an output spectrum | |
1197 | + | |
1198 | + size_t i; //index into the band array | |
1199 | + size_t bdst; //index into the output array | |
1200 | + for(size_t xy = 0; xy < XY; xy++){ //for each pixel | |
1201 | + i = 0; | |
1202 | + bdst = 0; | |
1203 | + file.read((char*)src, Bb); //read a spectrum | |
1204 | + for(size_t b = 0; b < B; b++){ //for each band | |
1205 | + if(b != band_array[i]){ //if the band isn't trimmed | |
1206 | + dst[bdst] = src[b]; //copy the band value to the output spectrum | |
1207 | + bdst++; | |
1208 | + } | |
1209 | + else i++; //otherwise increment i | |
1210 | + } | |
1211 | + out.write((char*)dst, Bdst * sizeof(T)); //write the output spectrum | |
1212 | + if(PROGRESS) progress = (double)(xy + 1) / (double) XY * 100; | |
1213 | + } | |
1214 | + free(src); | |
1215 | + free(dst); | |
1216 | + } | |
1217 | + | |
1218 | + | |
1182 | 1219 | |
1183 | 1220 | /// Close the file. |
1184 | 1221 | bool close(){ | ... | ... |
stim/envi/bsq.h
... | ... | @@ -996,6 +996,35 @@ public: |
996 | 996 | return true; |
997 | 997 | } |
998 | 998 | |
999 | + /// Remove a list of bands from the ENVI file | |
1000 | + | |
1001 | + /// @param outfile is the file name for the output hyperspectral image (with trimmed bands) | |
1002 | + /// @param b is an array of bands to be eliminated | |
1003 | + void trim(std::string outfile, std::vector<size_t> band_array, bool PROGRESS = false){ | |
1004 | + | |
1005 | + std::ofstream out(outfile.c_str(), std::ios::binary); //open the output file for writing | |
1006 | + file.seekg(0, std::ios::beg); //move to the beginning of the input file | |
1007 | + | |
1008 | + size_t XY = X() * Y(); //calculate the number of elements in a band | |
1009 | + size_t XYb = XY * sizeof(T); //calculate the number of bytes in a band | |
1010 | + T* temp = (T*)malloc(XYb); //allocate space to store a band | |
1011 | + | |
1012 | + size_t i = 0; //store the first index into the band array | |
1013 | + | |
1014 | + for(size_t b = 0; b < Z(); b++){ //for each band | |
1015 | + if(b != band_array[i]){ //if this band is not trimmed | |
1016 | + file.read((char*)temp, XYb); //read the band | |
1017 | + out.write((char*)temp, XYb); //output the band | |
1018 | + } | |
1019 | + else{ | |
1020 | + file.seekg(XYb, std::ios::cur); //otherwise, skip the band | |
1021 | + i++; | |
1022 | + } | |
1023 | + if(PROGRESS) progress = (double)(b+1) / (double) Z() * 100; | |
1024 | + } | |
1025 | + free(temp); //free the scratch space for the band | |
1026 | + } | |
1027 | + | |
999 | 1028 | |
1000 | 1029 | /// Close the file. |
1001 | 1030 | bool close(){ | ... | ... |
stim/envi/envi.h
... | ... | @@ -1235,6 +1235,64 @@ public: |
1235 | 1235 | return false; |
1236 | 1236 | } |
1237 | 1237 | |
1238 | + /// Remove a list of bands from the ENVI file | |
1239 | + | |
1240 | + /// @param outfile is the file name for the output hyperspectral image (with trimmed bands) | |
1241 | + /// @param b is an array of bands to be eliminated | |
1242 | + void trim(std::string outfile, std::vector<size_t> trimmed, bool PROGRESS = false){ | |
1243 | + | |
1244 | + envi_header h = header; | |
1245 | + h.bands = header.bands - trimmed.size(); //calculate the new number of bands | |
1246 | + if(header.wavelength.size() != 0) | |
1247 | + h.wavelength.resize(h.bands); | |
1248 | + if(header.band_names.size() != 0) | |
1249 | + h.band_names.resize(h.bands); | |
1250 | + size_t it = 0; //allocate an index into the trimmed bands array | |
1251 | + size_t i = 0; | |
1252 | + for(size_t b = 0; b < header.bands; b++){ //for each band | |
1253 | + if(b != trimmed[it]){ | |
1254 | + if(h.wavelength.size()) h.wavelength[i] = header.wavelength[b]; | |
1255 | + if(h.band_names.size()) h.band_names[i] = header.band_names[i]; | |
1256 | + i++; | |
1257 | + } | |
1258 | + else it++; | |
1259 | + } | |
1260 | + h.save(outfile + ".hdr"); | |
1261 | + | |
1262 | + if (header.interleave == envi_header::BSQ){ | |
1263 | + if (header.data_type == envi_header::float32) | |
1264 | + return ((bsq<float>*)file)->trim(outfile, trimmed, PROGRESS); | |
1265 | + else if (header.data_type == envi_header::float64) | |
1266 | + return ((bsq<double>*)file)->trim(outfile, trimmed, PROGRESS); | |
1267 | + else{ | |
1268 | + std::cout << "ERROR: unidentified data type" << std::endl; | |
1269 | + exit(1); | |
1270 | + } | |
1271 | + } | |
1272 | + else if (header.interleave == envi_header::BIL){ | |
1273 | + if (header.data_type == envi_header::float32) | |
1274 | + return ((bil<float>*)file)->trim(outfile, trimmed, PROGRESS); | |
1275 | + else if (header.data_type == envi_header::float64) | |
1276 | + return ((bil<double>*)file)->trim(outfile, trimmed, PROGRESS); | |
1277 | + else{ | |
1278 | + std::cout << "ERROR: unidentified data type" << std::endl; | |
1279 | + exit(1); | |
1280 | + } | |
1281 | + } | |
1282 | + else if (header.interleave == envi_header::BIP){ | |
1283 | + if (header.data_type == envi_header::float32) | |
1284 | + return ((bip<float>*)file)->trim(outfile, trimmed, PROGRESS); | |
1285 | + else if (header.data_type == envi_header::float64) | |
1286 | + return ((bip<double>*)file)->trim(outfile, trimmed, PROGRESS); | |
1287 | + else{ | |
1288 | + std::cout << "ERROR: unidentified data type" << std::endl; | |
1289 | + exit(1); | |
1290 | + } | |
1291 | + } | |
1292 | + | |
1293 | + | |
1294 | + } | |
1295 | + | |
1238 | 1296 | }; |
1239 | 1297 | |
1240 | 1298 | } //end namespace rts | ... | ... |
stim/envi/envi_header.h
... | ... | @@ -6,6 +6,7 @@ |
6 | 6 | #include <fstream> |
7 | 7 | #include <sstream> |
8 | 8 | #include <vector> |
9 | +#include <algorithm> | |
9 | 10 | #include <stdlib.h> |
10 | 11 | |
11 | 12 | //information from an ENVI header file |
... | ... | @@ -431,6 +432,68 @@ struct envi_header |
431 | 432 | std::string interleave_str(){ |
432 | 433 | return interleave_str(interleave); |
433 | 434 | } |
435 | + | |
436 | + /// Convert a wavelength to a band index (or a pair of surrounding band indices) | |
437 | + std::vector<size_t> band_index(double w){ | |
438 | + std::vector<size_t> idx; //create an empty array of indices | |
439 | + if(w < wavelength[0] || w > wavelength[bands-1]) return idx; //if the wavelength range is outside of the file, return an empty array | |
440 | + | |
441 | + for(size_t b = 0; b < bands; b++){ //for each band in the wavelength vector | |
442 | + if(wavelength[b] == w){ //if an exact match is found | |
443 | + idx.push_back(b); //add the band to the array and return it | |
444 | + return idx; | |
445 | + } | |
446 | + if(wavelength[b] >= w){ //if the current wavelength exceeds w | |
447 | + idx.resize(2); | |
448 | + idx[0] = b-1; //push both the previous and current band index | |
449 | + idx[1] = b; | |
450 | + return idx; //return the pair of indices | |
451 | + } | |
452 | + } | |
453 | + return idx; | |
454 | + } | |
455 | + | |
456 | + /// Convert a wavelength range to a list of bands | |
457 | + std::vector<size_t> band_indices(double w0, double w1){ | |
458 | + | |
459 | + size_t idx0 = 0; | |
460 | + size_t idx1 = 0; //declare the interval indices for the band range | |
461 | + | |
462 | + //get the indices for the first wavelength | |
463 | + std::vector<size_t> r; | |
464 | + | |
465 | + if(w0 > wavelength[bands-1] || w1 < wavelength[0]){ | |
466 | + std::cout<<"ERROR in envi_header::band_indices - wavelengths are completely out of range: ["<<w0<<", "<<w1<<"]"<<std::endl; | |
467 | + exit(1); | |
468 | + } | |
469 | + if(w0 < wavelength[0]) //if the lower wavelength is outside the file range | |
470 | + idx0 = 0; //just set it to zero | |
471 | + else{ | |
472 | + r = band_index(w0); | |
473 | + if(r.size() == 1) //if there is an exact match, set the first interval index | |
474 | + idx0 = r[0]; | |
475 | + else | |
476 | + idx0 = r[1]; //otherwise save the highest band index (this is the first band with wavelength > w0) | |
477 | + } | |
478 | + //get the indices for the second wavelength | |
479 | + if(w1 > wavelength[bands-1]) | |
480 | + idx1 = bands-1; | |
481 | + else{ | |
482 | + r = band_index(w1); | |
483 | + if(r.size() == 0) | |
484 | + idx1 = bands - 1; | |
485 | + else | |
486 | + idx1 = r[0]; //take the lowest band index (this is the last band < w1) | |
487 | + } | |
488 | + | |
489 | + size_t n = idx1 - idx0 + 1; //calculate the number of bands in this interval | |
490 | + r.resize(n); //resize the band index array | |
491 | + for(size_t b = 0; b < n; b++){ //for each band in the interval | |
492 | + r[b] = idx0 + b; // insert the band in the array | |
493 | + } | |
494 | + | |
495 | + return r; //return the index array | |
496 | + } | |
434 | 497 | }; //end EnviHeader |
435 | 498 | } |
436 | 499 | #endif | ... | ... |