OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimHistogramRemapper.cpp
Go to the documentation of this file.
1 //*******************************************************************
2 //
3 // License: MIT
4 //
5 // Author: David Burken
6 //
7 // Description:
8 //
9 // Histogram remapper class declaration. Derived from ossimTableRemapper.
10 //
11 // Remaps a tile based on mode and histogram clip points.
12 //
13 //*************************************************************************
14 // $Id$
15 
20 #include <ossim/base/ossimTrace.h>
25 #include <cstdlib>
26 #include <iomanip>
27 
28 RTTI_DEF1(ossimHistogramRemapper, "ossimHistogramRemapper", ossimTableRemapper)
29 
30 static ossimTrace traceDebug("ossimHistogramRemapper:debug");
31 
32 static const char* STRETCH_MODE[] = { "linear_one_piece",
33  "linear_1std_from_mean",
34  "linear_2std_from_mean",
35  "linear_3std_from_mean",
36  "linear_auto_min_max",
37  "linear_auto_percentile",
38  "stretch_unknown" };
39 
40 static const char NORMALIZED_LOW_CLIP_POINT_KW[] = "normalized_low_clip_point";
41 static const char NORMALIZED_HIGH_CLIP_POINT_KW[]="normalized_high_clip_point";
42 static const char MID_POINT_KW[] = "mid_point";
43 static const char MIN_OUTPUT_VALUE_KW[] = "min_output_value";
44 static const char MAX_OUTPUT_VALUE_KW[] = "max_output_value";
45 static const char STRETCH_MODE_KW[] = "stretch_mode";
46 static const char HISTOGRAM_FILENAME_KW[] = "histogram_filename";
47 
48 #ifdef OSSIM_ID_ENABLED
49 static const char OSSIM_ID[] = "$Id: ossimHistogramRemapper.cpp 23182 2015-03-09 14:30:52Z okramer $";
50 #endif
51 
53  :
54  ossimTableRemapper(), // base class
55  theStretchMode(ossimHistogramRemapper::LINEAR_ONE_PIECE),
56  theDirtyFlag(false),
57  theHistogram(0),
58  theNormalizedLowClipPoint(),
59  theNormalizedHighClipPoint(),
60  theMidPoint(),
61  theMinOutputValue(),
62  theMaxOutputValue(),
63  theBandList(),
64  theBypassFlag(true),
65  theResetBandIndicesFlag(false)
66 {
68  if (traceDebug())
69  {
71  << "ossimHistogramRemapper::ossimHistogramRemapper entered...\n";
72 #ifdef OSSIM_ID_ENABLED
74  << "OSSIM_ID: " << OSSIM_ID << "\n";
75 #endif
76  }
77 }
78 
80 {
81 }
82 
84 {
85  if (traceDebug())
86  {
88  << "ossimHistogramRemapper::initialize entered..." << endl;
89  }
90 
91  theResetBandIndicesFlag = (dynamic_cast<const ossimHistogramSource*>(getInput(1))!=0);
92 
93  //---
94  // Call the base class initialize.
95  // Note: This will reset "theInputConnection" if it changed...
96  //---
98 
99  // Check the band list to see if it's changes.
100  vector<ossim_uint32> bandList;
101  getOutputBandList(bandList);
102  ossim_uint32 idx = 0;
103  // bool emptyOutput = theBandList.empty();
104 
106  {
107  for(idx = 0; idx < bandList.size();++idx)
108  {
109  bandList[idx] = idx;
110  }
111  }
112  if (theBandList.size() != 0 && bandList.size())
113  {
114  if (theBandList.size() != bandList.size())
115  {
116  // Somethings changed. Set everthing back.
117  initializeClips();
118  setNullCount();
119  theTable.clear();
120  theDirtyFlag = true;
121  }
122  else
123  {
124  // Sizes same check the order.
125  for(ossim_uint32 band = 0; band < theBandList.size(); ++band)
126  {
127  if (theBandList[band] != bandList[band])
128  {
129  //initializeClips();
130  //setNullCount();
131  theDirtyFlag = true;
132  break;
133  }
134  }
135  }
136  }
137  else
138  {
140  }
141 
142  // Update the band list with the latest.
143  theBandList = bandList;
144 
145  verifyEnabled();
146 
147  if (traceDebug())
148  {
150  << "ossimHistogramRemapper::initialize exited..." << endl;
151  }
152 }
153 
155 {
156  // We could delete theTable to free up memory???
158  initializeClips();
159  verifyEnabled();
160 }
161 
163 {
164  theHistogram = histogram;
165  setNullCount();
166 
167  // Note: initializeClips before setNullCount since it relies on clips.
168  initializeClips();
169  theTable.clear();
170  theDirtyFlag = true;
171 }
172 
174 {
176  if (h->importHistogram(histogram_file))
177  {
178  setHistogram(h);
179  return true;
180  }
181 
182  // Import failed if here!
183  return false;
184 }
185 
187 {
188  bool result = false;
189  if ( theInputConnection )
190  {
192  if ( tile.valid() )
193  {
194  ossimDataObjectStatus tile_status = tile->getDataObjectStatus();
195  if ( (tile_status != OSSIM_NULL) && (tile_status != OSSIM_EMPTY) )
196  {
199 
200  tile->populateHistogram(h);
201 
203 
204  histo->addHistogram( h.get() );
205 
206  setHistogram( histo );
207  result = true;
208  }
209  }
210  }
211  return result;
212 }
213 
215  const ossimIrect& tile_rect,
216  ossim_uint32 resLevel)
217 {
218 
219 #if 0 /* Please leave for debug. (drb) */
220  cout << "\ntheEnableFlag: " << theEnableFlag
221  << "\ntheBypassFlag: " << theBypassFlag
222  << "\ntheDirtyFlag: " << theDirtyFlag
223  << endl;
224 #endif
225 
226  if ( !theInputConnection )
227  return 0;
228 
229  // Rebuild the table if dirty flag set:
230  if ( theDirtyFlag )
231  makeClean();
232 
233  if ( !theEnableFlag || theBypassFlag )
234  return theInputConnection->getTile(tile_rect, resLevel);
235 
236  ossimRefPtr<ossimImageData> inputTile = theInputConnection->getTile(tile_rect, resLevel);
237  if(!inputTile.valid())
238  return 0;
239 
240  ossimDataObjectStatus tile_status = inputTile->getDataObjectStatus();
241  if ( (tile_status == OSSIM_NULL) || (tile_status == OSSIM_EMPTY) )
242  return inputTile;
243 
244  if (!theTile)
245  allocate(tile_rect);
246 
247  theTile->setImageRectangle(tile_rect);
248  theTile->makeBlank();
249  switch (theOutputScalarType)
250  {
251  case OSSIM_UINT8:
252  applyLinearStretch(ossim_uint8(0), inputTile);
253  break;
254 
255  case OSSIM_USHORT11:
256  case OSSIM_USHORT12:
257  case OSSIM_USHORT13:
258  case OSSIM_USHORT14:
259  case OSSIM_USHORT15:
260  case OSSIM_UINT16:
261  applyLinearStretch(ossim_uint16(0), inputTile);
262  break;
263 
264  case OSSIM_SSHORT16:
265  applyLinearStretch(ossim_sint16(0), inputTile);
266  //remapFromNativeTable(ossim_sint16(0), inputTile);
267  break;
268 
270  case OSSIM_FLOAT:
271  applyLinearStretch(ossim_float32(0), inputTile);
272  //remapFromNativeTable(ossim_float32(0), inputTile);
273  break;
274 
276  case OSSIM_DOUBLE:
277  applyLinearStretch(ossim_float64(0), inputTile);
278  //remapFromNativeTable(ossim_float64(0), inputTile);
279  break;
280 
282  default:
283  // Shouldn't hit this.
284  if(traceDebug())
285  {
286  ossimNotify(ossimNotifyLevel_WARN) << "ossimHistogramRemapper::getTile"
287  << "\nOutput scalar type is OSSIM_SCALAR_UNKNOWN!\n";
288  }
289  } // End of "switch (theTableType)"
290 
291  theTile->validate();
292  return theTile;
293 }
294 
296  T /* dummy */,
297  ossimRefPtr<ossimImageData>& inputTile)
298 {
299  const ossim_uint32 BANDS = inputTile->getNumberOfBands();
300 
301  // Sanity check.
302  if (theNormalizedLowClipPoint.size() != BANDS || !getHistogram(0).valid())
303  {
304  if(traceDebug())
305  {
307  << "ossimHistogramRemapper::buildTable ERROR!"
308  << " Line: " << __LINE__ << endl;
309  }
310  return;
311  }
312 
313 
314 
315 // T* table = reinterpret_cast<T*>(&theTable.front());
316 // ossim_uint32 index = 0;
317 
318  // Finally, build the table...
319  for (ossim_uint32 band = 0; band < BANDS; ++band)
320  {
322  T* bandPtr = static_cast<T*>(inputTile->getBuf(band));
323  T* outputPtr = static_cast<T*>(theTile->getBuf(band));
324  if (h.get()&&bandPtr&&outputPtr)
325  {
326  if (traceDebug())
327  {
329  << "ossimHistogramRemapper::buildLinearTable DEBUG:"
330  << "\nband: " << band
331  << "\nmean: " << h->GetMean()
332  << "\nstddev: " << h->GetStandardDev()
333  << endl;
334  }
335  }
336  else
337  {
338  if(traceDebug())
339  {
341  << "ossimHistogramRemapper::buildTable ERROR!"
342  << " Line: " << __LINE__ << endl;
343  }
344  return;
345  }
346  //std::cout << "MIN OUTPUT ==== " << theMinOutputValue[band] << std::endl;
347  const T NULL_PIX = static_cast<T>(getNullPixelValue(band));
348  const T MIN_PIX = static_cast<T>(theMinOutputValue[band]);
349  const T MAX_PIX = static_cast<T>(theMaxOutputValue[band]);
350 //std::cout <<"theMinOutputValue[band]: " << theMinOutputValue[band] << "\n";
351 //std::cout <<"theMaxOutputValue[band]: " << theMaxOutputValue[band] << "\n";
352 //std::cout <<"theNormalizedLowClipPoint[band]: " << theNormalizedLowClipPoint[band] << "\n";
353 //std::cout <<"theNormalizedHighClipPoint[band]: " << theNormalizedHighClipPoint[band] << "\n";
354 //std::cout <<"MIN_PIX: " << MIN_PIX << "\n";
355 //std::cout <<"MAX_PIX: " << MAX_PIX << "\n";
356  ossim_float64 min_clip_value =
358  ossim_float64 max_clip_value =
360 
362  {
363  min_clip_value = floor(min_clip_value);
364  max_clip_value = ceil(max_clip_value);
365  }
366  //ossim_float64 gain = (MAX_PIX-MIN_PIX+1)/(max_clip_value-min_clip_value);
367  ossim_float64 gain = 1.0;
368 
370  {
371  gain = (MAX_PIX-MIN_PIX+1)/(max_clip_value-min_clip_value);
372  }
373  else
374  {
375  gain = (MAX_PIX-MIN_PIX)/(max_clip_value-min_clip_value);
376  }
377  const ossim_uint32 PPB = inputTile->getSizePerBand(); // pixels per band
378 
379  ossim_uint32 idx = 0;
380  for(idx = 0; idx < PPB;++idx)
381  {
382  if ( bandPtr[idx] != NULL_PIX )
383  {
384  ossim_float64 p = bandPtr[idx];
385  if (p < min_clip_value)
386  {
387  p = MIN_PIX;
388  }
389  else if (p > max_clip_value)
390  {
391  p = MAX_PIX;
392  }
393  else
394  {
395  p = ((p - min_clip_value) * gain) + MIN_PIX;// - 1.0;
396  }
397  // Final range check:
398  outputPtr[idx] =
399  static_cast<T>( p >= MIN_PIX ? ( p <= MAX_PIX ? p : MAX_PIX ) : MIN_PIX );
400  }
401  else
402  {
403  outputPtr[idx] = NULL_PIX;
404  }
405  }
406 
407  } // End of band loop.
408 
409 }
410 
412 {
413  const ossim_uint32 BANDS = getNumberOfInputBands();
414  for (ossim_uint32 band = 0; band < BANDS; ++band)
415  {
416  setLowNormalizedClipPoint(clip, band);
417  }
418 }
419 
421 {
422  if (theEnableFlag && theDirtyFlag) // Enabled and dirty.
423  {
424  // Always rebuild table if dirty.
425  buildTable();
426 
427  // Check for internal bypass.
428  verifyEnabled();
429 
430  // Always clear the dirty flag.
431  theDirtyFlag = false;
432  }
433 }
434 
436  ossim_uint32 zero_based_band)
437 {
438  const ossim_uint32 BANDS = getNumberOfInputBands();
439 
440  if (zero_based_band >= BANDS)
441  {
443  << "ossimHistogramRemapper::setLowNormalizedClipPoint ERROR:"
444  << "\nband " << zero_based_band << " is out of range!"
445  << "\nhighest band: " << (BANDS-1) << endl;
446  }
447 
448  if (theNormalizedLowClipPoint.size() != BANDS)
449  {
450  initializeClips();
451  }
452 
453  if ( clip != theNormalizedLowClipPoint[zero_based_band] &&
454  clip < theNormalizedHighClipPoint[zero_based_band] )
455  {
456  theDirtyFlag = true;
457  theNormalizedLowClipPoint[zero_based_band] = clip;
458  }
459 }
460 
461 void
463 {
464  const ossim_uint32 BANDS = getNumberOfInputBands();
465  for (ossim_uint32 band = 0; band < BANDS; ++band)
466  {
467  setHighNormalizedClipPoint(clip, band);
468  }
469 }
470 
472  const ossim_float64& clip, ossim_uint32 zero_based_band)
473 {
474  const ossim_uint32 BANDS = getNumberOfInputBands();
475 
476  if (zero_based_band >= BANDS)
477  {
479  << "ossimHistogramRemapper::setHighNormalizedClipPoint ERROR:"
480  << "\nband " << zero_based_band << " is out of range!"
481  << "\nhighest band: " << (BANDS-1) << endl;
482  }
483 
484  if (theNormalizedHighClipPoint.size() != BANDS)
485  {
486  initializeClips();
487  }
488 
489  if ( clip != theNormalizedHighClipPoint[zero_based_band] &&
490  clip > theNormalizedLowClipPoint[zero_based_band] )
491  {
492  theDirtyFlag = true;
493  theNormalizedHighClipPoint[zero_based_band] = clip;
494  }
495 }
496 
498 {
499  const ossim_uint32 BANDS = getNumberOfInputBands();
500  for (ossim_uint32 band = 0; band < BANDS; ++band)
501  {
502  setLowClipPoint(clip, band);
503  }
504 }
505 
507  ossim_uint32 zero_based_band)
508 {
509  // allow the call to getHistogram to happen this way we can calculate a histogram if
510  // a histosource is connected to this object
511  //
512  // if (!theHistogram) return;
513 
514  ossimRefPtr<ossimHistogram> h = getHistogram(zero_based_band);
515  if (h.valid())
516  {
518  if (ossim::isnan(d) == false)
519  {
520  setLowNormalizedClipPoint(d, zero_based_band);
521  }
522  }
523 }
524 
526 {
527  const ossim_uint32 BANDS = getNumberOfInputBands();
528  for (ossim_uint32 band = 0; band < BANDS; ++band)
529  {
530  setHighClipPoint(clip, band);
531  }
532 }
533 
535  ossim_uint32 zero_based_band)
536 {
537  // allow the call to getHistogram to happen this way we can calculate a histogram if
538  // a histosource is connected to this object
539  //
540  // if (!theHistogram) return;
541 
542  ossimRefPtr<ossimHistogram> h = getHistogram(zero_based_band);
543  if (h.valid())
544  {
546  if (ossim::isnan(d) == false)
547  {
548  d = 1.0-d;
549  setHighNormalizedClipPoint(d, zero_based_band);
550  }
551  }
552 }
553 
555 {
556  const ossim_uint32 BANDS = getNumberOfInputBands();
557  for (ossim_uint32 band = 0; band < BANDS; ++band)
558  {
559  setMidPoint(value, band);
560  }
561 }
562 
564  ossim_uint32 zero_based_band)
565 {
566  const ossim_uint32 BANDS = getNumberOfInputBands();
567 
568  if (zero_based_band >= BANDS)
569  {
571  << "ossimHistogramRemapper::setMidPoint ERROR:"
572  << "\nband " << zero_based_band << " is out of range!"
573  << "\nhighest band: " << (BANDS-1) << endl;
574  }
575 
576  if (theMidPoint.size() != BANDS)
577  {
578  initializeClips();
579  }
580 
581  if (theMidPoint[zero_based_band] != value)
582  {
583  theDirtyFlag = true;
584  theMidPoint[zero_based_band] = value;
585  }
586 }
587 
589 {
590  const ossim_uint32 BANDS = getNumberOfInputBands();
591  for (ossim_uint32 band = 0; band < BANDS; ++band)
592  {
593  setMinOutputValue(value, band);
594  }
595 }
596 
598  ossim_uint32 zero_based_band)
599 {
600  if (theInputConnection)
601  {
602  const ossim_uint32 BANDS = getNumberOfInputBands();
603 
604  if (zero_based_band >= BANDS)
605  {
607  << "ossimHistogramRemapper::setMinOutputValue ERROR:"
608  << "\nband " << zero_based_band << " is out of range!"
609  << "\nhighest band: " << (BANDS-1) << endl;
610  }
611 
612  if (theMinOutputValue.size() != BANDS)
613  {
614  initializeClips();
615  }
616 
617  if ( value != theMinOutputValue[zero_based_band] &&
618  value >= theInputConnection->getMinPixelValue(zero_based_band) &&
619  value < theMaxOutputValue[zero_based_band] )
620  {
621  theDirtyFlag = true;
622  theMinOutputValue[zero_based_band] = value;
623  }
624  }
625 }
626 
628 {
629  const ossim_uint32 BANDS = getNumberOfInputBands();
630  for (ossim_uint32 band = 0; band < BANDS; ++band)
631  {
632  setMaxOutputValue(value, band);
633  }
634 }
635 
637  ossim_uint32 zero_based_band)
638 {
639  if (theInputConnection)
640  {
641  const ossim_uint32 BANDS = getNumberOfInputBands();
642 
643  if (zero_based_band >= BANDS)
644  {
646  << "ossimHistogramRemapper::setMidPoint ERROR:"
647  << "\nband " << zero_based_band << " is out of range!"
648  << "\nhighest band: " << (BANDS-1) << endl;
649  }
650 
651  if (theMaxOutputValue.size() != BANDS)
652  {
653  initializeClips();
654  }
655 
656  if ( value != theMaxOutputValue[zero_based_band] &&
657  value <= theInputConnection->getMaxPixelValue(zero_based_band) &&
658  value > theMinOutputValue[zero_based_band] )
659  {
660  theDirtyFlag = true;
661  theMaxOutputValue[zero_based_band] = value;
662  }
663  }
664 }
665 
667 {
668  if (theNormalizedLowClipPoint.size() == 0 ||
669  zero_based_band >= getNumberOfInputBands())
670  {
671  return ossim::nan();
672  }
673 
674  if (zero_based_band >= theNormalizedLowClipPoint.size())
675  {
677  << "ossimHistogramRemapper::getLowNormalizedClipPoint ERROR:"
678  << "\nband " << zero_based_band << " is out of range!"
679  << "\nhighest band: " << (theNormalizedLowClipPoint.size()-1)
680  << endl;
681  return ossim::nan();
682  }
683 
684  return theNormalizedLowClipPoint[zero_based_band];
685 }
686 
688 {
689  if (theNormalizedLowClipPoint.size() == 0)
690  {
691  return ossim::nan();
692  }
693 
694  ossim_float64 d = 0.0;
696  for (ossim_uint32 band = 0; band < BANDS; ++band)
697  {
698  d += getLowNormalizedClipPoint(band);
699  }
700 
701  return (d / BANDS);
702 }
703 
705 {
706  if (theNormalizedHighClipPoint.size() == 0 ||
707  zero_based_band >= getNumberOfInputBands())
708  {
709  return ossim::nan();
710  }
711 
712  if (zero_based_band >= theNormalizedHighClipPoint.size())
713  {
715  << "ossimHistogramRemapper::getHighNormalizedClipPoint ERROR:"
716  << "\nband " << zero_based_band << " is out of range!"
717  << "\nhighest band: " << (theNormalizedHighClipPoint.size()-1)
718  << endl;
719  return ossim::nan();
720  }
721 
722  return theNormalizedHighClipPoint[zero_based_band];
723 }
724 
726 {
727  if (theNormalizedHighClipPoint.size() == 0)
728  {
729  return ossim::nan();
730  }
731 
732  ossim_float64 d = 0.0;
734  for (ossim_uint32 band = 0; band < BANDS; ++band)
735  {
736  d += getHighNormalizedClipPoint(band);
737  }
738 
739  return (d / BANDS);
740 }
741 
743 {
744  if(zero_based_band >= getNumberOfInputBands() ||
745  !theHistogram || zero_based_band >= theNormalizedLowClipPoint.size())
746  {
747  return ossim::nan();
748  }
749 
750  if (theNormalizedLowClipPoint[zero_based_band] == 0.0)
751  {
752  return getMinPixelValue(zero_based_band);
753  }
754 
755  ossimRefPtr<ossimHistogram> h = getHistogram(zero_based_band);
756  if (h.valid())
757  {
758  ossim_float64 d =
759  h->LowClipVal(theNormalizedLowClipPoint[zero_based_band]);
760 
761  return d;//floor(d);
762  }
763 
764  return ossim::nan();
765 }
766 
768 {
769  if (theNormalizedLowClipPoint.size() == 0 || !theHistogram)
770  {
771  return ossim::nan();
772  }
773 
774  ossim_float64 d = 0.0;
775  const ossim_uint32 BANDS = getNumberOfInputBands();
776  for (ossim_uint32 band = 0; band < BANDS; ++band)
777  {
778  d += getLowClipPoint(band);
779  }
780 
781  return (d / BANDS);
782 }
783 
785 {
786  if(zero_based_band >= getNumberOfInputBands() ||
787  !theHistogram || zero_based_band >= theNormalizedHighClipPoint.size())
788  {
789  return ossim::nan();
790  }
791 
792  if (theNormalizedHighClipPoint[zero_based_band] == 1.0)
793  {
794  return getMaxPixelValue(zero_based_band);
795  }
796 
797  ossimRefPtr<ossimHistogram> h = getHistogram(zero_based_band);
798  if (h.valid())
799  {
800  ossim_float64 d =
801  h->HighClipVal(1.0-theNormalizedHighClipPoint[zero_based_band]);
802  return (d);//ceil(d);
803  }
804 
805  return ossim::nan();
806 }
807 
809 {
810  if (theNormalizedHighClipPoint.size() == 0 || !theHistogram)
811  {
812  return ossim::nan();
813  }
814 
815  ossim_float64 d = 0.0;
816  const ossim_uint32 BANDS = getNumberOfInputBands();
817  for (ossim_uint32 band = 0; band < BANDS; ++band)
818  {
819  d += getHighClipPoint(band);
820  }
821 
822  return (d / BANDS);
823 }
824 
826 {
827  if (theMidPoint.size() == 0 ||
828  zero_based_band >= getNumberOfInputBands())
829  {
830  return ossim::nan();
831  }
832 
833  if (zero_based_band >= theMidPoint.size())
834  {
836  << "ossimHistogramRemapper::getMidPoint ERROR:"
837  << "\nband " << zero_based_band << " is out of range!"
838  << "\nhighest band: " << (theMidPoint.size()-1)
839  << endl;
840  return ossim::nan();
841  }
842 
843  return theMidPoint[zero_based_band];
844 }
845 
847 {
848  if (theMidPoint.size() == 0)
849  {
850  return ossim::nan();
851  }
852 
853  ossim_float64 d = 0.0;
854  const ossim_uint32 BANDS = (ossim_uint32)theMidPoint.size();
855  for (ossim_uint32 band = 0; band < BANDS; ++band)
856  {
857  d += getMidPoint(band);
858  }
859 
860  return (d / BANDS);
861 }
862 
864 {
865  if (theMinOutputValue.size() == 0 ||
866  zero_based_band >= getNumberOfInputBands())
867  {
868  return ossim::nan();
869  }
870 
871  if (zero_based_band >= theMinOutputValue.size())
872  {
874  << "ossimHistogramRemapper::getMinOutputValue ERROR:"
875  << "\nband " << zero_based_band << " is out of range!"
876  << "\nhighest band: " << (theMinOutputValue.size()-1)
877  << endl;
878  return ossim::nan();
879  }
880 
881  return theMinOutputValue[zero_based_band];
882 }
883 
885 {
886  if (theMinOutputValue.size() == 0)
887  {
888  return ossim::nan();
889  }
890 
891  ossim_float64 d = 0.0;
892  const ossim_uint32 BANDS = (ossim_uint32)theMinOutputValue.size();
893  for (ossim_uint32 band = 0; band < BANDS; ++band)
894  {
895  d += getMinOutputValue(band);
896  }
897 
898  return (d / BANDS);
899 }
900 
902 {
903  if (theMaxOutputValue.size() == 0 ||
904  zero_based_band >= getNumberOfInputBands())
905  {
906  return ossim::nan();
907  }
908 
909  if (zero_based_band >= theMaxOutputValue.size())
910  {
912  << "ossimHistogramRemapper::getMaxOutputValue ERROR:"
913  << "\nband " << zero_based_band << " is out of range!"
914  << "\nhighest band: " << (theMaxOutputValue.size()-1)
915  << endl;
916  return ossim::nan();
917  }
918 
919  return theMaxOutputValue[zero_based_band];
920 }
921 
923 {
924  if (theMaxOutputValue.size() == 0)
925  {
926  return ossim::nan();
927  }
928 
929  ossim_float64 d = 0.0;
930  const ossim_uint32 BANDS = (ossim_uint32)theMaxOutputValue.size();
931  for (ossim_uint32 band = 0; band < BANDS; ++band)
932  {
933  d += getMaxOutputValue(band);
934  }
935 
936  return (d / BANDS);
937 }
938 
940  const char* prefix)
941 {
942  static const char MODULE[] = "ossimHistogramRemapper::loadState";
943  if (traceDebug())
944  {
945  CLOG << " Entered..."
946  << "\nprefix: " << prefix << endl;
947  }
948  // Load the base class states...
949  bool status = ossimTableRemapper::loadState(kwl, prefix);
950  if (status)
951  {
952  const char* lookup = 0;
953  ossimString keyword;
954 
955  lookup = kwl.find(prefix, HISTOGRAM_FILENAME_KW);
956  if (lookup)
957  {
958  if ( !openHistogram(ossimFilename(lookup)) )
959  {
961  << "ossimHistogramRemapper::loadState ERROR!"
962  << "\nCould not open file: " << lookup
963  << "\nReturning..." << endl;
964  return false;
965  }
966  }
967 
968  //---
969  // Get the band specific keywords.
970  // NOTES:
971  // - This loadState assumes the all keywords will have the same number
972  // of bands.
973  // - The set methods cannot be used here as there may not be a connection
974  // yet that they need.
975  //---
976  ossim_uint32 bands = 0;
977  lookup = kwl.find(prefix, ossimKeywordNames::NUMBER_BANDS_KW);
978  if (lookup)
979  {
980  bands = ossimString::toUInt32(lookup);
981  }
982  else // For backwards compatibility.
983  {
984  // Use the low clip to find number of bands...
985  keyword = NORMALIZED_LOW_CLIP_POINT_KW;
986  bands = kwl.numberOf(prefix, keyword);
987  }
988  //if(!bands&&theHistogram.valid())
989  // {
990  // bands = theHistogram->getNumberOfBands();
991  // }
992 
993  if (traceDebug())
994  {
996  << "ossimHistogramRemapper::loadState DEBUG:"
997  << "\nBands: " << bands
998  << endl;
999  }
1000  if (bands)
1001  {
1002  // Start with fresh clips.
1003  initializeClips(bands);
1004  for (ossim_uint32 band = 0; band < bands; ++band)
1005  {
1006  // Get the low clip.
1007  keyword = NORMALIZED_LOW_CLIP_POINT_KW;
1008  keyword += ".";
1009  keyword += ossimKeywordNames::BAND_KW;
1010  keyword += ossimString::toString(band+1);
1011  lookup = kwl.find(prefix, keyword);
1012  if(lookup)
1013  {
1014  theNormalizedLowClipPoint[band] = atof(lookup);
1015  }
1016 
1017  // Get the high clip.
1018  keyword = NORMALIZED_HIGH_CLIP_POINT_KW;
1019  keyword += ".";
1020  keyword += ossimKeywordNames::BAND_KW;
1021  keyword += ossimString::toString(band+1);
1022  lookup = kwl.find(prefix, keyword);
1023  if(lookup)
1024  {
1025  theNormalizedHighClipPoint[band] = atof(lookup);
1026  }
1027 
1028  // Get the mid point.
1029  keyword = MID_POINT_KW;
1030  keyword += ".";
1031  keyword += ossimKeywordNames::BAND_KW;
1032  keyword += ossimString::toString(band+1);
1033  lookup = kwl.find(prefix, keyword);
1034  if(lookup)
1035  {
1036  theMidPoint[band] = atof(lookup);
1037  }
1038 
1039  // Get the min output value.
1040  keyword = MIN_OUTPUT_VALUE_KW;
1041  keyword += ".";
1042  keyword += ossimKeywordNames::BAND_KW;
1043  keyword += ossimString::toString(band+1);
1044  lookup = kwl.find(prefix, keyword);
1045  if(lookup)
1046  {
1047  theMinOutputValue[band] = atof(lookup);
1048  }
1049 
1050  // Get the max output value.
1051  keyword = MAX_OUTPUT_VALUE_KW;
1052  keyword += ".";
1053  keyword += ossimKeywordNames::BAND_KW;
1054  keyword += ossimString::toString(band+1);
1055  lookup = kwl.find(prefix, keyword);
1056  if(lookup)
1057  {
1058  theMaxOutputValue[band] = atof(lookup);
1059  }
1060  }
1061  }
1062 
1063  lookup = kwl.find(prefix, STRETCH_MODE_KW);
1064  if (lookup)
1065  {
1066  ossimString s = lookup;
1067  s.downcase();
1068  if (s == STRETCH_MODE[ossimHistogramRemapper::LINEAR_ONE_PIECE])
1069  {
1071  }
1072  else if (s == STRETCH_MODE[ossimHistogramRemapper::LINEAR_1STD_FROM_MEAN])
1073  {
1075  }
1076  else if (s == STRETCH_MODE[ossimHistogramRemapper::LINEAR_2STD_FROM_MEAN])
1077  {
1079  }
1080  else if (s == STRETCH_MODE[ossimHistogramRemapper::LINEAR_3STD_FROM_MEAN])
1081  {
1083  }
1084  else if (s == STRETCH_MODE[ossimHistogramRemapper::LINEAR_AUTO_MIN_MAX])
1085  {
1087  }
1088  else if (s == STRETCH_MODE[ossimHistogramRemapper::LINEAR_AUTO_PERCENTILE])
1089  {
1091  }
1092  else
1093  {
1095  }
1096  }
1097 
1098  // Always set the dirty flag.
1099  theDirtyFlag = true;
1100  }
1101  verifyEnabled();
1102 
1103  if (traceDebug())
1104  {
1105  CLOG << "ossimHistogramRemapper::loadState DEBUG:"
1106  << *this
1107  << "\nExited..." << endl;
1108  }
1109  return status;
1110 }
1111 
1113  const char* prefix) const
1114 {
1115  if (theHistogram.valid())
1116  {
1117  kwl.add(prefix,
1118  HISTOGRAM_FILENAME_KW,
1120  true);
1121  }
1122  kwl.add(prefix,
1123  STRETCH_MODE_KW,
1124  getStretchModeString().c_str(),
1125  true);
1126 
1127  const ossim_uint32 BANDS = (ossim_uint32)theNormalizedLowClipPoint.size();
1128 
1129  kwl.add(prefix,
1131  BANDS,
1132  true);
1133 
1134  for (ossim_uint32 band = 0; band < BANDS; ++band)
1135  {
1136  ossimString keyword;
1137 
1138  // Save the low clip.
1139  keyword = NORMALIZED_LOW_CLIP_POINT_KW;
1140  keyword += ".";
1141  keyword += ossimKeywordNames::BAND_KW;
1142  keyword += ossimString::toString(band+1);
1143  kwl.add(prefix,
1144  keyword,
1146  true);
1147 
1148  // Save the high clip.
1149  keyword = NORMALIZED_HIGH_CLIP_POINT_KW;
1150  keyword += ".";
1151  keyword += ossimKeywordNames::BAND_KW;
1152  keyword += ossimString::toString(band+1);
1153  kwl.add(prefix,
1154  keyword,
1156  true);
1157 
1158  // Save the mid point.
1159  keyword = MID_POINT_KW;
1160  keyword += ".";
1161  keyword += ossimKeywordNames::BAND_KW;
1162  keyword += ossimString::toString(band+1);
1163  kwl.add(prefix,
1164  keyword,
1165  theMidPoint[band],
1166  true);
1167 
1168  // Save the min output value.
1169 
1170  keyword = MIN_OUTPUT_VALUE_KW;
1171  keyword += ".";
1172  keyword += ossimKeywordNames::BAND_KW;
1173  keyword += ossimString::toString(band+1);
1174  kwl.add(prefix,
1175  keyword,
1176  theMinOutputValue[band],
1177  true);
1178 
1179  // Save the max output value.
1180  keyword = MAX_OUTPUT_VALUE_KW;
1181  keyword += ".";
1182  keyword += ossimKeywordNames::BAND_KW;
1183  keyword += ossimString::toString(band+1);
1184 
1185  kwl.add(prefix,
1186  keyword,
1187  theMaxOutputValue[band],
1188  true);
1189  }
1190 
1191  return ossimTableRemapper::saveState(kwl, prefix);
1192 }
1193 
1195  bool rebuildTable)
1196 {
1197  if (theStretchMode != mode)
1198  {
1199  theStretchMode = mode;
1200 
1201  if (rebuildTable)
1202  {
1203  buildTable();
1204 
1205  // Check for internal bypass.
1206  verifyEnabled();
1207 
1208  // Clear the dirty flag.
1209  theDirtyFlag = false;
1210  }
1211  else
1212  {
1213  theDirtyFlag = true;
1214  }
1215  }
1216 }
1217 
1219  bool rebuildTable)
1220 {
1221  if( mode == "linear_one_piece")
1222  {
1223  setStretchMode(LINEAR_ONE_PIECE, rebuildTable);
1224  }
1225  else if(mode == "linear_1std_from_mean")
1226  {
1227  setStretchMode(LINEAR_1STD_FROM_MEAN, rebuildTable);
1228  }
1229  else if(mode == "linear_2std_from_mean")
1230  {
1231  setStretchMode(LINEAR_2STD_FROM_MEAN, rebuildTable);
1232  }
1233  else if(mode == "linear_3std_from_mean")
1234  {
1235  setStretchMode(LINEAR_3STD_FROM_MEAN, rebuildTable);
1236  }
1237  else if(mode == "linear_auto_min_max")
1238  {
1239  setStretchMode(LINEAR_AUTO_MIN_MAX, rebuildTable);
1240  }
1241  else if(mode == "linear_auto_percentile")
1242  {
1243  setStretchMode(LINEAR_AUTO_PERCENTILE, rebuildTable);
1244  }
1245  else
1246  {
1248  }
1249 }
1250 
1252 {
1253  setupTable();
1254  switch(theStretchMode)
1255  {
1257  {
1258  buildLinearTable();
1259  break;
1260  }
1262  {
1264  break;
1265  }
1267  {
1269  break;
1270  }
1275  break;
1276 
1277  default:
1278  if(traceDebug())
1279  {
1281  << "ossimHistogramRemapper::buildTable ERROR!"
1282  << "\nUnknown stretch type!" << endl;
1283  }
1284  break;
1285  }
1286 
1287  if (traceDebug())
1288  {
1290  << "ossimHistogramRemapper::buildTable DEBUG:\n" << endl;
1292  }
1293 }
1294 
1296 {
1297  switch (getOutputScalarType())
1298  {
1299  case OSSIM_UINT8:
1300  {
1302  break;
1303  }
1304 
1305  case OSSIM_USHORT11:
1306  case OSSIM_USHORT12:
1307  case OSSIM_USHORT13:
1308  case OSSIM_USHORT14:
1309  case OSSIM_USHORT15:
1310  case OSSIM_UINT16:
1311  {
1313  break;
1314  }
1315 
1316  case OSSIM_SINT16:
1317  {
1319  break;
1320  }
1321 
1322  case OSSIM_UINT32:
1323  {
1325  break;
1326  }
1327 
1328  case OSSIM_SINT32:
1329  {
1331  break;
1332  }
1333 
1334  case OSSIM_NORMALIZED_FLOAT:
1335  case OSSIM_FLOAT:
1336  {
1338  break;
1339  }
1341  case OSSIM_DOUBLE:
1342  {
1344  break;
1345  }
1346 
1347  case OSSIM_SCALAR_UNKNOWN:
1348  default:
1349  {
1350  if(traceDebug())
1351  {
1352  // Shouldn't hit this.
1354  << "ossimHistogramRemapper::buildLinearTable OSSIM_SCALAR_UNKNOWN!" << endl;
1355  }
1356  break;
1357  }
1358 
1359  } // End of "switch (theTableType)"
1360 }
1361 
1363 {
1364  switch (getOutputScalarType())
1365  {
1366  case OSSIM_UINT8:
1367  {
1369  break;
1370  }
1371 
1372  case OSSIM_USHORT11:
1373  case OSSIM_USHORT12:
1374  case OSSIM_USHORT13:
1375  case OSSIM_USHORT14:
1376  case OSSIM_USHORT15:
1377  case OSSIM_UINT16:
1378  {
1380  break;
1381  }
1382 
1383  case OSSIM_SINT16:
1384  {
1386  break;
1387  }
1388 
1389  case OSSIM_NORMALIZED_FLOAT:
1390  case OSSIM_FLOAT:
1391  {
1393  break;
1394  }
1395 
1397  case OSSIM_DOUBLE:
1398  {
1400  break;
1401  }
1402 
1403  case OSSIM_SCALAR_UNKNOWN:
1404  default:
1405  {
1406  if(traceDebug())
1407  {
1408  // Shouldn't hit this.
1410  << "ossimTableRemapper::buildTable OSSIM_SCALAR_UNKNOWN!"
1411  << endl;
1412  }
1413  break;
1414  }
1415 
1416  } // End of "switch (theTableType)"
1417 }
1418 
1420 {
1421  switch (getOutputScalarType())
1422  {
1423  case OSSIM_UINT8:
1424  {
1426  break;
1427  }
1428 
1429  case OSSIM_USHORT11:
1430  case OSSIM_USHORT12:
1431  case OSSIM_USHORT13:
1432  case OSSIM_USHORT14:
1433  case OSSIM_USHORT15:
1434  case OSSIM_UINT16:
1435  {
1437  break;
1438  }
1439 
1440  case OSSIM_SINT16:
1441  {
1443  break;
1444  }
1445 
1446  case OSSIM_NORMALIZED_FLOAT:
1447  case OSSIM_FLOAT:
1448  {
1450  break;
1451  }
1452 
1454  case OSSIM_DOUBLE:
1455  {
1457  break;
1458  }
1459 
1460  case OSSIM_SCALAR_UNKNOWN:
1461  default:
1462  {
1463  if(traceDebug())
1464  {
1465  // Shouldn't hit this.
1467  << "ossimHistogramRemapper::buildAutoLinearPercentileTableTemplate OSSIM_SCALAR_UNKNOWN!"
1468  << endl;
1469  }
1470  break;
1471  }
1472 
1473  } // End of "switch (theTableType)"
1474 }
1475 
1476 template <class T> void ossimHistogramRemapper::buildLinearTable(T /* dummy */)
1477 {
1478  #if 1
1479  // for now we are not using the lookup
1480  theDirtyFlag = false;
1481  return;
1482 #else
1483 
1484  // This builds a native table.
1485  //theTableType = ossimTableRemapper::NATIVE;
1486 
1487  const ossim_uint32 BANDS = getNumberOfInputBands();
1488 
1489  // Sanity check.
1490  if (theNormalizedLowClipPoint.size() != BANDS || !getHistogram(0).valid())
1491  {
1492  if(traceDebug())
1493  {
1495  << "ossimHistogramRemapper::buildTable ERROR!"
1496  << " Line: " << __LINE__ << endl;
1497  }
1498  return;
1499  }
1500 
1501  T* table = reinterpret_cast<T*>(&theTable.front());
1502  ossim_uint32 index = 0;
1503 
1504  // Finally, build the table...
1505  for (ossim_uint32 band = 0; band < BANDS; ++band)
1506  {
1508  if (h.get())
1509  {
1510  if (traceDebug())
1511  {
1513  << "ossimHistogramRemapper::buildLinearTable DEBUG:"
1514  << "\nband: " << band
1515  << "\nmean: " << h->GetMean()
1516  << "\nstddev: " << h->GetStandardDev()
1517  << endl;
1518  }
1519  }
1520  else
1521  {
1522  if(traceDebug())
1523  {
1525  << "ossimHistogramRemapper::buildTable ERROR!"
1526  << " Line: " << __LINE__ << endl;
1527  }
1528  return;
1529  }
1530  //std::cout << "MIN OUTPUT ==== " << theMinOutputValue[band] << std::endl;
1531  const T NULL_PIX = static_cast<T>(getNullPixelValue(band));
1532  const T MIN_PIX = static_cast<T>(theMinOutputValue[band]);
1533  const T MAX_PIX = static_cast<T>(theMaxOutputValue[band]);
1534  ossim_float64 min_clip_value =
1536  ossim_float64 max_clip_value =
1538  ossim_float64 gain = 1.0;
1540  {
1541  min_clip_value = floor(min_clip_value);
1542  max_clip_value = ceil(max_clip_value);
1543  gain = (MAX_PIX-MIN_PIX)/(max_clip_value-min_clip_value);
1544  // gain = (MAX_PIX-MIN_PIX+1)/(max_clip_value-min_clip_value);
1545 
1546  }
1547  else
1548  {
1549  gain = ((MAX_PIX-MIN_PIX)+1)/(max_clip_value-min_clip_value);
1550  }
1551 
1552  table[index] = NULL_PIX;
1553  ++index;
1554 // std::cout << "min_clip_value === " << min_clip_value << "\n";
1555 // std::cout << "max_clip_value === " << max_clip_value << "\n";
1556 // std::cout << "MIN_PIX === " << MIN_PIX << "\n";
1557 // std::cout << "MAX_PIX === " << MAX_PIX << "\n";
1558 // std::cout << "GAIN === " << gain << "\n";
1559  for (ossim_uint32 pix = 1; pix < theTableBinCount; ++pix)
1560  {
1561  ossim_float64 p = pix;
1562  if (p <= min_clip_value)
1563  {
1564  p = MIN_PIX;
1565  }
1566  else if (p >= max_clip_value)
1567  {
1568  p = MAX_PIX;
1569  }
1570  else
1571  {
1572  p = ((p - min_clip_value) * gain) + MIN_PIX - 1.0;
1573  }
1574 
1575  if(p == NULL_PIX)
1576  {
1577  p = MIN_PIX;
1578  }
1579  table[index] = static_cast<T>(p+0.5);
1580 
1581  ++index;
1582  }
1583  } // End of band loop.
1584 
1585  // Clear the dirty flag so the table's not rebuilt on the next getTile.
1586  theDirtyFlag = false;
1587 #endif
1588 }
1589 
1591 {
1592  const ossim_uint32 BANDS = getNumberOfInputBands();
1593 
1594  // Sanity check.
1595  if (theNormalizedLowClipPoint.size() != BANDS || !getHistogram(0).valid())
1596  {
1597  if(traceDebug())
1598  {
1600  << "ossimHistogramRemapper::buildAutoLinearMinMaxTableTemplate ERROR!"
1601  << " Line: " << __LINE__ << endl;
1602  }
1603  return;
1604  }
1605  for (ossim_uint32 band = 0; band < BANDS; ++band)
1606  {
1608  T nullPix = static_cast<T>(getNullPixelValue(band));
1609  //h->fillInteriorEmptyBins();
1610  // std::cout << "************************\n";
1611 
1612  if(h.valid())
1613  {
1614 
1615  ossim_uint32 n = h->GetRes();
1616  ossim_float64 low = h->GetIndex(h->GetMinVal());
1617  ossim_float64 high = h->GetIndex(h->GetMaxVal());
1618  double bias = .006;//.006;
1619  if(n > 0)
1620  {
1621  double newCount = 0.0;
1622  double nextPercentage = 0.0;
1623  double percentage = 0.0;
1624  int idx = 0;
1625  const float * counts = h->GetCounts();
1626  double count = h->ComputeArea();
1627  for(idx = 0; idx < (ossim_int32)(n-1); ++idx)
1628  {
1629  bool hasValue = (counts[idx] > 0)&&(counts[idx+1]);
1630  if(nullPix != idx)
1631  {
1632  newCount += counts[idx];
1633  }
1634  percentage = newCount / count;
1635  nextPercentage = (newCount + counts[idx+1]) / count;
1636 // if (std::fabs(percentage - 0.006) <
1637 // std::fabs(nextPercentage - 0.006))
1638  if (hasValue &&((std::fabs(percentage - bias) <
1639  std::fabs(nextPercentage - bias))))
1640  {
1641  low = idx+1;
1642  break;
1643  }
1644 
1645  }
1646  newCount = 0.0;
1647  for (idx = n-1; idx > 0; idx--)
1648  {
1649  bool hasValue = (counts[idx] > 0)&&(counts[idx-1]);
1650  newCount += counts[idx];
1651  percentage = newCount / count;
1652  nextPercentage = (newCount + counts[idx-1]) / count;
1653  if (hasValue && ((std::fabs(percentage - bias) <
1654  std::fabs(nextPercentage - bias))))
1655  {
1656  high=idx-1;
1657  break;
1658  }
1659  }
1660  if(low > high)
1661  {
1662  low = 0;
1663  high = n - 1;
1664  }
1665 
1667  {
1668  setLowClipPoint(low, band);
1669  setHighClipPoint(high, band);
1670  }
1671  else
1672  {
1673  setLowClipPoint(h->GetMinValFromIndex(low), band);
1674  setHighClipPoint(h->GetMaxValFromIndex(high), band);
1675  }
1676  }
1677  }
1678  }
1679 
1680  buildLinearTable();
1681 }
1682 
1684 {
1685  const ossim_uint32 BANDS = getNumberOfInputBands();
1686 
1687  // Sanity check.
1688  if (theNormalizedLowClipPoint.size() != BANDS || !getHistogram(0).valid())
1689  {
1690  if(traceDebug())
1691  {
1693  << "ossimHistogramRemapper::buildTable ERROR!"
1694  << " Line: " << __LINE__ << endl;
1695  }
1696  return;
1697  }
1698 
1699  ossim_float64 multiplier = 1.0;
1701  {
1702  multiplier = 2.0;
1703  }
1705  {
1706  multiplier = 3.0;
1707  }
1708 
1709  // Finally, build the table...
1710  for (ossim_uint32 band = 0; band < BANDS; ++band)
1711  {
1713  ossim_float64 mean = 0.0;
1714  ossim_float64 stdDev = 0.0;
1715  if(h.valid())
1716  {
1717  mean = h->GetMean();
1718  stdDev = h->GetStandardDev();
1719  }
1720  ossim_float64 lowClip = mean - (stdDev * multiplier);
1721  ossim_float64 highClip = mean + (stdDev * multiplier);
1722 
1723  // Clamp to min/max.
1724  if (lowClip < theMinOutputValue[band])
1725  {
1726  lowClip = theMinOutputValue[band];
1727  }
1728  if (highClip > theMaxOutputValue[band])
1729  {
1730  highClip = theMaxOutputValue[band];
1731  }
1732 
1733  setLowClipPoint(lowClip, band);
1734  setMidPoint(mean, band);
1735  setHighClipPoint(highClip, band);
1736 
1737  if (traceDebug())
1738  {
1740  << "ossimHistogramRemapper::buildLinearStdFromMean DEBUG:"
1741  << "\nband: " << band
1742  << "\nmean: " << mean
1743  << "\nstddev: " << stdDev
1744  << "\nlow clip: " << lowClip
1745  << "\nhigh clip: " << highClip
1746  << endl;
1747  }
1748  }
1749 
1750  buildLinearTable();
1751 }
1752 
1754 {
1755  const ossim_uint32 BANDS = getNumberOfInputBands();
1756 
1757  // Sanity check.
1758  if (theNormalizedLowClipPoint.size() != BANDS || !getHistogram(0).valid())
1759  {
1760  if(traceDebug())
1761  {
1763  << "ossimHistogramRemapper::buildAutoLinearMinMaxTableTemplate ERROR!"
1764  << " Line: " << __LINE__ << endl;
1765  }
1766  return;
1767  }
1768  for (ossim_uint32 band = 0; band < BANDS; ++band)
1769  {
1771  // T nullPix = static_cast<T>(getNullPixelValue(band));
1772  // h->fillInteriorEmptyBins();
1773  if(h.valid())
1774  {
1775  ossim_uint32 n = h->GetRes();
1776  ossim_float64 low = h->GetIndex(h->LowClipVal(0.05));
1777  ossim_float64 high = h->GetIndex(h->HighClipVal(0.05));
1778  if(low > high)
1779  {
1780  low = 0;
1781  high = n - 1;
1782  }
1783  if(low < 0) low = 0;
1784  if(high < 0) high = n-1;
1785 
1787  {
1788  setLowClipPoint(low, band);
1789  setHighClipPoint(high, band);
1790  }
1791  else
1792  {
1793  setLowClipPoint(h->GetValFromIndex(static_cast<ossim_uint32>(low)), band);
1794  setHighClipPoint(h->GetValFromIndex(static_cast<ossim_uint32>(high)), band);
1795  }
1796  }
1797  }
1798 
1799  buildLinearTable();
1800 }
1801 
1803 {
1805 }
1806 
1808 {
1809  //---
1810  // NOTE: This method deoes not set theDirtyFlag by design.
1811  //---
1812  if (bands)
1813  {
1814  theNormalizedLowClipPoint.resize(bands);
1815  theNormalizedHighClipPoint.resize(bands);
1816  theMidPoint.resize(bands);
1817  theMinOutputValue.resize(bands);
1818  theMaxOutputValue.resize(bands);
1819 
1820  for (ossim_uint32 band = 0; band < bands; ++band)
1821  {
1822  theNormalizedLowClipPoint[band] = 0.0;
1823  theNormalizedHighClipPoint[band] = 1.0;
1824  theMidPoint[band] = 0.0;
1825 
1826  switch(theOutputScalarType)
1827  {
1828  case OSSIM_FLOAT32:
1829  case OSSIM_FLOAT64:
1830  {
1831  theMinOutputValue[band] = getMinPixelValue(band);
1832  theMaxOutputValue[band] = getMaxPixelValue(band);
1833  break;
1834  }
1835  case OSSIM_SCALAR_UNKNOWN:
1836  {
1837  theMinOutputValue[band] = 0.0;
1838  theMaxOutputValue[band] = 0.0;
1839  }
1840  default:
1841  {
1842  theMinOutputValue[band] = ossim::defaultMin(theOutputScalarType);//getMinPixelValue(band);
1843  theMaxOutputValue[band] = ossim::defaultMax(theOutputScalarType);//getMaxPixelValue(band);
1844  break;
1845  }
1846  }
1847  }
1848  }
1849 }
1850 
1852 {
1854  theMinOutputValue.resize(nBands);
1855  theMaxOutputValue.resize(nBands);
1856  for (ossim_uint32 band = 0; band < nBands; ++band)
1857  {
1858  // Must have an output scalar type for getMin/Max call.
1860  {
1861  theMinOutputValue[band] = ossim::defaultMin(theOutputScalarType);//getMinPixelValue(band);
1862  theMaxOutputValue[band] = ossim::defaultMax(theOutputScalarType);//getMaxPixelValue(band);
1863  }
1864  else
1865  {
1866  theMinOutputValue[band] = 0.0;
1867  theMaxOutputValue[band] = 0.0;
1868  }
1869  }
1870 
1871 }
1872 
1874 {
1875  // This will set the null bucket for all res zero bands to zero!
1876  if (getHistogram(0).valid())
1877  {
1878  const ossim_uint32 BANDS = theHistogram->getNumberOfBands();
1879  for (ossim_uint32 band = 0; band < BANDS; ++band)
1880  {
1882  if (h.valid())
1883  {
1884  h->SetCount(0, 0);
1885  }
1886  }
1887  }
1888 }
1889 
1891 {
1892  return theStretchMode;
1893 }
1894 
1896 {
1897  return ossimString(STRETCH_MODE[theStretchMode]);
1898 }
1899 
1901 {
1902  return ossimHistogramRemapper::STRETCH_UNKNOWN; // last index
1903 }
1904 
1907 {
1909  {
1910  return ossimString(STRETCH_MODE[index]);
1911  }
1912 
1914 
1915 }
1916 
1918 {
1919  os << setiosflags(ios::fixed) << setprecision(15)
1920  << "\nossimHistogramRemapper::print:"
1921  << "\ntheStretchMode: " << getStretchModeString().c_str()
1922  << "\ntheDirtyFlag: " << (theDirtyFlag?"true":"false")
1923  << "\ntheBypassFlag: " << (theBypassFlag?"true":"false")
1924 
1925  << "\ntheHistogram: " << (theHistogram.valid()?"initialized":"null")
1926  << "\ntheTableSizeInBytes: " << theTable.size()
1927  << endl;
1928 
1929  const ossim_uint32 BANDS = (ossim_uint32)theNormalizedLowClipPoint.size();
1930  for (ossim_uint32 band = 0; band < BANDS; ++band)
1931  {
1932  os << "\ntheNormalizedLowClipPoint[" << band << "]: "
1933  << theNormalizedLowClipPoint[band]
1934  << "\ntheNormalizedHighClipPoint[" << band << "]: "
1936  << "\ntheMidPoint[" << band << "]: "
1937  << theMidPoint[band]
1938  << "\ntheMinOutputValue[" << band << "]: "
1939  << theMinOutputValue[band]
1940  << "\ntheMaxOutputValue[" << band << "]: "
1941  << theMaxOutputValue[band]
1942  << endl;
1943  }
1944 
1945  for (ossim_uint32 i = 0; i < theBandList.size(); ++i)
1946  {
1947  os << "theBandList[" << i << "]: " << theBandList[i] << endl;
1948  }
1949 
1950  // Note: To set table call ossimTableRemapper::print or turn trace on
1951  // for "ossimTableRemapper:debug"
1952 
1953  return os;
1954 }
1955 
1957 {
1958  const ossim_uint32 BANDS = getNumberOfInputBands();
1959 
1960 
1961  ossim_uint32 values_per_band = 0;
1962  ossim_uint32 bytes_per_pixel = 0;
1963 
1964  switch (theOutputScalarType)
1965  {
1966  case OSSIM_UINT8:
1967  values_per_band = 256; // 2 ^ 8
1968  bytes_per_pixel = 1;
1970  break;
1971 
1972  case OSSIM_USHORT11:
1973  values_per_band = 2048; // 2 ^ 11
1974  bytes_per_pixel = 2;
1976  break;
1977  case OSSIM_USHORT12:
1978  values_per_band = 4096; // 2 ^ 12
1979  bytes_per_pixel = 2;
1981  break;
1982  case OSSIM_USHORT13:
1983  values_per_band = 8192; // 2 ^ 13
1984  bytes_per_pixel = 2;
1986  break;
1987  case OSSIM_USHORT14:
1988  values_per_band = 16384; // 2 ^ 14
1989  bytes_per_pixel = 2;
1991  break;
1992  case OSSIM_USHORT15:
1993  values_per_band = 32768; // 2 ^ 15
1994  bytes_per_pixel = 2;
1996  break;
1997 
1998  case OSSIM_UINT16:
1999  case OSSIM_SINT16:
2000  values_per_band = 65536; // 2 ^ 16
2001  bytes_per_pixel = 2;
2003  break;
2004 
2005  case OSSIM_UINT32:
2006  case OSSIM_SINT32:
2007  values_per_band = 65536; // 2 ^ 16
2008  bytes_per_pixel = 4;
2010  break;
2011 
2013  {
2014  bytes_per_pixel = 4;
2016  break;
2017  }
2018  case OSSIM_FLOAT:
2019  bytes_per_pixel = 4;
2020  values_per_band = 65536; // 2 ^ 16
2022  break;
2023 
2025  {
2026  bytes_per_pixel = 8;
2027  values_per_band = 65536; // 2 ^ 16
2029  break;
2030  }
2031  case OSSIM_DOUBLE:
2032  bytes_per_pixel = 8;
2033  values_per_band = 65536; // 2 ^ 16
2035  break;
2036 
2037  default:
2038  break;
2039  }
2040 
2041  if (theNormalizedLowClipPoint.size() == 0)
2042  {
2043  initializeClips(BANDS);
2044  }
2045 
2046  if ( theOutputScalarType == OSSIM_FLOAT ||
2050  {
2051  for (ossim_uint32 band = 0; band < BANDS; ++band)
2052  {
2054 
2055  if (h.valid())
2056  {
2057  if (h->GetRes() > static_cast<ossim_int32>(values_per_band))
2058  {
2059  values_per_band = h->GetRes();
2060  }
2061  }
2062  }
2063  }
2064 
2065  theTableBinCount = values_per_band;
2066  theTableBandCount = BANDS;
2067 
2068  ossim_uint32 size_in_bytes = values_per_band * BANDS * bytes_per_pixel;
2069  theTable.resize(size_in_bytes);
2070 
2071  ossimImageSource* input = dynamic_cast<ossimImageSource*>(getInput());
2072  double minPix = ossim::defaultMin(getOutputScalarType());
2073  double maxPix = ossim::defaultMax(getOutputScalarType());
2074 
2075  if(input)
2076  {
2077  //---
2078  // Last check for NaNs in key data members and set to some default if so.
2079  // This could occur if someone stripped a keyword list down to a minimal
2080  // set of keywords.
2081  //---
2082  for (ossim_uint32 band = 0; band < BANDS; ++band)
2083  {
2084  minPix = input->getMinPixelValue(band);
2085  maxPix = input->getMaxPixelValue(band);
2086  if ( ossim::isnan(theMinOutputValue[band]) )
2087  {
2088  theMinOutputValue[band] = minPix;
2089  }
2090  if ( ossim::isnan(theMaxOutputValue[band]) )
2091  {
2092  theMaxOutputValue[band] = maxPix;
2093  }
2094  }
2095  }
2096  else
2097  {
2098  //---
2099  // Last check for NaNs in key data members and set to some default if so.
2100  // This could occur if someone stripped a keyword list down to a minimal
2101  // set of keywords.
2102  //---
2103  for (ossim_uint32 band = 0; band < BANDS; ++band)
2104  {
2105  if ( ossim::isnan(theMinOutputValue[band]) )
2106  {
2107  theMinOutputValue[band] = minPix;
2108  }
2109  if ( ossim::isnan(theMaxOutputValue[band]) )
2110  {
2111  theMaxOutputValue[band] = maxPix;
2112  }
2113  }
2114  }
2115 }
2116 
2118 {
2119  //---
2120  // Since this filter can be constructed with no input connection do not
2121  // output and error, simply return.
2122  //---
2123  setBypassFlag(true);
2124  //if (theInputConnection)
2125  {
2126 
2127 #if 1
2128  // Start off bypassed.
2129 
2131  {
2132  if(theHistogram.valid())
2133  {
2134  setBypassFlag(false);
2135  }
2136 /*
2137  const ossim_uint32 BANDS =
2138  (ossim_uint32)theNormalizedLowClipPoint.size();
2139  for (ossim_uint32 band = 0; band < BANDS; ++band)
2140  {
2141  //const double MIN = ossimTableRemapper::getMinPixelValue(band);
2142  //const double MAX = ossimTableRemapper::getMaxPixelValue(band);
2143  if ( theNormalizedLowClipPoint[band] != 0.0 ||
2144  theNormalizedHighClipPoint[band] != 1.0 )
2145  // theMinOutputValue[band] != MIN ||
2146  //theMaxOutputValue[band] != MAX )
2147  {
2148  // Need to turn filter on.
2149  setBypassFlag(false);
2150  break;
2151  }
2152  }
2153  */
2154  }
2155 #endif
2156  }
2157  if (traceDebug())
2158  {
2160  << "ossimHistogramRemapper::verifyEnabled theBypassFlag: "
2161  << (theBypassFlag ? "true" : "false") << endl;
2162  }
2163 }
2164 
2166 {
2168 }
2169 
2171 {
2173 }
2174 
2177  ossim_uint32 res_level) const
2178 {
2179  ossim_uint32 histogram_band = getHistogramBand(zero_based_band);
2180 
2181  if(!theHistogram.valid())
2182  {
2183  const ossimHistogramSource* source = dynamic_cast<const ossimHistogramSource*>(getInput(1));
2184  if(source)
2185  {
2186  theHistogram = const_cast<ossimHistogramSource*>(source)->getHistogram();
2187  }
2188  }
2189 
2190  if (theHistogram.valid())
2191  {
2192  if (histogram_band < theHistogram->getNumberOfBands())
2193  {
2194  return theHistogram->getHistogram(histogram_band, res_level);
2195  }
2196  }
2197 
2198  return 0;
2199 }
2200 
2202 {
2203  if (theHistogram.valid())
2204  {
2205  return theHistogram->getHistogramFile();
2206  }
2207 
2208  return ossimFilename::NIL;
2209 }
2210 
2213 {
2214  if(theResetBandIndicesFlag) return input_band;
2215  vector<ossim_uint32> bandList;
2216  getOutputBandList(bandList);
2217 
2218  const ossim_uint32 BANDS = (ossim_uint32)bandList.size();
2219 
2220  if (BANDS == 0)
2221  {
2222  return 0;
2223  }
2224 
2225  return bandList[input_band];
2226 }
2227 
2229 {
2230  return ossimString("Histogram Remapper, filter with controls for histogram stretching.");
2231 }
2232 
2234 {
2235  return ossimString("Histogram Remapper");
2236 }
2237 
2238 // Private to disallow use...
2240 {
2241 }
2242 
2243 // Private to disallow use...
2245 {
2246  return *this;
2247 }
2248 
2250 {
2251  if (theBypassFlag != flag)
2252  {
2253  //---
2254  // If switching from bypassed to enabled set
2255  // the dirty flag. We don't care about going the other way.
2256  //---
2257  if ( theBypassFlag && !flag )
2258  {
2259  theDirtyFlag = true;
2260  }
2261  theBypassFlag = flag;
2262  }
2263 }
2264 
2266 {
2267  double result = ossimTableRemapper::getMinPixelValue(band);
2268  if(theEnableFlag&&!theBypassFlag &&(band < theMinOutputValue.size()))
2269  {
2270  result = theMinOutputValue[band];
2271  }
2272  // if(theOutputScalarType != OSSIM_SCALAR_UNKNOWN)
2273  // {
2274  // return ossim::defaultMin(theOutputScalarType);
2275  // }
2276 
2277  return result;
2278 }
2279 
2281 {
2282  double result = ossimTableRemapper::getMaxPixelValue(band);
2283 
2284  if(theEnableFlag&&!theBypassFlag &&(band < theMaxOutputValue.size()))
2285  {
2286  result = theMaxOutputValue[band];
2287  }
2288  //if(theOutputScalarType != OSSIM_SCALAR_UNKNOWN)
2289  // {
2290  // result = ossim::defaultMax(theOutputScalarType);
2291  // }
2292 
2293  return result;
2294 }
2295 
2297  const ossimConnectableObject* object)const
2298 {
2299  // we will alloe the histogram source only to be connected to input slot 2 and
2300  // the first slot will be reserved for the ossimImageSource.
2301  //
2302  bool result = false;
2303  if(inputIndex == 0) result = dynamic_cast<const ossimImageSource*>(object)!=0;
2304  if(inputIndex == 1) result = dynamic_cast<const ossimHistogramSource*>(object)!=0;
2305 
2306  return result;
2307 }
16 bit unsigned integer (15 bits used)
virtual void setNumberOfInputs(ossim_int32 numberOfInputs)
Will set the number of inputs.
virtual void getOutputBandList(std::vector< ossim_uint32 > &bandList) const
virtual double getMinPixelValue(ossim_uint32 band=0) const
Returns the min pixel of the band.
RemapTableType theTableType
virtual bool importHistogram(const ossimFilename &inputFile)
virtual ossim_uint32 getNumberOfInputBands() const
void setHighClipPoint(const ossim_float64 &clip)
Sets the high clip point.
ossimRefPtr< ossimHistogram > getHistogram(ossim_uint32 band, ossim_uint32 resLevel=0)
ossim_uint32 numberOf(const char *str) const
virtual ossim_uint32 getNumberOfBands() const
vector< ossim_float64 > theNormalizedLowClipPoint
64 bit floating point
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of an object to a keyword list.
void buildAutoLinearMinMaxTableTemplate(T dummy)
#define CLOG
Definition: ossimTrace.h:23
virtual void setImageRectangle(const ossimIrect &rect)
static const ossimFilename NIL
This was taken from Wx widgets for performing touch and access date stamps.
Definition: ossimFilename.h:40
16 bit unsigned integer
ossim_float64 getLowNormalizedClipPoint() const
Returns the normalized low clip point which is the average of all bands.
void buildLinearTableStdFromMean()
Sets clip points using mean and standard deviations then calls buildLinearTable method.
ossim_float64 getHighClipPoint() const
Returns the high clip point which is the average of all bands.
virtual void populateHistogram(ossimRefPtr< ossimMultiBandHistogram > histo)
Represents serializable keyword/value map.
bool theEnableFlag
Definition: ossimSource.h:62
virtual ostream & print(ostream &os) const
Outputs theErrorStatus as an ossimErrorCode and an ossimString.
bool valid() const
Definition: ossimRefPtr.h:75
const char * find(const char *key) const
float getHighFractionFromValue(float val) const
float ossim_float32
void setHighNormalizedClipPoint(const ossim_float64 &clip)
Sets the high clip point.
ossimRefPtr< ossimMultiResLevelHistogram > theHistogram
ossimFilename getHistogramFile() const
Returns the currently opened histogram.
double nan()
Method to return ieee floating point double precision NAN.
Definition: ossimCommon.h:135
ossimRefPtr< ossimImageData > theTile
bool computeHistogram(const ossimIrect &roi)
Compute the histogram from input connection and region of interest.
vector< ossim_uint32 > theBandList
ossimHistogramRemapper & operator=(const ossimHistogramRemapper &hr)
virtual ossimScalarType getOutputScalarType() const
This will be used to query the output pixel type of the tile source.
virtual ~ossimHistogramRemapper()
virtual destructor
std::vector< ossim_uint8 > theTable
vector< ossim_float64 > theNormalizedHighClipPoint
static ossimString toString(bool aValue)
Numeric to string methods.
ossim_float64 getMaxOutputValue() const
Returns the maximum output value which is the average of all bands.
16 bit signed integer
void setLowClipPoint(const ossim_float64 &clip)
Sets the low clip point.
ossimRefPtr< ossimMultiResLevelHistogram > getHistogram()
ossim_uint32 getHistogramBand(ossim_uint32 input_band) const
Returns the histogram band that maps to the input band.
virtual ossimDataObjectStatus getDataObjectStatus() const
void setupTable()
Initialized base class (ossimTableRemapper) values:
16 bit unsigned integer (14 bits used)
ossim_uint32 toUInt32() const
16 bit unsigned integer (13 bits used)
32 bit floating point
void initializeClips()
Uses getNumberOfInputBands() to determine BANDS then calls initializeClips(BANDS) ...
float GetMaxValFromIndex(ossim_uint32 idx) const
unsigned short ossim_uint16
32 bit unsigned integer
virtual ossimRefPtr< ossimImageData > getTile(const ossimIrect &tile_rect, ossim_uint32 resLevel=0)
ossim_float64 getLowClipPoint() const
Returns the low clip point which is the average of all bands.
void setMidPoint(const ossim_float64 &value)
Sets the mid clip point.
virtual void initialize()
ossimConnectableObject * getInput(ossim_uint32 index=0)
returns the object at the specified index.
ossim_uint32 getNumberOfStretchModes() const
Returns the number of stretch modes.
void setStretchMode(StretchMode mode, bool rebuildTableFlag=false)
Sets remap mode to mode.
virtual double getMinPixelValue(ossim_uint32 band=0) const
Returns the min pixel of the band.
double ossim_float64
void add(const char *prefix, const ossimKeywordlist &kwl, bool overwrite=true)
void makeClean()
If we are dirty then it will init what it needs and then set the dirty back to false;.
int GetRes() const
vector< ossim_float64 > theMinOutputValue
void verifyEnabled()
This set theBypassFlag.
float GetValFromIndex(ossim_uint32 idx) const
OSSIM_DLL double defaultMin(ossimScalarType scalarType)
Definition: ossimCommon.cpp:73
ossim_float64 getMinOutputValue() const
Returns the minimum output value which is the average of all bands.
float GetMean() const
virtual ossimDataObjectStatus validate() const
signed short ossim_sint16
float GetStandardDev() const
virtual ossimString getLongName() const
StretchMode getStretchMode() const
Returns the current enumerated node.
os2<< "> n<< " > nendobj n
32 bit signed integer
virtual ossim_uint32 getSizePerBand() const
Returns the number of pixels in a single band in a tile.
ossimImageSource * theInputConnection
unsigned int ossim_uint32
32 bit normalized floating point
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to the save the state to a keyword list.
virtual int GetIndex(float) const
void allocate(const ossimIrect &rect)
signed int ossim_sint32
virtual void addHistogram(ossimMultiBandHistogram *histo)
static const char * NUMBER_BANDS_KW
static ossimString downcase(const ossimString &aString)
Definition: ossimString.cpp:48
float HighClipVal(float clip_fraction) const
static const char * BAND_KW
vector< ossim_float64 > theMaxOutputValue
ossim_uint32 getNumberOfBands(ossim_uint32 resLevel=0) const
void setMinOutputValue(const ossim_float64 &value)
Sets the min output value.
float LowClipVal(float clip_fraction) const
ossim_float64 getMidPoint() const
Returns the mid clip point which is the average of all bands.
float GetMinValFromIndex(ossim_uint32 idx) const
return status
virtual void makeBlank()
Initializes data to null pixel values.
64 bit normalized floating point
float GetMinVal() const
16 bit unsigned integer (11 bits used)
OSSIM_DLL double defaultMax(ossimScalarType scalarType)
void applyLinearStretch(T dummy, ossimRefPtr< ossimImageData > &inputTile)
ossim_uint32 theTableBandCount
ossimHistogramRemapper()
default constructor
void buildAutoLinearPercentileTableTemplate(T dummy)
virtual double getMaxPixelValue(ossim_uint32 band=0) const
Returns the max pixel of the band.
vector< ossim_float64 > theMidPoint
ossimScalarType theOutputScalarType
virtual const void * getBuf() const
ossimString getStretchModeString() const
Returns the string for current remap mode.
float * GetCounts()
ossim_uint32 theTableBinCount
const char * c_str() const
Returns a pointer to a null-terminated array of characters representing the string&#39;s contents...
Definition: ossimString.h:396
ossim_float64 getHighNormalizedClipPoint() const
Returns the normalized High clip point which is the average of all bands.
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
virtual double getMaxPixelValue(ossim_uint32 band=0) const
Returns the max pixel of the band.
void setBypassFlag(bool flag)
Sets theBypassFlag.
virtual ossimString getShortName() const
void setStretchModeAsString(const ossimString &mode, bool rebuildTableFlag=false)
Stretch mode values can be linear_one_piece, linear_1std_from_mean, linear_2std_from_mean, linear_3std_from_mean, linear_auto_min_max, If rebuildTableFlag is true, the table will be built at this time; else just the dirty flag is set.
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
float ComputeArea(float low, float high) const
8 bit unsigned integer
#define RTTI_DEF1(cls, name, b1)
Definition: ossimRtti.h:485
ossimDataObjectStatus
Definitions for data object status.
bool canConnectMyInputTo(ossim_int32 inputIndex, const ossimConnectableObject *object) const
Will test for the input being a ossimHistogramSource and allow pulling the histogram from a histogram...
32 bit floating point
void setHistogram(ossimRefPtr< ossimMultiResLevelHistogram > histogram)
Sets the histogram.
void create(const ossimImageSource *input)
float GetMaxVal() const
void setLowNormalizedClipPoint(const ossim_float64 &clip)
Sets the low clip point.
64 bit floating point
16 bit signed integer
unsigned char ossim_uint8
virtual double getNullPixelValue(ossim_uint32 band=0) const
Each band has a null pixel associated with it.
virtual ossimFilename getHistogramFile() const
float getLowFractionFromValue(float val) const
float SetCount(float pixelval, float count)
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
bool openHistogram(const ossimFilename &histogram_file)
Open the histogram file.
std::basic_ostream< char > ostream
Base class for char output streams.
Definition: ossimIosFwd.h:23
int ossim_int32
virtual ossimRefPtr< ossimImageData > getTile(const ossimIpt &origin, ossim_uint32 resLevel=0)
void setMaxOutputValue(const ossim_float64 &value)
Sets the max output value.
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