OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimPixelFlipper.cpp
Go to the documentation of this file.
1 //*******************************************************************
2 //
3 // License: See top level LICENSE.txt file.
4 //
5 // Author: David Burken
6 //
7 // Description:
8 //
9 // Filter to toggle pixel values.
10 //
11 //*************************************************************************
12 // $Id: ossimPixelFlipper.cpp 21631 2012-09-06 18:10:55Z dburken $
13 
15 #include <ossim/base/ossimTrace.h>
21 #include <cstdlib>
22 
24 
25 static ossimTrace traceDebug("ossimPixelFlipper:debug");
26 
27 const char ossimPixelFlipper::PF_TARGET_VALUE_KW[] = "target_value";
28 const char ossimPixelFlipper::PF_TARGET_RANGE_KW[] = "target_range";
29 const char ossimPixelFlipper::PF_REPLACEMENT_VALUE_KW[] = "replacement_value";
30 const char ossimPixelFlipper::PF_REPLACEMENT_MODE_KW[] = "replacement_mode";
31 const char ossimPixelFlipper::PF_CLAMP_VALUE_KW[] = "clamp_value"; // deprecated by clamp_value_hi
32 const char ossimPixelFlipper::PF_CLAMP_VALUE_LO_KW[] = "clamp_value_lo";
33 const char ossimPixelFlipper::PF_CLAMP_VALUE_HI_KW[] = "clamp_value_hi";
34 const char ossimPixelFlipper::PF_CLIP_MODE_KW[] = "border_clip_mode";
35 
36 static const char TARGET_LOWER_LIMIT_PROP_NAME[] = "target_range_lower_limit";
37 static const char TARGET_UPPER_LIMIT_PROP_NAME[] = "target_range_upper_limit";
38 
39 #ifdef OSSIM_ID_ENABLED
40 static const char OSSIM_ID[] = "$Id: ossimPixelFlipper.cpp 21631 2012-09-06 18:10:55Z dburken $";
41 #endif
42 
44  : ossimImageSourceFilter(owner),
45  theTargetValueLo(0.0),
46  theTargetValueHi(0.0),
47  theReplacementValue(1.0),
48  theReplacementMode(ossimPixelFlipper::REPLACE_BAND_IF_TARGET),
49  theClampValueLo(ossim::nan()),
50  theClampValueHi(ossim::nan()),
51  theClampingMode(DISABLED),
52  theClipMode(NONE)
53 {
54  if (traceDebug())
55  {
57  << "ossimPixelFlipper::ossimPixelFlipper entered...\n";
58 #ifdef OSSIM_ID_ENABLED
60  << "OSSIM_ID: " << OSSIM_ID << "\n";
61 #endif
62  }
63 
64  setDescription(ossimString("Pixel Flipper"));
65  enableSource();
66 }
67 
69 {
70 }
71 
73  const ossimIrect &tile_rect, ossim_uint32 resLevel)
74 {
75 
76  if (!theInputConnection)
77  {
78  return 0;
79  }
80 
81  // Fetch tile from pointer from the input source.
82  ossimRefPtr<ossimImageData> inputTile =
83  theInputConnection->getTile(tile_rect, resLevel);
84 
85  if (!inputTile.valid() || !isSourceEnabled())
86  return inputTile;
87 
88  if (!inputTile->getBuf())
89  return inputTile;
90 
91  // Lock for the length of this method.
92  std::lock_guard<std::recursive_mutex> scopeLock(theMutex);
93 
94  // Call the appropriate load method.
95  switch (inputTile->getScalarType())
96  {
97 
98  case OSSIM_UCHAR:
99  {
100  flipPixels(ossim_uint8(0), inputTile.get(), resLevel);
101  break;
102  }
103 
104  case OSSIM_UINT16:
105  case OSSIM_USHORT11:
106  case OSSIM_USHORT12:
107  case OSSIM_USHORT13:
108  case OSSIM_USHORT14:
109  case OSSIM_USHORT15:
110  {
111  flipPixels(ossim_uint16(0), inputTile.get(), resLevel);
112  break;
113  }
114 
115  case OSSIM_SSHORT16:
116  {
117  flipPixels(ossim_sint16(0), inputTile.get(), resLevel);
118  break;
119  }
120  case OSSIM_UINT32:
121  {
122  flipPixels(ossim_uint32(0), inputTile.get(), resLevel);
123  break;
124  }
125  case OSSIM_SINT32:
126  {
127  flipPixels(ossim_sint32(0), inputTile.get(), resLevel);
128  break;
129  }
130  case OSSIM_FLOAT32:
132  {
133  flipPixels(ossim_float32(0), inputTile.get(), resLevel);
134  break;
135  }
136 
138  case OSSIM_FLOAT64:
139  {
140  flipPixels(ossim_float64(0), inputTile.get(), resLevel);
141  break;
142  }
143 
145  default:
146  {
148  << "ossimPixelFlipper::getTile Unsupported scalar type!" << endl;
149  break;
150  }
151  }
152 
153  inputTile->validate();
154  return inputTile;
155 }
156 
157 template <class T>
158 void ossimPixelFlipper::flipPixels(T /* dummy */,
159  ossimImageData *inputTile,
160  ossim_uint32 resLevel)
161 {
162  if (!inputTile)
163  return;
164 
165  T targetLo = static_cast<T>(theTargetValueLo);
166  T targetHi = static_cast<T>(theTargetValueHi);
167  T replacement = static_cast<T>(theReplacementValue);
168  T clampLo = static_cast<T>(theClampValueLo);
169  T clampHi = static_cast<T>(theClampValueHi);
170 
171  // Get pointers to data for each band.
172  ossim_uint32 bands = inputTile->getNumberOfBands();
173  ossim_uint32 band;
174  T **buf = new T *[bands];
175  for (band = 0; band < bands; ++band)
176  buf[band] = static_cast<T *>(inputTile->getBuf(band));
177 
178  ossimIrect rect = inputTile->getImageRectangle();
179  ossimIpt ul = rect.ul();
180  ossimIpt lr = rect.lr();
181 
182  // Check the relation between tile rect and the area of interest (either bounding rect or
183  // valid vertices polygons). If completely outside, we can return with empty buffer.get If
184  // partially inside, we'll need to test individual pixels.
185  bool is_outside_aoi = false;
186  bool needsTesting = false;
187  if ((theClipMode == BOUNDING_RECT) && (resLevel < theBoundingRects.size()))
188  {
189  if (!rect.intersects(theBoundingRects[resLevel]))
190  is_outside_aoi = true;
191  else
192  needsTesting = !rect.completely_within(theBoundingRects[resLevel]);
193  }
194  else if ((theClipMode == VALID_VERTICES) && (resLevel < theValidVertices.size()))
195  {
196  bool ulFlag = theValidVertices[resLevel].isPointWithin(rect.ul());
197  bool urFlag = theValidVertices[resLevel].isPointWithin(rect.ur());
198  bool lrFlag = theValidVertices[resLevel].isPointWithin(rect.lr());
199  bool llFlag = theValidVertices[resLevel].isPointWithin(rect.ll());
200  if ((!ulFlag) && (!urFlag) && (!lrFlag) && (!llFlag))
201  is_outside_aoi = true;
202  else
203  needsTesting = !(ulFlag && urFlag && lrFlag && llFlag);
204  }
205  if (is_outside_aoi)
206  {
207  // none of the tile is inside so just return with empty tile:
208  delete[] buf;
209  return;
210  }
211 
212  ossim_uint32 i = 0; // index into band buffers;
213  ossimIpt pixel_loc;
214  bool can_replace, found_candidate;
215 
216  // Begin loop over each pixel in the tile. The individual bands are handled inside this loop:
217  for (pixel_loc.y = ul.y; pixel_loc.y <= lr.y; ++pixel_loc.y)
218  {
219  for (pixel_loc.x = ul.x; pixel_loc.x <= lr.x; ++pixel_loc.x)
220  {
221  // First consider if we need to test the pixel for border clipping:
222  if (needsTesting)
223  {
224  bool is_inside = true; // Assume it will pass the border test
225  if (theClipMode == BOUNDING_RECT)
226  is_inside = theBoundingRects[resLevel].pointWithin(pixel_loc);
227  else if (theClipMode == VALID_VERTICES)
228  is_inside = theValidVertices[resLevel].isPointWithin(pixel_loc);
229 
230  if (!is_inside)
231  {
232  // Remap this pixel to the replacement value (all bands)
233  for (band = 0; band < bands; ++band)
234  buf[band][i] = replacement;
235 
236  // Proceed to next pixel location:
237  ++i;
238  continue;
239  }
240  }
241 
242  // If clamping specified, the target replacement function is disabled:
243  if (theClampingMode)
244  {
245  switch (theReplacementMode)
246  {
249  for (band = 0; band < bands; ++band)
250  {
251  if (!ossim::isnan(theClampValueLo) && (buf[band][i] < clampLo))
252  buf[band][i] = clampLo;
253  else if (!ossim::isnan(theClampValueHi) && (buf[band][i] > clampHi))
254  buf[band][i] = clampHi;
255  }
256  break;
257 
260  // First band loop to establish if pixel qualifies for replacement (at least one
261  // band must be valid):
262  can_replace = false;
263  found_candidate = false;
264  for (band = 0; (band < bands) && !(can_replace && found_candidate); ++band)
265  {
266  if ((!ossim::isnan(theClampValueLo) && (buf[band][i] < clampLo)) ||
267  (!ossim::isnan(theClampValueHi) && (buf[band][i] > clampHi)))
268  found_candidate = true;
269  else
270  can_replace = true;
271  }
272  if (can_replace && found_candidate)
273  {
274  // This pixel has at least one band with normal value, so need to rescan bands
275  // to find pixels that need replacing (are within the target range):
276  for (band = 0; band < bands; ++band)
277  {
278  if (!ossim::isnan(theClampValueLo) && (buf[band][i] < clampLo))
279  buf[band][i] = clampLo;
280  else if (!ossim::isnan(theClampValueHi) && buf[band][i] > clampHi)
281  buf[band][i] = clampHi;
282  }
283  }
284  break;
285 
287  // First band loop to establish if pixel qualifies for replacement (all
288  // bands must be in target range):
289  can_replace = true;
290  for (band = 0; (band < bands) && can_replace; ++band)
291  {
292  if ((ossim::isnan(theClampValueLo) || (buf[band][i] >= clampLo)) &&
293  (ossim::isnan(theClampValueHi) || (buf[band][i] <= clampHi)))
294  can_replace = false;
295  }
296  if (can_replace)
297  {
298  // Map all pixels to replacement value:
299  for (band = 0; band < bands; ++band)
300  {
301  if (!ossim::isnan(theClampValueLo) && (buf[band][i] < clampLo))
302  buf[band][i] = clampLo;
303  else if (!ossim::isnan(theClampValueHi) && buf[band][i] > clampHi)
304  buf[band][i] = clampHi;
305  }
306  }
307  break;
308  } // close switch
309 
310  // Proceed to next pixel location:
311  ++i;
312  continue;
313  }
314 
315  // If we got here (the continue statement was not reached) then
316  // the pixel value now needs to be checked for possible target replacement:
317  switch (theReplacementMode)
318  {
320  for (band = 0; band < bands; ++band)
321  {
322  if ((buf[band][i] >= targetLo) && (buf[band][i] <= targetHi))
323  buf[band][i] = theReplacementValue;
324  }
325  break;
326 
328 
329  // First band loop to establish if pixel qualifies for replacement (at least one
330  // band must be valid):
331  can_replace = false;
332  found_candidate = false;
333  for (band = 0; (band < bands) && !(can_replace && found_candidate); ++band)
334  {
335  // check for target range replacement qualification:
336  if ((buf[band][i] < targetLo) || (buf[band][i] > targetHi))
337  can_replace = true; // Has valid band
338  else
339  found_candidate = true; // found band within target range
340  }
341  if (can_replace && found_candidate)
342  {
343  // This pixel has at least one band with normal value, so need to rescan bands
344  // to find pixels that need replacing (are within the target range):
345  for (band = 0; band < bands; ++band)
346  {
347  if ((buf[band][i] >= targetLo) && (buf[band][i] <= targetHi))
348  buf[band][i] = theReplacementValue;
349  }
350  }
351  break;
352 
354 
355  // First band loop to establish if pixel qualifies for replacement (at least one
356  // band must be valid):
357  can_replace = false;
358  found_candidate = false;
359  for (band = 0; (band < bands) && !(can_replace && found_candidate); ++band)
360  {
361  // check for target range replacement qualification:
362  if ((buf[band][i] < targetLo) || (buf[band][i] > targetHi))
363  can_replace = true;
364  else
365  found_candidate = true;
366  }
367  if (can_replace && found_candidate)
368  {
369  // This pixel has at least one band with normal value and one with target, so
370  // map all bands to target:
371  for (band = 0; band < bands; ++band)
372  buf[band][i] = theReplacementValue;
373  }
374  break;
375 
377 
378  // First band loop to establish if pixel qualifies for replacement (all
379  // bands must be in target range):
380  can_replace = true;
381  for (band = 0; (band < bands) && can_replace; ++band)
382  {
383  // check for target range replacement qualification:
384  if ((buf[band][i] < targetLo) || (buf[band][i] > targetHi))
385  can_replace = false;
386  }
387  if (can_replace)
388  {
389  // Map all pixels to replacement value:
390  for (band = 0; band < bands; ++band)
391  buf[band][i] = theReplacementValue;
392  }
393  break;
394 
396 
397  // First band loop to establish if pixel qualifies for replacement (all
398  // bands must be in target range):
399  can_replace = false;
400  for (band = 0; (band < bands) && !can_replace; ++band)
401  {
402  // check for target range replacement qualification:
403  if ((buf[band][i] >= targetLo) && (buf[band][i] <= targetHi))
404  can_replace = true;
405  }
406  if (can_replace)
407  {
408  // Map all pixels to replacement value:
409  for (band = 0; band < bands; ++band)
410  buf[band][i] = theReplacementValue;
411  }
412  break;
413  } // close switch
414 
415  // Reached end of processing for one pixel location. Increment the band buffers index:
416  ++i;
417  } // end of loop over pixel_loc.x
418  } // end of loop over pixel_loc.y
419 
420  delete[] buf;
421  inputTile->validate();
422 }
423 
424 template <class T>
425 void ossimPixelFlipper::clipTile(T /* dummy */,
426  ossimImageData *inputTile,
427  ossim_uint32 resLevel)
428 {
429  if (theClipMode == NONE)
430  {
431  theClipTileBuffer = 0;
432  return;
433  }
434  if (!inputTile)
435  return;
436  if (!inputTile->getBuf() ||
437  (inputTile->getDataObjectStatus() == OSSIM_EMPTY))
438  {
439  return;
440  }
441  allocateClipTileBuffer(inputTile);
442 
443  if (theClipTileBuffer.valid())
444  {
445  ossimIrect tileRect = inputTile->getImageRectangle();
446  // force to all nulls
449 
450  switch (theClipMode)
451  {
452  case NONE:
453  {
454  break;
455  }
456  case BOUNDING_RECT:
457  {
458  if (resLevel < theBoundingRects.size())
459  {
460  if (tileRect.completely_within(theBoundingRects[resLevel]) ||
461  theBoundingRects[resLevel].hasNans())
462  {
463  return;
464  }
465  else
466  {
467  if (tileRect.intersects(theBoundingRects[resLevel]))
468  {
469  ossimIrect clipRect = tileRect.clipToRect(theBoundingRects[resLevel]);
470 
472 
473  theClipTileBuffer->loadTile(inputTile);
474  inputTile->makeBlank();
475  inputTile->loadTile(theClipTileBuffer.get());
476  inputTile->validate();
477  }
478  else
479  {
480  inputTile->makeBlank();
481  }
482  }
483  }
484  break;
485  }
486  case VALID_VERTICES:
487  {
488  if (resLevel < theValidVertices.size())
489  {
490  const ossimPolygon &p = theValidVertices[resLevel];
491  bool ulWithin = p.isPointWithin(tileRect.ul());
492  bool urWithin = p.isPointWithin(tileRect.ur());
493  bool lrWithin = p.isPointWithin(tileRect.lr());
494  bool llWithin = p.isPointWithin(tileRect.ll());
495 
496  if (ulWithin &&
497  urWithin &&
498  lrWithin &&
499  llWithin)
500  {
501  return;
502  }
503  else if (!(ulWithin || // if none are in
504  urWithin ||
505  lrWithin ||
506  llWithin))
507  {
508  inputTile->makeBlank();
509  return;
510  }
511  else
512  {
513  ossimIpt ul = tileRect.ul();
514  ossimIpt origin;
515  ossim_uint32 x = 0;
516  ossim_uint32 y = 0;
517  ossim_uint32 w = inputTile->getWidth();
518  ossim_uint32 h = inputTile->getHeight();
519  ossim_uint32 offset = 0;
520  origin.y = ul.y;
521  for (y = 0; y < h; ++y)
522  {
523  origin.x = ul.x;
524  for (x = 0; x < w; ++x)
525  {
526  if (!p.isPointWithin(origin))
527  {
528  inputTile->setNull(offset);
529  }
530  ++offset;
531  ++origin.x;
532  }
533  ++origin.y;
534  }
535  }
536  }
537  break;
538  }
539  }
540  }
541 }
542 
544 {
545  if (inputImage.valid())
546  {
547  bool needDupFlag = false;
548  if (theClipTileBuffer.valid())
549  {
550  if ((theClipTileBuffer->getScalarType() != inputImage->getScalarType()) ||
552  {
553  needDupFlag = true;
554  }
555  else
556  {
558  }
559  }
560  else
561  {
562  needDupFlag = true;
563  }
564  if (needDupFlag)
565  {
566  theClipTileBuffer = (ossimImageData *)inputImage->dup();
567  }
568  }
569 }
570 
572 {
573  std::lock_guard<std::recursive_mutex> scopeLock(theMutex);
575  theValidVertices.clear();
576  theBoundingRects.clear();
577 
579  ossim_uint32 idx = 0;
580 
581  if (rlevels)
582  {
583  if (theValidVertices.size() != rlevels)
584  {
585  theValidVertices.resize(rlevels);
586  }
587  if (theBoundingRects.size() != rlevels)
588  {
589  theBoundingRects.resize(rlevels);
590  }
591  for (idx = 0; idx < rlevels; ++idx)
592  {
593  std::vector<ossimIpt> validVertices;
594  getValidImageVertices(validVertices,
596  idx);
597  theValidVertices[idx] = ossimPolygon(validVertices);
598  theBoundingRects[idx] = getBoundingRect(idx);
599  }
600  }
601 }
602 
604 {
605  if (theInputConnection)
606  {
608  {
609  if (scalar == OSSIM_USHORT16 && theClampValueHi == 2047.0)
610  {
611  //---
612  // Special case:
613  // We have an unsigned 16 bit type but we want to call it
614  // USHORT11 ( (2^11- 1) = 2047 ).
615  //---
616  return OSSIM_USHORT11;
617  }
618  else if (scalar == OSSIM_USHORT16 && theClampValueHi == 4095.0)
619  {
620  //---
621  // Special case:
622  // We have an unsigned 16 bit type but we want to call it
623  // USHORT12 ( (2^12- 1) = 4095 ).
624  //---
625  return OSSIM_USHORT12;
626  }
627  else if (scalar == OSSIM_USHORT16 && theClampValueHi == 8191.0)
628  {
629  //---
630  // Special case:
631  // We have an unsigned 16 bit type but we want to call it
632  // USHORT13 ( (2^13- 1) = 8191 ).
633  //---
634  return OSSIM_USHORT13;
635  }
636  else if (scalar == OSSIM_USHORT16 && theClampValueHi == 16383.0)
637  {
638  //---
639  // Special case:
640  // We have an unsigned 16 bit type but we want to call it
641  // USHORT14 ( (2^14- 1) = 16383 ).
642  //---
643  return OSSIM_USHORT14;
644  }
645  else if (scalar == OSSIM_USHORT16 && theClampValueHi == 32767.0)
646  {
647  //---
648  // Special case:
649  // We have an unsigned 16 bit type but we want to call it
650  // USHORT15 ( (2^15- 1) = 32767 ).
651  //---
652  return OSSIM_USHORT15;
653  }
654  return scalar;
655  }
656  }
657  return OSSIM_SCALAR_UNKNOWN;
658 }
659 
661 {
664 
665  if ((theClampValueHi > MIN) && (theClampValueHi < MAX))
666  return theClampValueHi;
667 
668  return MAX;
669 }
670 
672 {
675 
676  if ((theClampValueLo > MIN) && (theClampValueLo < MAX))
677  return theClampValueLo;
678 
679  return MIN;
680 }
681 
683  const char *prefix)
684 {
685  const char *lookupReturn;
686 
687  lookupReturn = kwl.find(prefix, PF_TARGET_VALUE_KW);
688  if (lookupReturn)
689  {
690  setTargetValue(atof(lookupReturn));
691  }
692 
693  lookupReturn = kwl.find(prefix, PF_TARGET_RANGE_KW);
694  if (lookupReturn)
695  {
696  ossimString min_max_string(lookupReturn);
697  ossimString separator(" ");
698  ossim_float64 min_target = min_max_string.before(separator).toFloat64();
699  ossim_float64 max_target = min_max_string.after(separator).toFloat64();
700  setTargetRange(min_target, max_target);
701  }
702 
703  lookupReturn = kwl.find(prefix, PF_REPLACEMENT_VALUE_KW);
704  if (lookupReturn)
705  {
706  setReplacementValue(atof(lookupReturn));
707  }
708 
709  lookupReturn = kwl.find(prefix, PF_REPLACEMENT_MODE_KW);
710  if (lookupReturn)
711  {
712  ossimString modeString = lookupReturn;
713  setReplacementMode(modeString);
714  }
715 
716  lookupReturn = kwl.find(prefix, PF_CLAMP_VALUE_KW);
717  if (lookupReturn)
718  {
719  setClampValue(atof(lookupReturn), true);
720  }
721 
722  lookupReturn = kwl.find(prefix, PF_CLAMP_VALUE_LO_KW);
723  if (lookupReturn)
724  {
725  setClampValue(atof(lookupReturn), false);
726  }
727 
728  lookupReturn = kwl.find(prefix, PF_CLAMP_VALUE_HI_KW);
729  if (lookupReturn)
730  {
731  setClampValue(atof(lookupReturn), true);
732  }
733 
734  lookupReturn = kwl.find(prefix, PF_CLIP_MODE_KW);
735  if (lookupReturn)
736  {
737  ossimString modeString = lookupReturn;
738  setClipMode(modeString);
739  }
740 
741  bool status = ossimImageSourceFilter::loadState(kwl, prefix);
742 
743  if (traceDebug())
744  {
746  }
747 
748  return status;
749 }
750 
752  const char *prefix) const
753 {
754  // Call the base class saveState.
756 
758  {
761  kwl.add(prefix, PF_TARGET_RANGE_KW, s);
762  }
763  else
764  {
766  }
768  kwl.add(prefix, PF_REPLACEMENT_MODE_KW, getReplacementModeString().c_str());
769 
770  if (theClampingMode)
771  {
774  }
775  kwl.add(prefix, PF_CLIP_MODE_KW, getClipModeString().c_str());
776 
777  return true;
778 }
779 
781 {
782  //---
783  // Since this is the value to replace we will allow for any value as it
784  // won't affect the output null, min and max ranges. This will fix a
785  // tiled nitf with max of 2047(11bit) with edge tile fill values of 2048.
786  //---
787  std::lock_guard<std::recursive_mutex> scopeLock(theMutex);
788 
789  theTargetValueLo = target_value;
790  theTargetValueHi = target_value;
791 }
792 
794 {
795  //---
796  // Since this is the value to replace we will allow for any value as it
797  // won't affect the output null, min and max ranges. This will fix a
798  // tiled nitf with max of 2047(11bit) with edge tile fill values of 2048.
799  //---
800  std::lock_guard<std::recursive_mutex> scopeLock(theMutex);
801 
802  theTargetValueLo = target_min;
803  theTargetValueHi = target_max;
804 }
805 
807 {
808  std::lock_guard<std::recursive_mutex> scopeLock(theMutex);
809 
810  // Range check to ensure within null, min and max of output radiometry.
811  if (inRange(replacement_value))
812  {
813  theReplacementValue = replacement_value;
814  }
815 }
816 
817 void ossimPixelFlipper::setClampValue(ossim_float64 clamp_value, bool clamp_max_value)
818 {
819  std::lock_guard<std::recursive_mutex> scopeLock(theMutex);
820 
821  if (inRange(clamp_value))
822  {
823  // Stupid MS compiler complains if we do an |= on enum type. (OLK 1/11)
824  int temp_int = (int)theClampingMode;
825  if (clamp_max_value)
826  {
827  theClampValueHi = clamp_value;
828  temp_int |= (int)CLAMPING_HI;
829  }
830  else
831  {
832  theClampValueLo = clamp_value;
833  temp_int |= (int)CLAMPING_LO;
834  }
835  theClampingMode = (ClampingMode)temp_int;
836  }
837 }
838 
840 {
841  theClampingMode = DISABLED; // reset and let next calls set accordingly
842  setClampValue(clamp_value_lo, false);
843  setClampValue(clamp_value_hi, true);
844 }
845 
847 {
848  std::lock_guard<std::recursive_mutex> scopeLock(theMutex);
849  theReplacementMode = mode;
850 }
851 
853 {
854  std::lock_guard<std::recursive_mutex> scopeLock(theMutex);
855 
856  ossimString mode = modeString;
857  mode.upcase();
858  if (mode == "REPLACE_BAND_IF_TARGET")
859  {
861  }
862  else if (mode == "REPLACE_BAND_IF_PARTIAL_TARGET")
863  {
865  }
866  else if (mode == "REPLACE_ALL_BANDS_IF_PARTIAL_TARGET")
867  {
869  }
870  else if (mode == "REPLACE_ONLY_FULL_TARGETS")
871  {
873  }
874  else if (mode == "REPLACE_ALL_BANDS_IF_ANY_TARGET")
875  {
877  }
878  else
879  {
881  << "ossimPixelFlipper::setReplacementMode warning:\n"
882  << "Invalid mode: " << modeString
883  << endl;
884  return false;
885  }
886  return true;
887 }
888 
890 {
891  std::lock_guard<std::recursive_mutex> scopeLock(theMutex);
892  theClipMode = mode;
893 }
894 
896 {
897  ossimString mode = modeString;
898  mode.downcase();
899  if (mode == "none")
900  {
901  setClipMode(NONE);
902  }
903  else if (mode == "bounding_rect")
904  {
906  }
907  else if (mode == "valid_vertices")
908  {
910  }
911  else
912  {
914  << "ossimPixelFlipper::setClipMode warning:\n"
915  << "Invalid mode: " << modeString
916  << endl;
917  }
918 }
919 
920 //ossim_float64 ossimPixelFlipper::getTargetValue() const
921 //{
922 // return theTargetValueLo;
923 //}
924 
926 {
927  return theReplacementValue;
928 }
929 
931 {
932  return theReplacementMode;
933 }
934 
936 {
937  switch (theReplacementMode)
938  {
940  return ossimString("REPLACE_BAND_IF_TARGET");
942  return ossimString("REPLACE_BAND_IF_PARTIAL_TARGET");
944  return ossimString("REPLACE_ALL_BANDS_IF_PARTIAL_TARGET");
946  return ossimString("REPLACE_ONLY_FULL_TARGETS");
948  return ossimString("REPLACE_ALL_BANDS_IF_ANY_TARGET");
949  default:
950  break;
951  }
952 
953  return ossimString("UNKNOWN_MODE");
954 }
955 
957 {
958  if (theClipMode == BOUNDING_RECT)
959  return ossimString("bounding_rect");
960 
962  return ossimString("valid_vertices");
963 
964  return ossimString("none");
965 }
966 
968 {
969  return theClipMode;
970 }
971 
973 {
974  out << "ossimPixelFlipper::print:"
975  << "\ntarget value Lo: " << theTargetValueLo
976  << "\ntarget value Hi: " << theTargetValueHi
977  << "\nreplacement value: " << theReplacementValue
978  << "\nclamp value Lo: " << theClampValueLo
979  << "\nclamp value Hi: " << theClampValueHi
980  << "\nreplacement mode: " << getReplacementModeString().c_str()
981  << "\nclip_mode: " << getClipModeString().c_str()
982  << endl;
983  return out;
984 }
985 
987  const ossimString &name) const
988 {
989  // Lock for the length of this method.
990  std::lock_guard<std::recursive_mutex> scopeLock(theMutex);
991 
992  if (name == PF_TARGET_VALUE_KW)
993  {
994  ossimProperty *p =
995  new ossimNumericProperty(name,
997  p->setCacheRefreshBit();
998  return ossimRefPtr<ossimProperty>(p);
999  }
1000  if (name == PF_TARGET_RANGE_KW)
1001  {
1002  ossimProperty *p =
1003  new ossimNumericProperty(name,
1005  p->setCacheRefreshBit();
1006  return ossimRefPtr<ossimProperty>(p);
1007  }
1008  if (name == TARGET_UPPER_LIMIT_PROP_NAME)
1009  {
1010  ossimProperty *p =
1011  new ossimNumericProperty(name,
1013  p->setCacheRefreshBit();
1014  return ossimRefPtr<ossimProperty>(p);
1015  }
1016  else if (name == PF_REPLACEMENT_VALUE_KW)
1017  {
1018  ossimProperty *p =
1019  new ossimNumericProperty(name,
1021  p->setCacheRefreshBit();
1022  return ossimRefPtr<ossimProperty>(p);
1023  }
1024  else if (name == PF_CLAMP_VALUE_LO_KW)
1025  {
1026  ossimProperty *p =
1028  p->setCacheRefreshBit();
1029  return ossimRefPtr<ossimProperty>(p);
1030  }
1031  else if (name == PF_CLAMP_VALUE_HI_KW)
1032  {
1033  ossimProperty *p =
1035  p->setCacheRefreshBit();
1036  return ossimRefPtr<ossimProperty>(p);
1037  }
1038  else if (name == PF_REPLACEMENT_MODE_KW)
1039  {
1040  vector<ossimString> constraintList(5);
1041  constraintList[0] = "REPLACE_BAND_IF_TARGET";
1042  constraintList[1] = "REPLACE_BAND_IF_PARTIAL_TARGET";
1043  constraintList[2] = "REPLACE_ALL_BANDS_IF_PARTIAL_TARGET";
1044  constraintList[3] = "REPLACE_ONLY_FULL_TARGETS";
1045  constraintList[4] = "REPLACE_ALL_BANDS_IF_ANY_TARGET";
1046 
1047  ossimStringProperty *p =
1048  new ossimStringProperty(name,
1050  false,
1051  constraintList);
1052  p->setCacheRefreshBit();
1053  return ossimRefPtr<ossimProperty>(p);
1054  }
1055  else if (name == PF_CLIP_MODE_KW)
1056  {
1057  vector<ossimString> constraintList(3);
1058  constraintList[0] = "none";
1059  constraintList[1] = "bounding_rect";
1060  constraintList[2] = "valid_vertices";
1061 
1062  ossimStringProperty *p =
1063  new ossimStringProperty(name,
1065  false,
1066  constraintList);
1067  p->setCacheRefreshBit();
1068  return ossimRefPtr<ossimProperty>(p);
1069  }
1071 
1072  if (result.valid())
1073  {
1074  if (result->getName() == ossimKeywordNames::ENABLED_KW)
1075  {
1076  result->clearChangeType();
1077 
1078  // we will at least say its a radiometric change
1079  //
1080  result->setCacheRefreshBit();
1081  }
1082  }
1083 
1084  return result;
1085 }
1086 
1088 {
1089  if (!property)
1090  return;
1091 
1092  ossimString os = property->valueToString();
1093 
1094  ossimString name = property->getName();
1095  if (name == PF_TARGET_VALUE_KW)
1096  {
1097  setTargetValue(os.toDouble());
1098  }
1099  if (name == TARGET_LOWER_LIMIT_PROP_NAME)
1100  {
1102  }
1103  if (name == TARGET_UPPER_LIMIT_PROP_NAME)
1104  {
1106  }
1107  else if (name == PF_REPLACEMENT_VALUE_KW)
1108  {
1110  }
1111  else if (name == PF_REPLACEMENT_MODE_KW)
1112  {
1113  setReplacementMode(os);
1114  }
1115  else if (name == PF_CLAMP_VALUE_LO_KW)
1116  {
1117  setClampValue(os.toDouble(), false);
1118  }
1119  else if (name == PF_CLAMP_VALUE_HI_KW)
1120  {
1121  setClampValue(os.toDouble(), true);
1122  }
1123  else if (name == PF_CLIP_MODE_KW)
1124  {
1125  setClipMode(os);
1126  }
1127  else
1128  {
1130  }
1131 }
1132 
1134  std::vector<ossimString> &propertyNames) const
1135 {
1136  propertyNames.push_back(PF_TARGET_VALUE_KW);
1137  propertyNames.push_back(TARGET_LOWER_LIMIT_PROP_NAME);
1138  propertyNames.push_back(TARGET_UPPER_LIMIT_PROP_NAME);
1139  propertyNames.push_back(PF_REPLACEMENT_VALUE_KW);
1140  propertyNames.push_back(PF_REPLACEMENT_MODE_KW);
1141  propertyNames.push_back(PF_CLAMP_VALUE_LO_KW);
1142  propertyNames.push_back(PF_CLAMP_VALUE_HI_KW);
1143  propertyNames.push_back(PF_CLIP_MODE_KW);
1144 
1146 }
1147 
1149 {
1150  return ossimString("Pixel flipper");
1151 }
1152 
1154 {
1155  if (!theInputConnection)
1156  {
1157  //---
1158  // Not initialized yet... We're going to return true so that things
1159  // like loadState work with the assumption that the caller know's
1160  // the correct range. This check is really intended for an uncheck
1161  // range on the gui side.
1162  //---
1163  return true;
1164  }
1165 
1169 
1170  if ((value == NULL_PIX) || ((value >= MIN_PIX) && (value <= MAX_PIX)))
1171  {
1172  return true;
1173  }
1174 
1176  << "\nossimPixelFlipper::inRange WARNING:"
1177  << "\nvalue \"" << value
1178  << "\" is out of range!"
1179  << "\nInput source null = " << NULL_PIX
1180  << "\nInput source min = " << MIN_PIX
1181  << "\nInput source max = " << MAX_PIX
1182  << endl;
1183 
1184  return false;
1185 }
16 bit unsigned integer (15 bits used)
virtual void setProperty(ossimRefPtr< ossimProperty > property)
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of an object to a keyword list.
virtual ossim_uint32 getWidth() const
ossim_uint32 x
virtual bool isSourceEnabled() const
Definition: ossimSource.cpp:79
virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0) const
This will return the bounding rect of the source.
virtual void setDescription(const ossimString &description)
ossimString before(const ossimString &str, std::string::size_type pos=0) const
METHOD: before(str, pos) Returns string beginning at pos and ending one before the token str If strin...
ossim_float64 theReplacementValue
When target values are defined, this is the value the pixel will assume if the pixel falls within the...
virtual void setProperty(ossimRefPtr< ossimProperty > property)
virtual ossimScalarType getOutputScalarType() const
This will be used to query the output pixel type of the tile source.
static ossimString upcase(const ossimString &aString)
Definition: ossimString.cpp:34
virtual ossim_uint32 getNumberOfBands() const
void setClipMode(const ossimString &modeString)
Clipping here refers to bounding rect or valid polygon (spacial) clipping, where all pixels outside t...
64 bit floating point
ReplacementMode
Target Replacement Mode:
virtual void setImageRectangle(const ossimIrect &rect)
16 bit unsigned integer
virtual ~ossimPixelFlipper()
destructor
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
Represents serializable keyword/value map.
ossimPixelFlipper(ossimObject *owner=NULL)
default constructor
ClipMode theClipMode
Border Clip mode.
ossim_uint32 y
virtual void getPropertyNames(std::vector< ossimString > &propertyNames) const
bool valid() const
Definition: ossimRefPtr.h:75
const char * find(const char *key) const
#define MAX(x, y)
ReplacementMode theReplacementMode
See documentation for ReplacementMode enum above.
float ossim_float32
std::recursive_mutex theMutex
For lock and unlock.
double nan()
Method to return ieee floating point double precision NAN.
Definition: ossimCommon.h:135
This code was derived from https://gist.github.com/mshockwave.
Definition: Barrier.h:8
ossim_float64 theTargetValueLo
The value range to replace.
static const char PF_REPLACEMENT_MODE_KW[]
static ossimString toString(bool aValue)
Numeric to string methods.
static const char PF_CLAMP_VALUE_KW[]
const ossimIpt & ul() const
Definition: ossimIrect.h:274
virtual ossimDataObjectStatus getDataObjectStatus() const
virtual ossim_uint32 getHeight() const
16 bit unsigned integer (14 bits used)
16 bit unsigned integer (13 bits used)
virtual ossim_uint32 getNumberOfDecimationLevels() const
Will return the number of resolution levels.
static const char PF_TARGET_RANGE_KW[]
32 bit floating point
bool intersects(const ossimIrect &rect) const
Definition: ossimIrect.cpp:183
unsigned short ossim_uint16
const ossimIpt & ll() const
Definition: ossimIrect.h:277
32 bit unsigned integer
ossimPixelFlipper::ReplacementMode getReplacementMode() const
void setClampValue(ossim_float64 clamp_value, bool is_high_clamp_value=true)
virtual void initialize()
Initializes the state of the object from theInputConnection.
static const char PF_CLAMP_VALUE_LO_KW[]
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
void setReplacementMode(ossimPixelFlipper::ReplacementMode mode)
virtual ossimObject * dup() const
ossim_float64 getReplacementValue() const
bool completely_within(const ossimIrect &rect) const
Definition: ossimIrect.cpp:425
ClampingMode
When either a lo and/or hi clamp value is set, the clamping mode will be enabled accordingly and over...
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)
virtual void loadTile(const void *src, const ossimIrect &src_rect, ossimInterleaveType il_type)
ossim_float64 theTargetValueHi
void allocateClipTileBuffer(ossimRefPtr< ossimImageData > inputImage)
void clearChangeType()
void flipPixels(T dummy, ossimImageData *inpuTile, ossim_uint32 resLevel)
This object can be used outside of an image chain for offline processing of existing tile...
virtual ossimDataObjectStatus validate() const
signed short ossim_sint16
virtual void getPropertyNames(std::vector< ossimString > &propertyNames) const
static const char PF_CLAMP_VALUE_HI_KW[]
32 bit signed integer
virtual void getValidImageVertices(std::vector< ossimIpt > &validVertices, ossimVertexOrdering ordering=OSSIM_CLOCKWISE_ORDER, ossim_uint32 resLevel=0) const
ordering specifies how the vertices should be arranged.
ossimImageSource * theInputConnection
unsigned int ossim_uint32
32 bit normalized floating point
double toDouble() const
ossim_float64 toFloat64() const
signed int ossim_sint32
ClipMode getClipMode() const
virtual ossimIrect getImageRectangle() const
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 ossim_float64 getMinPixelValue(ossim_uint32 band=0) const
Returns the min pixel of the band.
ossimString getClipModeString() const
void setClampValues(ossim_float64 clamp_value_lo, ossim_float64 clamp_value_hi)
const ossimIpt & lr() const
Definition: ossimIrect.h:276
virtual void enableSource()
Definition: ossimSource.cpp:84
static ossimString downcase(const ossimString &aString)
Definition: ossimString.cpp:48
virtual ossimString getShortName() const
virtual ossimRefPtr< ossimImageData > getTile(const ossimIrect &tile_rect, ossim_uint32 resLevel=0)
ClampingMode theClampingMode
ossim_float64 theClampValueHi
ossimIrect clipToRect(const ossimIrect &rect) const
Definition: ossimIrect.cpp:501
static const char * ENABLED_KW
void setNull(ossim_uint32 offset)
const ossimIpt & ur() const
Definition: ossimIrect.h:275
ossimScalarType
return status
virtual ossimScalarType getScalarType() const
virtual void makeBlank()
Initializes data to null pixel values.
64 bit normalized floating point
16 bit unsigned integer (11 bits used)
#define MIN(x, y)
void setTargetRange(ossim_float64 target_min, ossim_float64 target_max)
Instead of a single value for a target, this method allows for specifying a range of values to flip t...
void setReplacementValue(ossim_float64 replacement_value)
ossimString getReplacementModeString() const
virtual ossimScalarType getOutputScalarType() const
This will be used to query the output pixel type of the tile source.
void setTargetValue(ossim_float64 target_value)
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.
ossim_int32 y
Definition: ossimIpt.h:142
bool isPointWithin(const ossimDpt &point) const
Class to scan pixels and flip target dn value to a replacement dn value.
virtual const void * getBuf() const
virtual std::ostream & print(std::ostream &out) const
Outputs theErrorStatus as an ossimErrorCode and an ossimString.
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
void clipTile(T dummy, ossimImageData *inpuTile, ossim_uint32 resLevel)
virtual void setDataObjectStatus(ossimDataObjectStatus status) const
Full list found in ossimConstants.h.
ossim_float64 theClampValueLo
The range of desired pixel values.
static const char PF_REPLACEMENT_VALUE_KW[]
ossim_int32 x
Definition: ossimIpt.h:141
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
ossimRefPtr< ossimImageData > theClipTileBuffer
#define RTTI_DEF1(cls, name, b1)
Definition: ossimRtti.h:485
static const char PF_CLIP_MODE_KW[]
ossimString after(const ossimString &str, std::string::size_type pos=0) const
METHOD: after(str, pos) Returns string immediately after the token str.
16 bit unsigned iteger
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 ossim_float64 getMaxPixelValue(ossim_uint32 band=0) const
Returns the max pixel of the band.
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
std::vector< ossimIrect > theBoundingRects
bool inRange(ossim_float64 value) const
Verifies pixel is in range.
std::basic_ostream< char > ostream
Base class for char output streams.
Definition: ossimIosFwd.h:23
void setCacheRefreshBit()
8 bit unsigned iteger
std::vector< ossimPolygon > theValidVertices
static const char PF_TARGET_VALUE_KW[]
const ossimString & getName() const
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