Commit dc8eb8aa7ab000475a4728408c5a69f1e5540e96

Authored by David Mayerich
1 parent 6a46c8ff

added band trimming to ENVI objects

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
... ...