Commit b31c02ebf337c0fb2fedefd203ef999cf061ed4a

Authored by David Mayerich
1 parent 66304f4f

added a --select feature that creates a new ENVI file from individual bands

stim/envi/bil.h
... ... @@ -462,6 +462,11 @@ public:
462 462 }*/
463 463 }
464 464  
  465 + bool select(std::string outfile, std::vector<double> bandlist, unsigned char* mask = NULL, bool PROGRESS = NULL) {
  466 + std::cout << "ERROR: select() not implemented for BIL" << std::endl;
  467 + exit(1);
  468 + }
  469 +
465 470 /// Convert the current BIL file to a BSQ file with the specified file name.
466 471  
467 472 /// @param outname is the name of the output BSQ file to be saved to disk.
... ...
stim/envi/bip.h
... ... @@ -392,6 +392,50 @@ public:
392 392 }
393 393 }
394 394  
  395 + /// This function loads a specified set of bands and saves them into a new output file
  396 + bool select(std::string outfile, std::vector<double> bandlist, unsigned char* mask = NULL, bool PROGRESS = false) {
  397 + std::ofstream target(outfile.c_str(), std::ios::binary); //open the target binary file
  398 + if (!target) {
  399 + std::cout << "ERROR opening output file: " << outfile << std::endl;
  400 + return false;
  401 + }
  402 + file.seekg(0, std::ios::beg); //move the pointer to the current file to the beginning
  403 +
  404 + size_t B = Z(); //number of spectral components
  405 + size_t XY = X() * Y(); //calculate the number of pixels
  406 + size_t Bout = bandlist.size();
  407 + size_t in_bytes = B * sizeof(T); //number of bytes in a spectrum
  408 + size_t out_bytes = Bout * sizeof(T); //number of bytes in an output spectrum
  409 +
  410 + T* in = (T*)malloc(in_bytes); //allocate space for the input spectrum
  411 + T* out = (T*)malloc(out_bytes); //allocate space for the output spectrum
  412 +
  413 + double wc; //register to store the desired wavelength
  414 + double w0, w1; //registers to store the wavelengths surrounding the given band
  415 + size_t b0, b1; //indices of the bands surrounding the specified wavelength
  416 + for (size_t xy = 0; xy < XY; xy++) { //for each pixel
  417 + //memset(out, 0, out_bytes); //set the spectrum to zero
  418 + if (mask == NULL || mask[xy]) { //if the pixel is masked
  419 + file.read((char*)in, in_bytes); //read an input spectrum
  420 + for (size_t b = 0; b < Bout; b++) { //for each band
  421 + wc = bandlist[b]; //set the desired wavelength
  422 + band_bounds(wc, b0, b1); //get the surrounding bands
  423 + w0 = w[b0]; //get the wavelength for the lower band
  424 + w1 = w[b1]; //get the wavelength for the higher band
  425 + out[b] = lerp(wc, in[b0], w0, in[b1], w1); //interpolate the spectral values to get the desired output value
  426 + }
  427 + }
  428 + else
  429 + file.seekg(Bout, std::ios::cur); //otherwise skip a spectrum
  430 + target.write((char*)out, out_bytes); //output the normalized spectrum
  431 + if (PROGRESS) progress = (double)(xy + 1) / (double)XY * 100; //update the progress
  432 + }
  433 +
  434 + free(in);
  435 + free(out);
  436 + return true;
  437 + }
  438 +
395 439  
396 440 /// Convert the current BIP file to a BIL file with the specified file name.
397 441  
... ...
stim/envi/bsq.h
... ... @@ -380,6 +380,30 @@ public:
380 380  
381 381 }
382 382  
  383 + bool select(std::string outfile, std::vector<double> bandlist, unsigned char* mask = NULL, bool PROGRESS = false) {
  384 + std::ofstream out(outfile.c_str(), std::ios::binary); //open the output file
  385 + if (!out) {
  386 + std::cout << "ERROR opening output file: " << outfile << std::endl;
  387 + return false;
  388 + }
  389 + file.seekg(0, std::ios::beg); //move the pointer to the current file to the beginning
  390 +
  391 + size_t B = Z(); //calculate the number of bands
  392 + size_t XY = X() * Y(); //calculate the number of pixels in a band
  393 + size_t in_bytes = XY * sizeof(T); //calculate the size of a band in bytes
  394 +
  395 + T* in = (T*)malloc(in_bytes); //allocate space for the band image
  396 + size_t nb = bandlist.size(); //get the number of bands in the output image
  397 + for (size_t b = 0; b < nb; b++) {
  398 + band(in, bandlist[b]); //get the band associated with the given wavelength
  399 + out.write((char*)in, in_bytes); //write the band to the output file
  400 + if (PROGRESS) progress = (double)(b + 1) / (double)bandlist.size() * 100;
  401 + }
  402 + out.close();
  403 + free(in);
  404 + return true;
  405 + }
  406 +
383 407 size_t readlines(T* dest, size_t start, size_t n){
384 408 return hsi<T>::read(dest, 0, start, 0, X(), n, Z());
385 409 }
... ...
stim/envi/envi.h
... ... @@ -562,6 +562,41 @@ public:
562 562 }
563 563 }
564 564  
  565 + bool select(std::string outfile, std::vector<double> bandlist, unsigned char* MASK = NULL, bool PROGRESS = false) {
  566 + stim::envi_header new_header = header; //copy all of the data from the current header file to the new one
  567 + new_header.bands = bandlist.size(); //the number of bands in the new file is equal to the number of bands provided by the user
  568 + new_header.wavelength = bandlist; //the wavelength values in the output file are the same as those specified by the user
  569 + new_header.band_names.empty(); //no band names will be provided in the output file
  570 + new_header.save(outfile + ".hdr"); //save the output header file
  571 +
  572 + if (header.interleave == envi_header::BSQ) { //if the infile is bip file
  573 + if (header.data_type == envi_header::float32)
  574 + return ((bsq<float>*)file)->select(outfile, bandlist, MASK, PROGRESS);
  575 + else if (header.data_type == envi_header::float64)
  576 + return ((bsq<double>*)file)->select(outfile, bandlist, MASK, PROGRESS);
  577 + else
  578 + std::cout << "ERROR: unidentified data type" << std::endl;
  579 + }
  580 + else if (header.interleave == envi_header::BIL) { //if the infile is bip file
  581 + if (header.data_type == envi_header::float32)
  582 + return ((bil<float>*)file)->select(outfile, bandlist, MASK, PROGRESS);
  583 + else if (header.data_type == envi_header::float64)
  584 + return ((bil<double>*)file)->select(outfile, bandlist, MASK, PROGRESS);
  585 + else
  586 + std::cout << "ERROR: unidentified data type" << std::endl;
  587 + }
  588 + else if (header.interleave == envi_header::BIP) { //if the infile is bip file
  589 + if (header.data_type == envi_header::float32)
  590 + return ((bip<float>*)file)->select(outfile, bandlist, MASK, PROGRESS);
  591 + else if (header.data_type == envi_header::float64)
  592 + return ((bip<double>*)file)->select(outfile, bandlist, MASK, PROGRESS);
  593 + else
  594 + std::cout << "ERROR: unidentified data type" << std::endl;
  595 + }
  596 +
  597 + return false;
  598 + }
  599 +
565 600 /// Performs piecewise linear baseline correction of a hyperspectral file/
566 601  
567 602 /// @param outfile is the file name for the baseline corrected output
... ...
stim/envi/hsi.h
... ... @@ -55,6 +55,7 @@ protected:
55 55 return n; //return the number of masked pixels
56 56 }
57 57  
  58 + //perform linear interpolation between two bands
58 59 T lerp(double w, T low_v, double low_w, T high_v, double high_w){
59 60 if(low_w == high_w) return low_v; //if the interval is of zero length, just return one of the bounds
60 61 double alpha = (w - low_w) / (high_w - low_w); //calculate the interpolation factor
... ...