OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimBandSelector.cpp
Go to the documentation of this file.
1 //*******************************************************************
2 //
3 // License: MIT
4 //
5 // Author: Garrett Potts
6 //
7 // Description:
8 //
9 // Contains class declaration for ossimBandSelector.
10 //
11 //*******************************************************************
12 // $Id$
13 
15 #include <ossim/base/ossimTrace.h>
23 #include <iostream>
24 #include <algorithm>
25 
26 static ossimTrace traceDebug("ossimBandSelector:debug");
27 
29 
31  :
33  m_tile(0),
34  m_outputBandList(0),
35  m_withinRangeFlag(ossimBandSelectorWithinRangeFlagState_NOT_SET),
36  m_passThroughFlag(false),
37  m_delayLoadRgbFlag(false),
38  m_inputIsSelectable(false)
39 {
40 // theEnableFlag = false; // Start off disabled.
41  theEnableFlag = true;
42 }
43 
45 {
46  m_tile = 0;
47 }
48 
50  const ossimIrect& tileRect,
51  ossim_uint32 resLevel)
52 {
53  if (!theInputConnection)
54  {
56  }
57 
58  // Get the tile from the source.
60 
61 
63  {
64  return t; // This tile source bypassed, return the input tile source.
65  }
66 
67  if(!m_tile.valid()) // First time through, might not be initialized...
68  {
69  allocate();
70  if (!m_tile.valid())
71  {
72  // Should never happen...
73  return t; // initialize failed.
74  }
75  }
76 
77  m_tile->setImageRectangle(tileRect);
79  {
83  }
85  {
86  m_tile->makeBlank();
87  return m_tile;
88  }
89 
90  if ( !t.valid() ||
91  (t->getDataObjectStatus() == OSSIM_EMPTY) ||
93  {
94  //---
95  // Since we're enabled, we must return our tile not "t" so the
96  // correct number of bands goes through the chain.
97  //---
98  m_tile->makeBlank();
99  return m_tile;
100  }
101 
102  // Copy selected bands to our tile.
103  for ( ossim_uint32 i = 0; i < m_outputBandList.size(); ++i)
104  {
105  m_tile->assignBand(t.get(), m_outputBandList[i], i);
106  }
107 
108  m_tile->validate();
109 
110  return m_tile;
111 }
112 
114 {
115  m_outputBandList.clear();
116  m_delayLoadRgbFlag = true;
117  initialize();
118 }
119 
120 void ossimBandSelector::setOutputBandList( const vector<ossim_uint32>& outputBandList,
121  bool disablePassThru)
122 {
123  if ( outputBandList.size() )
124  {
125  m_outputBandList = outputBandList; // Assign the new list.
126  m_passThroughFlag = false; // Assume no pass thru first
127  if ( !disablePassThru )
128  {
129  bool setBands = false;
131  if ( ih.valid() )
132  {
133  // Our input is a single image chain that can do band selection.
134  if ( ih->setOutputBandList( outputBandList ) )
135  {
136  m_passThroughFlag = true;
137  setBands = true;
138  m_tile = 0; // Don't need.
139  }
140  }
141 
142  if ( setBands == false )
143  {
144  if ( m_tile.valid() )
145  {
146  // Check the tile band size and scalar.
147  if ( ( m_tile->getNumberOfBands() != outputBandList.size() ) ||
149  {
150  m_tile = 0; // Force an allocate call next getTile.
151  }
152  }
155  //theOrderedCorrectlyFlag = isOrderedCorrectly();
156  }
157  }
158  }
159 }
160 
162 {
163  ossim_uint32 bands;
164 
165  if(isSourceEnabled())
166  {
167  bands = static_cast<ossim_uint32>(m_outputBandList.size());
168  }
169  else
170  {
171  //---
172  // Note:
173  // This returns theInputConnection->getNumberOfOutputBands() which is our
174  // input. Calling ossimBandSelector::getNumberOfInputBands() will produce
175  // an error if we are bypassed due to a band selectable image handler.
176  //---
178  }
179 
180  return bands;
181 }
182 
184 {
185  ossim_uint32 bands;
186 
187  // See if we have a single image chain with band selectable image handler.
189  if ( ih.valid() )
190  {
191  bands = ih->getNumberOfInputBands();
192  }
193  else
194  {
196  }
197 
198  return bands;
199 }
200 
201 
203 {
204  if(traceDebug())
205  {
206  ossimNotify(ossimNotifyLevel_WARN) << "ossimBandSelector::initialize() entered...\n";
207  }
208 
209  // Base class will recapture "theInputConnection".
211 
213 
215  {
216  if ( !m_outputBandList.size() )
217  {
218  // First time through...
219  if ( m_delayLoadRgbFlag )
220  {
221  //---
222  // "bands" key was set to "rgb" or "default" in loadState but there
223  // was not a connection to derive rgb bands from image handler.
224  //---
225  if ( getRgbBandList( m_outputBandList ) == false )
226  {
227  //---
228  // Could not derive from input. Assuming caller wanted three bands.
229  // Call to checkPassThrough()->outputBandsWithinInputRange()
230  // will check the range of output band list.
231  //---
233  {
234  m_outputBandList.resize(3);
235  m_outputBandList[0] = 0;
236  m_outputBandList[1] = 1;
237  m_outputBandList[2] = 2;
238  }
239  else
240  {
241  m_outputBandList.resize(1);
242  m_outputBandList[0] = 0;
243  }
244  }
245 
246  m_delayLoadRgbFlag = false; // clear flag.
247  }
248 
249  if ( !m_outputBandList.size() )
250  {
251  // Set the output band list to input if not set above.
253  }
254 
255  if( m_outputBandList.size() )
256  {
257  // Call to setOutputBandList configures band selector.
259  }
260 
261  } // if ( !m_outputBandList.size() )
262 
263  } // if(theInputConnection)
264 
265  if ( !isSourceEnabled() )
266  {
267  m_tile = 0;
268  }
269 
270  if(traceDebug())
271  {
272  ossimNotify(ossimNotifyLevel_WARN) << "ossimBandSelector::initialize() exited...\n";
273  }
274 }
275 
277 {
278  //initialize(); // Update the connection.
279  //theOrderedCorrectlyFlag = isOrderedCorrectly();
281  m_tile->initialize();
282 }
283 
285 {
287  if(result)
288  {
289  // if I am not marked to pass information on through then enable me
290  result = !m_passThroughFlag;
291  }
292 
293  return result;
294 }
295 
297 {
299  {
300  if (isSourceEnabled())
301  {
302  if(band < m_outputBandList.size())
303  {
304  return theInputConnection->
306  }
307  else
308  {
309  return theInputConnection->getMinPixelValue(band);
310  }
311  }
312  else
313  {
314  return theInputConnection->getMinPixelValue(band);
315  }
316  }
317  return 0;
318 }
319 
321 {
323  {
324  if (isSourceEnabled())
325  {
326  if(band < m_outputBandList.size())
327  {
328  return theInputConnection->
330  }
331  else
332  {
334  }
335  }
336  else
337  {
339  }
340  }
341 
342  return 0;
343 }
344 
346 {
348  {
349  if (isSourceEnabled())
350  {
351  if(band < m_outputBandList.size())
352  {
353  return theInputConnection->
355  }
356  else
357  {
358  return theInputConnection->getMaxPixelValue(band);
359  }
360  }
361  else
362  {
363  return theInputConnection->getMaxPixelValue(band);
364  }
365  }
366  return 1.0/DBL_EPSILON;
367 }
368 
370  const char* prefix)const
371 {
372  ossimString temp;
373 
374  kwl.add(prefix,
376  static_cast<int>(m_outputBandList.size()),
377  true);
378 
379  ossimString bandsString;
380  ossim::toSimpleStringList(bandsString,
382  kwl.add(prefix,
384  bandsString,
385  true);
386 /*
387  for(ossim_uint32 counter = 0; counter < m_outputBandList.size();counter++)
388  {
389  temp = ossimKeywordNames::BAND_KW;
390  temp += ossimString::toString(counter+1);
391 
392  kwl.add(prefix,
393  temp.c_str(),
394  ossimString::toString(m_outputBandList[counter]+1).c_str());
395  }
396 */
397  return ossimImageSourceFilter::saveState(kwl, prefix);
398 }
399 
401  const char* prefix)
402 {
403  bool result = false;
404 
406 
407  m_outputBandList.clear();
408 
409  ossimString copyPrefix = prefix;
410 
411  ossimString bands = kwl.find(prefix, ossimKeywordNames::BANDS_KW);
412  if(!bands.empty())
413  {
414  ossimString bs = bands;
415  bs.downcase();
416  if ( (bs == "rgb" ) || (bs == "default"))
417  {
418  // Flag initialize() to set the band list on first connection.
419  m_delayLoadRgbFlag = true;
420  }
421  else
422  {
423  // Load from key:value, e.g. bands:(2,1,0)
425  result = true;
426  }
427  }
428  else
429  {
430  ossimString regExpression = ossimString("^(") + copyPrefix + "band[0-9]+)";
431 
432  vector<ossimString> keys = kwl.getSubstringKeyList( regExpression );
433  long numberOfBands = (long)keys.size();
434  ossim_uint32 offset = (ossim_uint32)(copyPrefix+"band").size();
435  std::vector<int>::size_type idx = 0;
436  std::vector<int> numberList(numberOfBands);
437  for(idx = 0; idx < keys.size();++idx)
438  {
439  ossimString numberStr(keys[idx].begin() + offset,
440  keys[idx].end());
441  numberList[idx] = numberStr.toInt();
442  }
443  std::sort(numberList.begin(), numberList.end());
444  for(idx=0;idx < numberList.size();++idx)
445  {
446  const char* bandValue =
447  kwl.find(copyPrefix,
448  ("band"+ossimString::toString(numberList[idx])).c_str());
449  m_outputBandList.push_back( ossimString(bandValue).toLong()-1);
450  }
451  result = true;
452  }
453 
454  initialize();
455 
456  return result;
457 }
458 
460 {
462 
463  // check if marked with improper bands
465  return;
466 
468  {
469  std::vector<ossim_uint32> inputList;
471 
472  if ( inputList.size() == m_outputBandList.size() )
473  {
474  const std::vector<ossim_uint32>::size_type SIZE = m_outputBandList.size();
475 
476  std::vector<ossim_uint32>::size_type i = 0;
477  while (i < SIZE)
478  {
479  if ( inputList[i] != m_outputBandList[i] )
480  {
481  break;
482  }
483  ++i;
484  }
485  if (i == SIZE)
486  {
487  m_passThroughFlag = true;
488  }
489  }
490  }
491  else
492  {
493  if(traceDebug())
494  {
495  ossimNotify(ossimNotifyLevel_WARN) << "ossimBandSelector::isOrderedCorrectly() ERROR: "
496  "Method called prior to initialization!\n";
497  }
498  }
499 
500 }
501 
503 {
504  bool result = false;
505 
507  {
508  result = true;
509  const ossim_uint32 HIGHEST_BAND = getNumberOfInputBands() - 1;
510  const ossim_uint32 OUTPUT_BANDS = (ossim_uint32)m_outputBandList.size();
511  for (ossim_uint32 i=0; i<OUTPUT_BANDS; ++i)
512  {
513  if (m_outputBandList[i] > HIGHEST_BAND)
514  {
515  if(traceDebug())
516  {
518  << "ossimBandSelector::outputBandsWithinInputRange() ERROR:"
519  << "Output band greater than highest input band. "
520  << m_outputBandList[i] << " > " << HIGHEST_BAND << "."
521  << std::endl;
522  }
523  result = false;
524  break;
525  }
526  }
527  }
528  else
529  {
530  if(traceDebug())
531  {
533  << "ossimBandSelector::outputBandsWithinInputRange() ERROR:"
534  << "Method called prior to initialization!" << std::endl;
535  }
536  }
537  return result;
538 }
539 
540 void ossimBandSelector::getOutputBandList(std::vector<ossim_uint32>& bandList) const
541 {
542  if ( isSourceEnabled()&&m_outputBandList.size() )
543  {
544  bandList = m_outputBandList;
545  }
546  else if (theInputConnection)
547  {
549  }
550  else
551  {
552  bandList.clear();
553  }
554 }
555 
557 {
558  return ossimString("Band Selector, maps an input band to the output band.");
559 }
560 
562 {
563  return ossimString("Band Selector");
564 }
565 
567 {
568  if( property.valid() )
569  {
570  if(property->getName() == "bands")
571  {
572  std::vector<ossim_uint32> selection;
573  if(ossim::toSimpleVector(selection, property->valueToString()))
574  {
575  m_outputBandList = selection;
577  }
578  }
579  else if(property->getName() == "bandSelection")
580  {
581  ossimString str = property->valueToString();
582  std::vector<ossimString> str_vec;
583  std::vector<ossim_uint32> int_vec;
584 
585  str.split( str_vec, " " );
586 
587  for ( ossim_uint32 i = 0; i < str_vec.size(); ++i )
588  {
589  if(!str_vec[i].empty())
590  {
591  int_vec.push_back( str_vec[i].toUInt32() );
592  }
593  }
594  setOutputBandList( int_vec );
595  }
596  else
597  {
599  }
600  }
601 }
602 
604 {
605  if( name == "bands" )
606  {
607  ossimString bandsString;
608  ossim::toSimpleStringList(bandsString,
610  ossimStringProperty* stringProp = new ossimStringProperty(name, bandsString);
611 
612  stringProp->clearChangeType();
613  stringProp->setReadOnlyFlag(false);
614  stringProp->setCacheRefreshBit();
615 
616  return stringProp;
617  }
618  else if( name == "bandSelection" )
619  {
620  std::vector<ossim_uint32> bands;
621 
622  getOutputBandList( bands );
623 
624  std::vector<ossimString> bandNames;
625 
626  for(ossim_uint32 i = 0; i < bands.size(); i++)
627  {
628  bandNames.push_back( ossimString::toString( bands[i] ) );
629  }
630 
631  ossimString str;
632 
633  str.join( bandNames, " " );
634 
635  ossimStringProperty* stringProp = new ossimStringProperty(name, str);
636 
637  stringProp->clearChangeType();
638  stringProp->setReadOnlyFlag(false);
639  stringProp->setCacheRefreshBit();
640 
641  return stringProp;
642  }
643 
645 }
646 
647 void ossimBandSelector::getPropertyNames(std::vector<ossimString>& propertyNames)const
648 {
650  propertyNames.push_back("bands");
651 }
652 
654 {
656 
657  if ( theInputConnection )
658  {
663  ossimTypeNameVisitor visitor(ossimString("ossimImageHandler"),
664  true,
666  ossimTypeNameVisitor bandSelectorVisitor(ossimString("ossimBandSelector"),
667  true,
669 
670  theInputConnection->accept(visitor);
671  theInputConnection->accept(bandSelectorVisitor);
672  // if there is a band selector before us then do not
673  // set the image handler
674  if(bandSelectorVisitor.getObjects().size() < 1)
675  {
676  // If there are multiple image handlers, e.g. a mosaic do not uses.
677  if ( visitor.getObjects().size() == 1 )
678  {
679  ih = visitor.getObjectAs<ossimImageHandler>( 0 );
680  if ( ih.valid() )
681  {
682  if ( ih->isBandSelector() == false )
683  {
684  ih = 0;
685  }
686  }
687  }
688 
689  }
690 
691  } // Matches: if ( theInputConnection )
692  return ih;
693 
694 } // End: ossimBandSelector::getBandSelectableImageHandler()
695 
696 bool ossimBandSelector::getRgbBandList(std::vector<ossim_uint32>& bandList) const
697 {
698  bool result = false;
699 
700  if ( theInputConnection )
701  {
702  ossimTypeNameVisitor visitor(ossimString("ossimImageHandler"),
703  true,
705 
706  theInputConnection->accept(visitor);
707 
708  // If there are multiple image handlers, e.g. a mosaic do not uses.
709  if ( visitor.getObjects().size() == 1 )
710  {
712  if ( ih.valid() )
713  {
714  result = ih->getRgbBandList( bandList );
715  }
716  }
717 
718  } // Matches: if ( theInputConnection )
719 
720  return result;
721 
722 } // End: ossimBandSelector::getRgbBandList( ... )
virtual void valueToString(ossimString &valueResult) const =0
virtual bool isSourceEnabled() const
Definition: ossimSource.cpp:79
void checkPassThrough()
Will check all combinations of the band list to see if its.
ossimRefPtr< ossimImageData > m_tile
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=NULL)
Method to the load (recreate) the state of an object from a keyword list.
virtual void setProperty(ossimRefPtr< ossimProperty > property)
virtual ossim_uint32 getNumberOfInputBands() const
virtual ossim_uint32 getNumberOfBands() const
virtual double getNullPixelValue(ossim_uint32 band=0) const
Each band has a null pixel associated with it.
virtual void setImageRectangle(const ossimIrect &rect)
const ossimString & join(const std::vector< ossimString > &stringList, const ossimString &separator)
Represents serializable keyword/value map.
virtual ossim_uint32 getNumberOfOutputBands() const
Returns the number of bands in a tile returned from this TileSource.
bool valid() const
Definition: ossimRefPtr.h:75
const char * find(const char *key) const
static ossimString toString(bool aValue)
Numeric to string methods.
virtual bool isSourceEnabled() const
void toSimpleStringList(ossimString &result, const std::vector< T > &valuesList)
This will output a vector of values inst a string.
Definition: ossimCommon.h:484
void split(std::vector< ossimString > &result, const ossimString &separatorList, bool skipBlankFields=false) const
Splits this string into a vector of strings (fields) using the delimiter list specified.
virtual ossimDataObjectStatus getDataObjectStatus() const
void allocate()
Called on first getTile, will initialize all data needed.
virtual void setReadOnlyFlag(bool flag)
virtual double getMinPixelValue(ossim_uint32 band=0) const
Returns the min pixel of the band.
virtual void initialize()
Initialize the data buffer.
ossimRefPtr< ossimImageHandler > getBandSelectableImageHandler() const
Finds and returns band selectable image handler.
bool toSimpleVector(std::vector< T > &result, const ossimString &stringOfPoints)
Definition: ossimCommon.h:537
virtual double getMinPixelValue(ossim_uint32 band=0) const
Returns the min pixel of the band.
virtual void assignBand(const ossimImageData *data, ossim_uint32 source_band, ossim_uint32 output_band)
void add(const char *prefix, const ossimKeywordlist &kwl, bool overwrite=true)
virtual ossimString getShortName() const
virtual void getOutputBandList(std::vector< ossim_uint32 > &bandList) const
Initializes bandList.
void clearChangeType()
static ossimImageDataFactory * instance()
virtual ossimString getLongName() const
virtual ossim_uint32 getNumberOfInputBands() const
Returns the number of input bands.
virtual ossimDataObjectStatus validate() const
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
virtual void getPropertyNames(std::vector< ossimString > &propertyNames) const
virtual double getMaxPixelValue(ossim_uint32 band=0) const
Returns the max pixel of the band.
ossimImageSource * theInputConnection
unsigned int ossim_uint32
static const char * NUMBER_OUTPUT_BANDS_KW
virtual bool getRgbBandList(std::vector< ossim_uint32 > &bandList) const
Convenience method to get the zero based rgb output band list.
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=NULL) const
Method to save the state of an object to a keyword list.
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
static ossimString downcase(const ossimString &aString)
Definition: ossimString.cpp:48
virtual ossimRefPtr< ossimImageData > create(ossimSource *owner, ossimScalarType scalar, ossim_uint32 bands=1) const
#define DBL_EPSILON
static const char * BANDS_KW
virtual bool isBandSelector() const
Indicates whether or not the image handler can control output band selection via the setOutputBandLis...
virtual void initialize()
ossimBandSelectorWithinRangeFlagState m_withinRangeFlag
std::vector< ossimString > getSubstringKeyList(const ossimString &regularExpression) const
virtual ossimRefPtr< ossimImageData > getTile(const ossimIrect &tileRect, ossim_uint32 resLevel=0)
virtual ossimScalarType getScalarType() const
virtual void makeBlank()
Initializes data to null pixel values.
T * getObjectAs(ossim_uint32 idx=0)
Definition: ossimVisitor.h:64
virtual ossimScalarType getOutputScalarType() const
This will be used to query the output pixel type of the tile source.
This class defines an abstract Handler which all image handlers(loaders) should derive from...
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of an object to a keyword list.
virtual double getMaxPixelValue(ossim_uint32 band=0) const
Returns the max pixel of the band.
virtual void setThreeBandRgb()
Will set to three bands (rgb) out.
virtual void setOutputBandList(const vector< ossim_uint32 > &outputBandList, bool disablePassThru=false)
Sets the output band list.
bool getRgbBandList(std::vector< ossim_uint32 > &bandList) const
Attempts to derive rgb bands from image handler to the left of the band selector. ...
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
bool empty() const
Definition: ossimString.h:411
std::vector< ossim_uint32 > m_outputBandList
virtual void getPropertyNames(std::vector< ossimString > &propertyNames) const
virtual void accept(ossimVisitor &visitor)
We will add a visitor interface for all connectable objects.
#define RTTI_DEF1(cls, name, b1)
Definition: ossimRtti.h:485
virtual void getOutputBandList(std::vector< ossim_uint32 > &bandList) const
Initializes bandList to the zero based order of output bands.
bool outputBandsWithinInputRange() const
virtual ossim_uint32 getNumberOfInputBands() const =0
virtual bool setOutputBandList(const std::vector< ossim_uint32 > &band_list)
If the image handler "isBandSeletor()" then the band selection of the output chip can be controlled...
virtual ossim_uint32 getNumberOfOutputBands() const
Returns the number of bands in a tile returned from this TileSource.
virtual double getNullPixelValue(ossim_uint32 band=0) const
Each band has a null pixel associated with it.
virtual void setProperty(ossimRefPtr< ossimProperty > property)
Override base class so that a disableSource event does not reinitialize the object and enable itself...
int toInt() const
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
void setCacheRefreshBit()
const ossimString & getName() const
virtual ossimRefPtr< ossimImageData > getTile(const ossimIpt &origin, ossim_uint32 resLevel=0)