OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimTableRemapper.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 // Table remapper class definition.
10 //
11 // Takes input tile, remaps it through a table, then output tile in the desired
12 // scalar type.
13 //
14 // Two modes one that works on native remap tables, that being of the same
15 // scalar type (like ossim_uint8) of the input connection, and another that
16 // uses a normalized remap table (more scalar independent).
17 //
18 //*************************************************************************
19 // $Id: ossimTableRemapper.cpp 22745 2014-04-22 16:57:22Z dburken $
20 
22 #include <ossim/base/ossimTrace.h>
26 
28 
29 static ossimTrace traceDebug("ossimTableRemapper:debug");
30 
31 static const char* TABLE_TYPE[] = { "UNKNOWN", "NATIVE", "NORMALIZED" };
32 
34  :
35  ossimImageSourceFilter(), // base class
36  theTile(0),
37  theTmpTile(0),
38  theNormBuf(0),
39  theTableBinCount(0),
40  theTableBandCount(0),
41  theTableType(ossimTableRemapper::UKNOWN),
42  theInputScalarType(OSSIM_SCALAR_UNKNOWN),
43  theOutputScalarType(OSSIM_SCALAR_UNKNOWN)
44 {
45  //***
46  // Set the base class "theEnableFlag" to off since no adjustments have been
47  // made yet.
48  //***
49  //disableSource();
50 }
51 
53 {
54  destroy();
55 }
56 
58 {
59  if (theNormBuf)
60  {
61  delete [] theNormBuf;
62  theNormBuf = 0;
63  }
64  theTmpTile = 0;
65  theTile = 0;
66 }
67 
69 {
70  //---
71  // Call the base class initialize.
72  // Note: This will reset "theInputConnection" if it changed...
73  //---
75  destroy();
77  {
79 
80  // Since we override "getOutputScalarType" make sure something's set.
82  {
84  }
85 
86  if (theTile.valid())
87  {
88  //if ( theTile->getNumberOfBands() !=
89  // theInputConnection->getNumberOfOutputBands() )
90  // {
91  // Wipe everything slick. The next getTile will call allocate.
92  // destroy();
93  // }
94  }
95  }
96 
97  // Nothing else to do for this...
98 }
99 
101 {
102  //---
103  // It's either first getTile or we've had either a resize, so allocate
104  // needed stuff...
105  //---
106  destroy();
107 
108  if (theInputConnection)
109  {
110  ossim_uint32 width = rect.width();
111  ossim_uint32 height = rect.height();
112 
114  theTile->setImageRectangle(rect);
115  // theTile =
116  // ossimImageDataFactory::instance()->create(this,
117  // getOutputScalarType(),
118  // getNumberOfOutputBands(),
119  // width,x
120  // height);
121  theTile->initialize();
122 
123 
126  {
127  //---
128  // We need a temp tile so we can do two remaps
129  // inputTile->remapTable->tmpTile then
130  // tmpTile->normalize->theTile(unnormalize to new scalar)...
131  //---
132  theTmpTile
136  width,
137  height);
140 
141  }
142 
145  {
147  }
148  }
149 }
150 
152  const ossimIrect& tile_rect, ossim_uint32 resLevel)
153 {
154  ossimRefPtr<ossimImageData> result = 0;
155 
157  {
158  // Fetch tile from pointer from the input source.
159  result = theInputConnection->getTile(tile_rect, resLevel);
160  if (theEnableFlag&&result.valid())
161  {
162  // Get its status of the input tile.
163  ossimDataObjectStatus tile_status = result->getDataObjectStatus();
164 
165  // Check for remap bypass:
166  if ( (tile_status != OSSIM_NULL) &&
167  (tile_status != OSSIM_EMPTY) && theTable.size() )
168  {
169 
170  // OK we have an input tile... and it's not null or empty.
171  if(!theTile)
172  {
173  allocate(tile_rect);
174  }
175  if (theTile.valid())
176  {
177  theTile->setImageRectangle(tile_rect);
178  if(theTmpTile.valid()) // not mandatory for all modes.
179  {
180  theTmpTile->setImageRectangle(tile_rect);
181  }
182  // Think things are good. Do the real work...
184  {
185  // Most efficient case...
186  remapFromNativeTable(result);
187  }
188  else
189  {
190  remapFromNormalizedTable(result);
191  }
192 
193  theTile->validate();
194  result = theTile;
195  }
196  }
197  }
198  }
199  return result;
200 }
201 
203  ossimRefPtr<ossimImageData>& inputTile)
204 {
205  switch (theOutputScalarType)
206  {
207  case OSSIM_UINT8:
208  {
209  remapFromNativeTable(ossim_uint8(0), inputTile);
210  break;
211  }
212 
213  case OSSIM_USHORT11:
214  case OSSIM_USHORT12:
215  case OSSIM_USHORT13:
216  case OSSIM_USHORT14:
217  case OSSIM_USHORT15:
218  case OSSIM_USHORT16:
219  {
220  remapFromNativeTable(ossim_uint16(0), inputTile);
221  break;
222  }
223 
224  case OSSIM_SSHORT16:
225  {
226  remapFromNativeTable(ossim_sint16(0), inputTile);
227  break;
228  }
229 
231  case OSSIM_FLOAT:
232  {
233  remapFromNativeTable(ossim_float32(0), inputTile);
234  break;
235  }
236 
238  case OSSIM_DOUBLE:
239  {
240  remapFromNativeTable(ossim_float64(0), inputTile);
241  break;
242  }
243 
245  default:
246  {
247  if(traceDebug())
248  {
249  // Shouldn't hit this.
251  << "ossimTableRemapper::remapFromNativeTable"
252  << "\nOutput scalar type is OSSIM_SCALAR_UNKNOWN!\n";
253  }
254  break;
255  }
256 
257  } // End of "switch (theTableType)"
258 }
259 
261  T /* dummy */,
262  ossimRefPtr<ossimImageData>& inputTile)
263 {
264 
265  const ossim_uint32 BANDS = theTile->getNumberOfBands();
266  const ossim_uint32 PPB = theTile->getSizePerBand(); // pixels per band
267  //---
268  // NOTE:
269  // If (theTableBandCount == one) that means we only have one band; or,
270  // the user wanted to remap all bands using the same table...
271  //---
272  const ossim_uint32 BAND_OFFSET =
274 
275 
276 
277  const T* rt = reinterpret_cast<T*>(&theTable.front()); // remap table (rt)
280  {
281  id = theTile;
282  }
283  else
284  {
285  id = theTmpTile;
286  }
287  if(theTable.size() >= (BANDS*BAND_OFFSET))
288  {
289  for (ossim_uint32 band = 0; band < BANDS; ++band)
290  {
291  const T NULL_PIX = static_cast<T>(id->getNullPix(band));
292  //const T MIN_PIX = static_cast<T>(id->getMinPix(band));
293 
294  const T* s = static_cast<T*>(inputTile->getBuf(band)); // source (s)
295  T* d = static_cast<T*>(id->getBuf(band)); // destination (d)
296 
297  if(s&&d)
298  {
299  for (ossim_uint32 pixel = 0; pixel < PPB; ++pixel)
300  {
301  //---
302  // Get the source pixel and use it as an index to the table.
303  // Note Null is always the "0" index, min always the "1".
304  //---
305  T p = s[pixel];
306  if (p == NULL_PIX) // Null is not always zero (dted).
307  {
308  d[pixel] = NULL_PIX;
309  // p = 0;
310  }
311  else
312  {
313  // else
314  // {
315  // p = (p+1-MIN_PIX); // If min == 1 we want that to map to index 1.
316  // }
317 
318  ossim_uint32 table_index = static_cast<ossim_uint32>(p);
319 
320  //---
321  // If within range use to index the remap table; else, null.
322  // Note:
323  // There is no min, max range checking on value retrieved from table.
324  // Range checking should be performed when the table is built.
325  //---
326  if(table_index < theTableBinCount)
327  {
328  d[pixel] = rt[table_index];
329  }
330  // else if(table_index < 0)
331  // {
332  // if(theTableBinCount > 1)
333  // {
334  // d[pixel] = rt[1];
335  // }
336  // else
337  // {
338  // d[pixel] = table_index;
339  // }
340  // }
341  else
342  {
343  if(theTableBinCount>0)
344  {
345  d[pixel] = rt[theTableBinCount-1];
346  }
347  else
348  {
349  d[pixel] = p;
350  }
351  }
352  }
353  }
354 
355  }
356 
357  rt += BAND_OFFSET; // Go to next band in the table.
358  }
359 
360  }
361 
363  {
364  // Normalize and copy the temp tile to a buffer.
366 
367  // Un-normalize and copy the buffer to the destination tile.
369  }
370 }
371 
373  ossimRefPtr<ossimImageData>& inputTile)
374 {
375  if (!theNormBuf) // First time...
376  {
378  }
379 
380  // Normalize and copy the source tile to a buffer.
382 
383  const ossim_uint32 BANDS = theTile->getNumberOfBands();
384  const ossim_uint32 PPB = theTile->getSizePerBand(); // pixels per band
385 
386  //---
387  // NOTE:
388  // If (theTableBandCount == one) that means we only have one band; or,
389  // the user wanted to remap all bands using the same table...
390  //---
391  const ossim_uint32 BAND_OFFSET = (theTableBandCount == 1) ? 0 : PPB;
392 
393  // remap table (rt)
394  ossim_float64* rt = reinterpret_cast<ossim_float64*>(&theTable.front());
395 
396  ossim_float64* buf = theNormBuf;
397  ossim_float64 p = 0.0;
398  for (ossim_uint32 band = 0; band < BANDS; ++band)
399  {
400  for (ossim_uint32 pixel = 0; pixel < PPB; ++pixel)
401  {
402  // Get the source pixel...
403  ossim_uint32 idx
404  = static_cast<ossim_uint32>(buf[pixel]*theTableBinCount+0.5);
405 
406  if((idx < theTableBinCount))
407  {
408  // If within range use to index the remap table; else, null.
409  p = (idx < theTableBinCount) ? rt[idx] : 0.0;
410  }
411 // else if(idx < 0)
412 // {
413 // p = 0.0;
414 // }
415  else
416  {
417  p = 1.0;
418  }
419  // Range check (in case table bad) and assign to destination pixel.
420  buf[pixel] = (p >= 0.0) ? ( (p <=1.0) ? p : 1) : 0.0;
421  }
422 
423  // (GP)this is not for th table so this offset appears wrong
424  // commenting this out and replacing with t bin count
425  // Go to next band.
426  //rt += BAND_OFFSET;
427 
428 
429  rt += theTableBinCount;
430  buf += PPB;
431  }
432 
433  // Un-normalize and copy the buffer to the destination tile.
435 }
436 
438 {
440  {
441  return theOutputScalarType;
442  }
443 
445 }
446 
448  const char* prefix)
449 {
450  // Look for scalar type keyword.
452  getEntryNumber(kwl, prefix, true);
453 
454  // Lookup table returns -1 if not found so check return...
455  if ( (st != -1) && (st != OSSIM_SCALAR_UNKNOWN) )
456  {
457  theOutputScalarType = static_cast<ossimScalarType>(st);
458  }
459 
460  return ossimImageSourceFilter::loadState(kwl, prefix);
461 }
462 
464  const char* prefix) const
465 {
466  // Save the output scalar type.
467  kwl.add(prefix,
470  getEntryString(theOutputScalarType).c_str(),
471  true);
472 
473  return ossimImageSourceFilter::saveState(kwl, prefix);
474 }
475 
477 {
479 
480  os << "\nossimTableRemapper::print:"
481  << "\ntheTableBinCount: " << theTableBinCount
482  << "\ntheTableBandCount: " << theTableBandCount
483  << "\ntheTableType: " << TABLE_TYPE[theTableType]
484  << "\ntheInputScalarType: " << (*sl)[theInputScalarType]
485  << "\ntheOutputScalarType: " << (*sl)[theOutputScalarType]
486  << endl;
487 
488  if (theTile.valid())
489  {
490  os << "theTile:\n" << *theTile << endl;
491  }
492  if (theTmpTile.valid())
493  {
494  os << "theTmpTile:\n" << *theTmpTile << endl;
495  }
496 
497  switch (theOutputScalarType)
498  {
499  case OSSIM_UCHAR:
500  {
501  dumpTable(ossim_uint8(0), os);
502  break;
503  }
504 
505  case OSSIM_USHORT11:
506  case OSSIM_USHORT12:
507  case OSSIM_USHORT13:
508  case OSSIM_USHORT14:
509  case OSSIM_USHORT15:
510  case OSSIM_USHORT16:
511  {
512  dumpTable(ossim_uint16(0), os);
513  break;
514  }
515 
516  case OSSIM_SSHORT16:
517  {
518  dumpTable(ossim_sint16(0), os);
519  break;
520  }
521 
523  case OSSIM_FLOAT:
524  {
525  dumpTable(ossim_float32(0), os);
526  break;
527  }
528 
530  case OSSIM_DOUBLE:
531  {
532  dumpTable(ossim_float64(0), os);
533  break;
534  }
535 
537  default:
538  {
539  if(traceDebug())
540  {
541  // Shouldn't hit this.
543  << "ossimTableRemapper::print OSSIM_SCALAR_UNKNOWN!\n";
544  }
545  break;
546  }
547 
548  } // End of "switch (theTableType)"
549 
550  return os;
551 }
552 
553 template <class T> void ossimTableRemapper::dumpTable(T /*dummy*/,
554  ostream& os) const
555 {
556  if (theTable.empty() || !theTableBinCount || !theTableBandCount)
557  {
558  return;
559  }
560 
561  const T* table = reinterpret_cast<const T*>(&theTable.front());
562 
563  ossim_uint32 table_index = 0;
564  for (ossim_uint32 band = 0; band < theTableBandCount; ++band)
565  {
566  for (ossim_uint32 index = 0; index < theTableBinCount; ++index)
567  {
568  os << "tabel[" << band << "][" << index << "]: "
569  << static_cast<int>(table[table_index]) << endl;
570  ++table_index;
571  }
572  }
573 }
574 
575 
577 {
578  return tr.print(os);
579 }
580 
581 // Private to disallow use...
583 : theNormBuf(0),
584  theTableBinCount(0),
585  theTableBandCount(0),
586  theTableType(UKNOWN),
587  theInputScalarType(OSSIM_SCALAR_UNKNOWN),
588  theOutputScalarType(OSSIM_SCALAR_UNKNOWN)
589 {
590 }
591 
592 // Private to disallow use...
594 {
595  return *this;
596 }
16 bit unsigned integer (15 bits used)
ossimTableRemapper & operator=(const ossimTableRemapper &tr)
virtual ostream & print(ostream &os) const
Outputs theErrorStatus as an ossimErrorCode and an ossimString.
RemapTableType theTableType
virtual ossim_uint32 getNumberOfBands() const
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of an object to a keyword list.
virtual void setImageRectangle(const ossimIrect &rect)
virtual ossimRefPtr< ossimImageData > getTile(const ossimIrect &tile_rect, ossim_uint32 resLevel=0)
Represents serializable keyword/value map.
bool theEnableFlag
Definition: ossimSource.h:62
virtual ossim_uint32 getNumberOfOutputBands() const
Returns the number of bands in a tile returned from this TileSource.
bool valid() const
Definition: ossimRefPtr.h:75
float ossim_float32
ossimRefPtr< ossimImageData > theTile
ossim_float64 * theNormBuf
virtual ossimScalarType getOutputScalarType() const
This will be used to query the output pixel type of the tile source.
void remapFromNativeTable(ossimRefPtr< ossimImageData > &inputTile)
ossim_uint32 height() const
Definition: ossimIrect.h:487
std::vector< ossim_uint8 > theTable
virtual ossimDataObjectStatus getDataObjectStatus() const
16 bit unsigned integer (14 bits used)
16 bit unsigned integer (13 bits used)
ossimScalarType theInputScalarType
unsigned short ossim_uint16
virtual void initialize()
Initialize the data buffer.
virtual void initialize()
double ossim_float64
void add(const char *prefix, const ossimKeywordlist &kwl, bool overwrite=true)
ossimTableRemapper()
default constructor
static ossimScalarTypeLut * instance()
Returns the static instance of an ossimScalarTypeLut object.
static ossimImageDataFactory * instance()
virtual ossimDataObjectStatus validate() const
signed short ossim_sint16
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
void allocate(const ossimIrect &rect)
virtual void copyTileToNormalizedBuffer(ossim_float64 *buf) const
Copies entire tile to buf passed in.
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 void copyNormalizedBufferToTile(ossim_float64 *buf)
Copies buf passed in to tile.
void dumpTable(T dummy, ostream &os) const
virtual ossimRefPtr< ossimImageData > create(ossimSource *owner, ossimScalarType scalar, ossim_uint32 bands=1) const
ossim_uint32 width() const
Definition: ossimIrect.h:500
ossimScalarType
virtual const ossim_float64 * getMinPix() const
64 bit normalized floating point
16 bit unsigned integer (11 bits used)
virtual ossimScalarType getOutputScalarType() const
This will be used to query the output pixel type of the tile source.
ossim_uint32 theTableBandCount
ossimRefPtr< ossimImageData > theTmpTile
Used to convert from scalar type enumeration to strings and vice versa.
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 getSize() const
Returns the total number of pixels in a tile for all bands.
ossimScalarType theOutputScalarType
virtual const void * getBuf() const
ossim_uint32 theTableBinCount
static const char * SCALAR_TYPE_KW
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
void remapFromNormalizedTable(ossimRefPtr< ossimImageData > &inputTile)
ostream & operator<<(ostream &os, const ossimTableRemapper &tr)
8 bit unsigned integer
#define RTTI_DEF1(cls, name, b1)
Definition: ossimRtti.h:485
ossimDataObjectStatus
Definitions for data object status.
virtual ~ossimTableRemapper()
virtual destructor
32 bit floating point
virtual void setMinPix(ossim_float64 min_pix)
16 bit unsigned iteger
64 bit floating point
16 bit signed integer
unsigned char ossim_uint8
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
std::basic_ostream< char > ostream
Base class for char output streams.
Definition: ossimIosFwd.h:23
8 bit unsigned iteger
int ossim_int32
virtual ossimRefPtr< ossimImageData > getTile(const ossimIpt &origin, ossim_uint32 resLevel=0)
16 bit unsigned integer (12 bits used)