OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimImageHistogramSource.cpp
Go to the documentation of this file.
1 //*******************************************************************
2 //
3 // License: See LICENSE.txt file in the top level directory.
4 //
5 // Author: Garrett Potts
6 //
7 //*************************************************************************
8 // $Id: ossimImageHistogramSource.cpp 22737 2014-04-16 18:53:57Z gpotts $
9 
15 #include <ossim/base/ossimNotify.h>
16 #include <ossim/base/ossimTrace.h>
17 
18 static ossimTrace traceDebug("ossimImageHistogramSource:debug");
19 
21 
23  :ossimHistogramSource(owner,
24  1, // one input
25  0, // no outputs
26  true, // input list is fixed
27  false),// output can still grow though
28  theHistogramRecomputeFlag(true),
29  theMaxNumberOfResLevels(1),
30  theComputationMode(OSSIM_HISTO_MODE_NORMAL)
31  // theNumberOfTilesToUseInFastMode(100)
32 {
35 
39 }
40 
42 {
44 }
45 
47 {
48  return this;
49 }
50 
52 {
53  return this;
54 }
55 
57 {
58  if(rect != theAreaOfInterest)
59  {
61  }
62  theAreaOfInterest = rect;
63 }
64 
66 {
67  return theAreaOfInterest;
68 }
69 
71 {
72  rect = theAreaOfInterest;
73 }
74 
76 {
78 }
79 
81 {
82  if(number != theMaxNumberOfResLevels)
83  {
85  }
86  theMaxNumberOfResLevels = number;
87 }
88 
90 {
91  if((theAreaOfInterest != rect)||
93  {
94  theAreaOfInterest = rect;
96  }
97 
98  return getHistogram();
99 }
100 
102 {
103  if(!isSourceEnabled())
104  {
105  return theHistogram.valid();
106  }
107 
110  {
112  {
114  if(interface)
115  {
116  theAreaOfInterest = interface->getBoundingRect();
117  }
118  }
119 
120  switch(theComputationMode)
121  {
123  {
125  break;
126  }
128  default:
129  {
131  break;
132  }
133  }
134  }
135 
136  if (needsAborting())
137  {
140  }
141  else
142  {
144  }
145 
146  return true;
147 }
148 
150  const ossimConnectableObject* object)const
151 {
152  return ((myInputIndex==0)&&PTR_CAST(ossimImageSource,
153  object));
154 }
155 
157 {
158  theNumberOfBinsOverride = numberOfBinsOverride;
159 }
160 
162 {
163  theMinValueOverride = minValueOverride;
164 }
166 {
167  theMaxValueOverride = maxValueOverride;
168 }
169 
171 {
172  return theComputationMode;
173 }
174 
176 {
177  theComputationMode = mode;
178 }
179 
181 {
183 }
184 
186 {
188 }
189 
191 {
192  execute();
193  return theHistogram;
194 }
195 
197  ossim_float64& minValue,
198  ossim_float64& maxValue,
199  ossim_uint32 band)const
200 {
201  numberOfBins = 0;
202  minValue = 0;
203  maxValue = 0;
204 
206  if(input)
207  {
208  minValue = input->getMinPixelValue(band);
209  maxValue = input->getMaxPixelValue(band);
210  switch(input->getOutputScalarType())
211  {
212  case OSSIM_UINT8:
213  {
214  minValue = 0;
215  maxValue = OSSIM_DEFAULT_MAX_PIX_UCHAR;
216  numberOfBins = 256;
217 
218  break;
219  }
220  case OSSIM_USHORT11:
221  {
222  minValue = 0;
223  maxValue = OSSIM_DEFAULT_MAX_PIX_UINT11;
224  numberOfBins = OSSIM_DEFAULT_MAX_PIX_UINT11 + 1;
225 
226  break;
227  }
228  case OSSIM_USHORT12:
229  {
230  minValue = 0;
231  maxValue = OSSIM_DEFAULT_MAX_PIX_UINT12;
232  numberOfBins = OSSIM_DEFAULT_MAX_PIX_UINT12 + 1;
233 
234  break;
235  }
236  case OSSIM_USHORT13:
237  {
238  minValue = 0;
239  maxValue = OSSIM_DEFAULT_MAX_PIX_UINT13;
240  numberOfBins = OSSIM_DEFAULT_MAX_PIX_UINT13 + 1;
241 
242  break;
243  }
244  case OSSIM_USHORT14:
245  {
246  minValue = 0;
247  maxValue = OSSIM_DEFAULT_MAX_PIX_UINT14;
248  numberOfBins = OSSIM_DEFAULT_MAX_PIX_UINT14 + 1;
249 
250  break;
251  }
252  case OSSIM_USHORT15:
253  {
254  minValue = 0;
255  maxValue = OSSIM_DEFAULT_MAX_PIX_UINT15;
256  numberOfBins = OSSIM_DEFAULT_MAX_PIX_UINT15 + 1;
257 
258  break;
259  }
260  case OSSIM_UINT16:
261  {
262  minValue = 0;
263  maxValue = OSSIM_DEFAULT_MAX_PIX_UINT16;
264  numberOfBins = OSSIM_DEFAULT_MAX_PIX_UINT16 + 1;
265 
266  break;
267  }
268  case OSSIM_SINT16:
269  {
270  minValue = OSSIM_DEFAULT_MIN_PIX_SINT16;
271  maxValue = OSSIM_DEFAULT_MAX_PIX_SINT16;
273  break;
274  }
275  case OSSIM_SINT32:
276  case OSSIM_UINT32:
277  {
278  numberOfBins = OSSIM_DEFAULT_MAX_PIX_UINT16+1;
279  break;
280  }
281  case OSSIM_FLOAT32:
282  case OSSIM_FLOAT64:
283  {
284  numberOfBins = OSSIM_DEFAULT_MAX_PIX_UINT16+1;
285  break;
286  }
289  {
290  minValue = 0;
291  maxValue = 1.0;
292  numberOfBins = OSSIM_DEFAULT_MAX_PIX_UINT16+1;
293  break;
294  }
295  default:
296  {
297  if(traceDebug())
298  {
300  << "Unsupported scalar type in ossimImageHistogramSource::computeHistogram()" << endl;
301  }
302  return;
303  }
304  }
305  }
306 
307  if(ossim::isnan(theMinValueOverride) == false)
308  {
309  minValue = (float)theMinValueOverride;
310  }
311  if(ossim::isnan(theMaxValueOverride) == false)
312  {
313  maxValue = (float)theMaxValueOverride;
314  }
316  {
317  numberOfBins = theNumberOfBinsOverride;
318  }
319 }
320 
322 {
323  // ref ptr, not a leak.
325 
327  if(!input)
328  {
329  setPercentComplete(100.0);
330  return;
331  }
332 
333  if(getInput(0))
334  {
335  // sum up all tiles needing processing. We will use the sequencer.
336  // ossim_uint32 numberOfResLevels = input->getNumberOfDecimationLevels();
337  ossim_uint32 index = 0;
338  double tileCount = 0.0;
339  double totalTiles = 0.0;
340  ossim_uint32 numberOfBands = input->getNumberOfOutputBands();
341  ossim_uint32 numberOfBins = 0;
342  ossim_float64 minValue = 0;
343  ossim_float64 maxValue = 0;
344  getBinInformation(numberOfBins, minValue, maxValue, 0);
345 
347  sequencer->connectMyInputTo(0, getInput(0));
348  sequencer->initialize();
349 
350  vector<ossimDpt> decimationFactors;
351  input->getDecimationFactors(decimationFactors);
352  if ( !decimationFactors.size() )
353  {
355  << "ossimImageHistogramSource::computeNormalModeHistogram WARNING:"
356  << "\nNo decimation factors from input. returning..." << std::endl;
357  return;
358  }
359 
361  (ossim_uint32)decimationFactors.size());
362 
363  if( decimationFactors.size() < theMaxNumberOfResLevels)
364  {
365  ossimNotify(ossimNotifyLevel_WARN) << "Number Decimations is smaller than the request number of r-levels defaulting to the smallest of the 2 numbers" << endl;
366  }
367 
368  theHistogram->create(resLevelsToCompute);
369  for(index = 0; index < resLevelsToCompute; ++index)
370  {
371  sequencer->setAreaOfInterest(theAreaOfInterest*decimationFactors[index]);
372 
373  totalTiles += sequencer->getNumberOfTiles();
374  }
375 
376 
377  if(numberOfBins > 0)
378  {
379  setPercentComplete(0.0);
380  for(index = 0;
381  (index < resLevelsToCompute);
382  ++index)
383  {
384  // Check for abort request.
385  if (needsAborting())
386  {
387  setPercentComplete(100);
388  break;
389  }
390 
391  //sequencer->setAreaOfInterest(input->getBoundingRect(index));
392  sequencer->setAreaOfInterest(theAreaOfInterest*decimationFactors[index]);
393 
394  sequencer->setToStartOfSequence();
395 
396  theHistogram->getMultiBandHistogram(index)->create(numberOfBands,
397  numberOfBins,
398  minValue,
399  maxValue);
400 
401  ossimRefPtr<ossimImageData> data = sequencer->getNextTile(index);
402  ++tileCount;
403  setPercentComplete((100.0*(tileCount/totalTiles)));
404 
405  ossim_uint32 resLevelTotalTiles = sequencer->getNumberOfTiles();
406  for (ossim_uint32 resLevelTileCount = 0;
407  resLevelTileCount < resLevelTotalTiles;
408  ++resLevelTileCount)
409  {
410  if(data.valid()&&data->getBuf()&&(data->getDataObjectStatus() != OSSIM_EMPTY))
411  {
413  }
414 
415  // Check for abort request.
416  if (needsAborting())
417  {
418  setPercentComplete(100);
419  break;
420  }
421 
422 
423  data = sequencer->getNextTile(index);
424  ++tileCount;
425  setPercentComplete((100.0*(tileCount/totalTiles)));
426  }
427  }
428  }
429  sequencer->disconnect();
430  sequencer = 0;
431  }
432 }
433 
435 {
436  // Compute at most 9 x 9 tiles of 16 x 16 tile size.
437 
438  ossim_uint32 resLevelsToCompute = 1;
439 
440  // ref ptr, not a leak.
442  theHistogram->create(resLevelsToCompute);
444  if(!input)
445  {
446  setPercentComplete(100.0);
447  return;
448  }
449  // sum up all tiles needing processing. We will use the sequencer.
450  // ossim_uint32 numberOfResLevels = input->getNumberOfDecimationLevels();
451  double tileCount = 0.0;
452  double totalTiles = 0.0;
453  ossim_uint32 numberOfBands = input->getNumberOfOutputBands();
454  ossim_uint32 numberOfBins = 0;
455  ossim_float64 minValue = 0;
456  ossim_float64 maxValue = 0;
457  getBinInformation(numberOfBins, minValue, maxValue, 0);
458 
459  // Fixed 16 x 16 tile size:
460  ossimIpt tileSize( 16, 16 );
461 
462  ossimIrect tileBoundary = theAreaOfInterest;
463  tileBoundary.stretchToTileBoundary(tileSize);
464 
465  // Max of 9 x 9 tiles accross the image.
466  const ossim_uint32 MAX_TILES_WIDE = 9;
467 
468  ossim_uint32 tilesWide = ossim::min( (ossim_uint32)(tileBoundary.width()/tileSize.x),
469  MAX_TILES_WIDE);
470  ossim_uint32 tilesHigh = ossim::min( (ossim_uint32)(tileBoundary.height()/tileSize.y),
471  MAX_TILES_WIDE);
472 
473  totalTiles = tilesWide*tilesHigh;
474 
475  if(numberOfBins > 0)
476  {
477  ossimIpt origin = theAreaOfInterest.ul();
478 
479  ossim_uint32 xTileOffset = tileBoundary.width() / tilesWide;
480  ossim_uint32 yTileOffset = tileBoundary.height() / tilesHigh;
481 
482  theHistogram->getMultiBandHistogram(0)->create(numberOfBands,
483  numberOfBins,
484  minValue,
485  maxValue);
486  ossim_uint32 x = 0;
487  ossim_uint32 y = 0;
488  tileCount = 0;
489  totalTiles = tilesWide*tilesHigh;
490 
491  for(y = 0; y < tilesHigh; ++y)
492  {
493  for(x = 0; x < tilesWide; ++x)
494  {
495  ossimIpt ul( origin.x + (x*xTileOffset), origin.y + (y*yTileOffset) );
496  ossimIrect tileRect(ul.x, ul.y, ul.x + tileSize.x-1, ul.y + tileSize.y-1);
497 
498  ossimRefPtr<ossimImageData> data = input->getTile(tileRect);
499 
500  if(data.valid()&&data->getBuf()&&(data->getDataObjectStatus() != OSSIM_EMPTY))
501  {
503  }
504 
505  // Check for abort request.
506  if (needsAborting())
507  {
508  break;
509  }
510 
511  ++tileCount;
512  }
513 
514  // Check for abort request.
515  if (needsAborting())
516  {
517  setPercentComplete(100);
518  break;
519  }
520 
521  setPercentComplete((100.0*(tileCount/totalTiles)));
522  }
523  }
524 
525 #if 0 /* drb - old code was not working... */
526 
527  // We will only compute a full res histogram in fast mode. and will only do a MAX of 100 tiles.
528  //
529  ossim_uint32 resLevelsToCompute = 1;
530 
531  // ref ptr, not a leak.
533  theHistogram->create(resLevelsToCompute);
535  if(!input)
536  {
537  setPercentComplete(100.0);
538  return;
539  }
540  // sum up all tiles needing processing. We will use the sequencer.
541  // ossim_uint32 numberOfResLevels = input->getNumberOfDecimationLevels();
542  double tileCount = 0.0;
543  double totalTiles = 0.0;
544  ossim_uint32 numberOfBands = input->getNumberOfOutputBands();
545  ossim_uint32 numberOfBins = 0;
546  ossim_float64 minValue = 0;
547  ossim_float64 maxValue = 0;
548  getBinInformation(numberOfBins, minValue, maxValue, 0);
549 
550  ossimIrect tileBoundary = theAreaOfInterest;
551  // ossimIpt tileSize(ossim::max((ossim_uint32)input->getTileWidth(), (ossim_uint32)64),
552  // ossim::max((ossim_uint32)input->getTileHeight(), (ossim_uint32)64));
553 
554  ossimIpt tileSize(ossim::max<ossim_uint32>(input->getTileWidth(), (ossim_uint32)64),
556 
557  tileBoundary.stretchToTileBoundary(tileSize);
558  ossim_uint32 tilesWide = (tileBoundary.width()/tileSize.x);
559  ossim_uint32 tilesHigh = (tileBoundary.height()/tileSize.y);
560  totalTiles = tilesWide*tilesHigh;
561 
562  if(totalTiles > theNumberOfTilesToUseInFastMode)
563  {
564  ossim_uint32 testTiles = (ossim_uint32) (std::sqrt((double)theNumberOfTilesToUseInFastMode)+.5);
565  tilesWide = testTiles>tilesWide?tilesWide:testTiles;
566  tilesHigh = testTiles>tilesHigh?tilesHigh:testTiles;
567  }
568  if(numberOfBins > 0)
569  {
570  ossimIpt origin = theAreaOfInterest.ul();
571 
572  ossim_uint32 widthWithExcess = (ossim_uint32)(((ossim_float64)tileBoundary.width()/(tilesWide*tileSize.x))*tileSize.x);
573  ossim_uint32 heightWithExcess = ((ossim_uint32)((ossim_float64)tileBoundary.height()/(tilesHigh*tileSize.y))*tileSize.y);
574  theHistogram->getMultiBandHistogram(0)->create(numberOfBands,
575  numberOfBins,
576  minValue,
577  maxValue);
578 
579  ossim_uint32 x = 0;
580  ossim_uint32 y = 0;
581  tileCount = 0;
582  totalTiles = tilesWide*tilesHigh;
583  for(y = 0; y < tilesHigh; ++y)
584  {
585  for(x = 0; x < tilesWide; ++x)
586  {
587  ossimIpt ul(origin.x + (x*widthWithExcess),
588  origin.y + (y*heightWithExcess));
589  ossimIrect tileRect(ul.x, ul.y, ul.x + tileSize.x-1, ul.y + tileSize.y-1);
590  ossimRefPtr<ossimImageData> data = input->getTile(tileRect);
591 
592  if(data.valid()&&data->getBuf()&&(data->getDataObjectStatus() != OSSIM_EMPTY))
593  {
595  }
596  ++tileCount;
597  setPercentComplete((100.0*(tileCount/totalTiles)));
598  }
599  }
600  }
601 
602 #endif
603 }
604 
606  const char* prefix)
607 {
608  ossimHistogramSource::loadState(kwl, prefix);
610  ossimString rect = kwl.find(prefix, "rect");
611 
612  if(!rect.empty())
613  {
614  loadState(kwl, prefix);
615  }
616  else
617  {
618  ossimString newPrefix = ossimString(prefix) + "area_of_interest.";
619  theAreaOfInterest.loadState(kwl, newPrefix);
620  }
621 
622  ossimString mode = kwl.find(prefix, "mode");
623  mode = mode.downcase();
624  if(mode == "normal")
625  {
627  }
628  else if(mode == "fast")
629  {
631  }
632  if(getNumberOfInputs()!=1)
633  {
635  }
636 
637  // ossimString numberOfTiles = kwl.find(prefix, "number_of_tiles");
638  // if(!numberOfTiles.empty())
639  // {
640  // theNumberOfTilesToUseInFastMode = numberOfTiles.toUInt32();
641  // }
642 
644  theOutputListIsFixedFlag = false;
645 
646  return true;
647 }
648 
650  const char* prefix)const
651 {
652  bool result = ossimHistogramSource::saveState(kwl, prefix);
653  if(result)
654  {
655  ossimString newPrefix = ossimString(prefix) + "area_of_interest.";
656  theAreaOfInterest.saveState(kwl, newPrefix);
657  }
658  return result;
659 }
16 bit unsigned integer (15 bits used)
virtual void setNumberOfInputs(ossim_int32 numberOfInputs)
Will set the number of inputs.
#define OSSIM_DEFAULT_MAX_PIX_UINT16
ossim_uint32 x
virtual bool isSourceEnabled() const
Definition: ossimSource.cpp:79
virtual bool addListener(ossimListener *listener)
ossimImageHistogramSource(ossimObject *owner=0)
virtual ossim_uint32 getMaxNumberOfRLevels() const
ossimHistogramMode
T max(T a, T b)
Definition: ossimCommon.h:236
void setComputationMode(ossimHistogramMode mode)
64 bit floating point
16 bit unsigned integer
bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Definition: ossimIrect.cpp:589
virtual void disconnect(ossimConnectableObject *object=0)
Will disconnect the object passed in.
void setNumberOfBinsOverride(ossim_int32 numberOfBinsOverride)
virtual void populateHistogram(ossimRefPtr< ossimMultiBandHistogram > histo)
Represents serializable keyword/value map.
virtual bool canConnectMyInputTo(ossim_int32 myInputIndex, const ossimConnectableObject *object) const
required to be overriden by derived classes
virtual ossim_uint32 getNumberOfOutputBands() const
Returns the number of bands in a tile returned from this TileSource.
ossim_uint32 y
bool valid() const
Definition: ossimRefPtr.h:75
#define OSSIM_DEFAULT_MAX_PIX_UCHAR
const char * find(const char *key) const
ossimHistogramMode getComputationMode() const
float ossim_float32
double nan()
Method to return ieee floating point double precision NAN.
Definition: ossimCommon.h:135
ossim_uint32 height() const
Definition: ossimIrect.h:487
virtual ossimRefPtr< ossimImageData > getNextTile(ossim_uint32 resLevel=0)
virtual ossim_uint32 getTileHeight() const
Returns the default processing tile height.
16 bit signed integer
virtual void setPercentComplete(double percentComplete)
const ossimIpt & ul() const
Definition: ossimIrect.h:274
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
virtual ossimDataObjectStatus getDataObjectStatus() const
16 bit unsigned integer (14 bits used)
void create(ossim_uint32 numberOfResLevels)
16 bit unsigned integer (13 bits used)
32 bit floating point
32 bit unsigned integer
virtual void setProcessStatus(ossimProcessStatus processStatus)
virtual ossim_uint32 getTileWidth() const
Returns the default processing tile width.
virtual ossimRefPtr< ossimMultiResLevelHistogram > getHistogram()
ossimConnectableObject * getInput(ossim_uint32 index=0)
returns the object at the specified index.
void getBinInformation(ossim_uint32 &numberOfBins, ossim_float64 &minValue, ossim_float64 &maxValue, ossim_uint32 band) const
virtual double getMinPixelValue(ossim_uint32 band=0) const
Returns the min pixel of the band.
double ossim_float64
virtual void propertyEvent(ossimPropertyEvent &event)
ossimRefPtr< ossimMultiResLevelHistogram > theHistogram
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
virtual void setAreaOfInterest(const ossimIrect &areaOfInterest)
#define OSSIM_DEFAULT_MAX_PIX_UINT12
#define OSSIM_DEFAULT_MIN_PIX_SINT16
RTTI_DEF3(ossimImageHistogramSource, "ossimImageHistogramSource", ossimHistogramSource, ossimConnectableObjectListener, ossimProcessInterface)
bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Definition: ossimIrect.cpp:641
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
32 bit signed integer
#define OSSIM_DEFAULT_MAX_PIX_UINT15
unsigned int ossim_uint32
32 bit normalized floating point
#define PTR_CAST(T, p)
Definition: ossimRtti.h:321
#define OSSIM_DEFAULT_MAX_PIX_UINT13
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
static ossimString downcase(const ossimString &aString)
Definition: ossimString.cpp:48
virtual ossim_int32 connectMyInputTo(ossimConnectableObject *inputObject, bool makeOutputConnection=true, bool createEventFlag=true)
Will try to connect this objects input to the passed in object.
T min(T a, T b)
Definition: ossimCommon.h:203
ossim_uint32 width() const
Definition: ossimIrect.h:500
#define OSSIM_DEFAULT_MAX_PIX_SINT16
void setMaxValueOverride(ossim_float32 maxValueOverride)
64 bit normalized floating point
16 bit unsigned integer (11 bits used)
virtual ossimScalarType getOutputScalarType() const
This will be used to query the output pixel type of the tile source.
virtual double getMaxPixelValue(ossim_uint32 band=0) const
Returns the max pixel of the band.
#define OSSIM_DEFAULT_MAX_PIX_UINT14
ossim_int32 y
Definition: ossimIpt.h:142
void makeNan()
Definition: ossimIrect.h:329
virtual const void * getBuf() const
#define OSSIM_DEFAULT_MAX_PIX_UINT11
virtual ossim_uint32 getNumberOfInputs() const
Returns the number of input objects.
bool theInputListIsFixedFlag
Indicates whether the theInputObjectList is fixed.
bool empty() const
Definition: ossimString.h:411
void stretchToTileBoundary(const ossimIpt &tileWidthHeight)
Definition: ossimIrect.cpp:212
bool hasNans() const
Definition: ossimIrect.h:337
virtual void setMaxNumberOfRLevels(ossim_uint32 number)
ossim_int32 x
Definition: ossimIpt.h:141
8 bit unsigned integer
bool theOutputListIsFixedFlag
Indicates whether the theOutputObjectList is fixed.
void setAreaOfInterest(const ossimIrect &rect)
void setMinValueOverride(ossim_float32 minValueOverride)
ossimRefPtr< ossimMultiBandHistogram > getMultiBandHistogram(ossim_uint32 resLevel) const
void create(const ossimImageSource *input)
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
virtual void getDecimationFactors(std::vector< ossimDpt > &decimations) const
Will return an array of all decimations for each resolution level.
virtual void connectInputEvent(ossimConnectionEvent &event)
int ossim_int32
virtual ossimRefPtr< ossimImageData > getTile(const ossimIpt &origin, ossim_uint32 resLevel=0)
16 bit unsigned integer (12 bits used)
bool isnan(const float &v)
isnan Test for floating point Not A Number (NAN) value.
Definition: ossimCommon.h:91
virtual bool removeListener(ossimListener *listener)