OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimBlendMosaic.cpp
Go to the documentation of this file.
1 //*******************************************************************
2 //
3 // License: See top level LICENSE.txt file.
4 //
5 // Author: Garrett Potts
6 //
7 //*************************************************************************
8 // $Id: ossimBlendMosaic.cpp 20696 2012-03-19 12:36:40Z dburken $
9 
14 
15 RTTI_DEF1(ossimBlendMosaic, "ossimBlendMosaic", ossimImageMosaic)
16 
18  : ossimImageMosaic(),
19  theNormResult(NULL)
20 {
21 }
22 
24  : ossimImageMosaic(inputSources),
25  theNormResult(NULL)
26 {
27  initialize();
28 }
29 
31 {
32 }
33 
35 {
37 
38  allocate();
39 
40  // only allocate this space if we have to
41  if(hasDifferentInputs())
42  {
43  theNormResult = new ossimImageData(this,
47  }
48 
49  if(theWeights.size() < theInputObjectList.size())
50  {
51  for(ossim_uint32 index =(ossim_uint32)theWeights.size();
52  index < theInputObjectList.size();
53  ++index)
54  {
55  theWeights.push_back(1.0);
56  }
57  }
58 }
59 
61  const ossimIrect& tileRect,
62  ossim_uint32 resLevel)
63 {
64  // ossimIpt origin = tileRect.ul();
65  if(!isSourceEnabled())
66  {
67  return ossimImageMosaic::getTile(tileRect, resLevel);
68  }
69 
71  if(!theTile.get())
72  {
73  // try to initialize
74  initialize();
75 
76  // if we still don't have a buffer
77  // then we will leave
78  if(!theTile.get())
79  {
80  return theTile;
81  }
82  }
83 
84  if(size == 0)
85  {
87  }
88  if(size == 1)
89  {
90  return ossimImageMosaic::getTile(tileRect, resLevel);
91  }
92 
93  theTile->setImageRectangle(tileRect);
94  theTile->makeBlank();
95  if(theNormResult.valid())
96  {
99  }
100 
101  switch(theTile->getScalarType())
102  {
103  case OSSIM_UINT8:
104  {
105  if(!hasDifferentInputs())
106  {
107  return combine(static_cast<ossim_uint8>(0), tileRect, resLevel);
108  }
109  else
110  {
111  return combineNorm(static_cast<ossim_uint8>(0), tileRect,
112  resLevel);
113  }
114  }
115  case OSSIM_SINT8:
116  {
117  if(!hasDifferentInputs())
118  {
119  return combine(static_cast<ossim_sint8>(0), tileRect, resLevel);
120  }
121  else
122  {
123  return combineNorm(static_cast<ossim_sint8>(0), tileRect,
124  resLevel);
125  }
126  }
127  case OSSIM_FLOAT32:
129  {
130  if(!hasDifferentInputs())
131  {
132  return combine(static_cast<float>(0), tileRect, resLevel);
133  }
134  else
135  {
136  return combineNorm(static_cast<float>(0), tileRect, resLevel);
137  }
138  }
139  case OSSIM_UINT16:
140  case OSSIM_USHORT11:
141  case OSSIM_USHORT12:
142  case OSSIM_USHORT13:
143  case OSSIM_USHORT14:
144  case OSSIM_USHORT15:
145  {
146  if(!hasDifferentInputs())
147  {
148  return combine(static_cast<ossim_uint16>(0), tileRect, resLevel);
149  }
150  else
151  {
152  return combineNorm(static_cast<ossim_uint16>(0), tileRect,
153  resLevel);
154  }
155  }
156  case OSSIM_SINT16:
157  {
158  if(!hasDifferentInputs())
159  {
160  return combine(static_cast<ossim_sint16>(0), tileRect, resLevel);
161  }
162  else
163  {
164  return combineNorm(static_cast<ossim_sint16>(0), tileRect,
165  resLevel);
166  }
167  }
168  case OSSIM_SINT32:
169  {
170  if(!hasDifferentInputs())
171  {
172  return combine(static_cast<ossim_sint32>(0), tileRect, resLevel);
173  }
174  else
175  {
176  return combineNorm(static_cast<ossim_sint32>(0), tileRect,
177  resLevel);
178  }
179  }
180  case OSSIM_UINT32:
181  {
182  if(!hasDifferentInputs())
183  {
184  return combine(static_cast<ossim_uint32>(0), tileRect, resLevel);
185  }
186  else
187  {
188  return combineNorm(static_cast<ossim_uint32>(0), tileRect,
189  resLevel);
190  }
191  }
192  case OSSIM_FLOAT64:
194  {
195  if(!hasDifferentInputs())
196  {
197  return combine(static_cast<double>(0), tileRect, resLevel);
198  }
199  else
200  {
201  return combineNorm(static_cast<double>(0), tileRect, resLevel);
202  }
203  }
205  default:
206  {
208  << "ossimBlendMosaic::getTile NOTICE:\n"
209  << "Scalar type = " << theTile->getScalarType()
210  << " Not supported by ossimImageMosaic" << endl;
211  }
212  }
213 
214  return ossimRefPtr<ossimImageData>();
215 }
216 
218  T,
219  const ossimIrect& tileRect,
220  ossim_uint32 resLevel)
221 {
222  ossimRefPtr<ossimImageData> currentImageData=NULL;
223  ossim_uint32 band;
224  double currentWeight = 1.0;
225  double previousWeight = 1.0;
226  // double sumOfWeights = 1;
227  long offset = 0;
228  long row = 0;
229  long col = 0;
230  ossim_uint32 layerIdx = 0;
231  currentImageData = getNextTile(layerIdx, 0, tileRect, resLevel);
232 
233  if(!currentImageData.get()) // if we don't have one then return theTile
234  {
235  return theTile;
236  }
237 
238  T** srcBands = new T*[theLargestNumberOfInputBands];
239  T** destBands = new T*[theLargestNumberOfInputBands];
240  T* nullPix = new T[theTile->getNumberOfBands()];
241 
242  previousWeight = theWeights[layerIdx];
243  // // now get the previous weight and then combine the two into one.
244  // let's assign the bands
245  for(band = 0; band < theLargestNumberOfInputBands; ++band)
246  {
247  destBands[band] = static_cast<T*>(theTile->getBuf(band));
248  nullPix[band] = static_cast<T>(theTile->getNullPix(band));
249  }
250  while(currentImageData.get())
251  {
252  ossimDataObjectStatus currentStatus =
253  currentImageData->getDataObjectStatus();
254 
255  // set the current weight for the current tile.
256  currentWeight = theWeights[layerIdx];
257 
258  // sumOfWeights = previousWeight+currentWeight;
259  if( (currentStatus != OSSIM_EMPTY) &&
260  (currentStatus != OSSIM_NULL))
261  {
262  long h = (long)currentImageData->getHeight();
263  long w = (long)currentImageData->getWidth();
264  offset = 0;
265  ossim_uint32 minNumberOfBands = currentImageData->getNumberOfBands();
266 
267  // let's assign the bands
268  for(band = 0; band < minNumberOfBands; ++band)
269  {
270  srcBands[band] = static_cast<T*>(currentImageData->getBuf(band));
271  }
272  for(;band < theLargestNumberOfInputBands; ++band)
273  {
274  srcBands[band] = srcBands[minNumberOfBands - 1];
275  }
276 
277  if(currentStatus == OSSIM_PARTIAL)
278  {
279  for(row = 0; row < h; ++row)
280  {
281  for(col = 0; col < w; ++col)
282  {
283  if(!currentImageData->isNull(offset))
284  {
285  for(band = 0; band < theLargestNumberOfInputBands; ++band)
286  {
287  if(destBands[band][offset] != nullPix[band])
288  {
289 // destBands[band][offset] = static_cast<T>((destBands[band][offset]*(1.0-currentWeight) +
290 // srcBands[band][offset]*currentWeight));
291  destBands[band][offset] = static_cast<T>((destBands[band][offset]*previousWeight +
292  srcBands[band][offset]*currentWeight)/(previousWeight+currentWeight));
293  }
294  else
295  {
296  destBands[band][offset] = srcBands[band][offset];
297  }
298  }
299  }
300  ++offset;
301  }
302  }
303  }
304  else
305  {
306  for(row = 0; row < h; ++row)
307  {
308  for(col = 0; col < w; ++col)
309  {
310  for(band = 0; band < theLargestNumberOfInputBands; ++band)
311  {
312  if(destBands[band][offset] != nullPix[band])
313  {
314  destBands[band][offset] = static_cast<T>((destBands[band][offset]*previousWeight+
315  srcBands[band][offset]*currentWeight)/(previousWeight + currentWeight));
316  }
317  else
318  {
319  destBands[band][offset] = srcBands[band][offset];
320  }
321  }
322  ++offset;
323  }
324  }
325  }
326  }
327  currentImageData = getNextTile(layerIdx, tileRect, resLevel);
328  previousWeight = (previousWeight+currentWeight)/2.0;
329  }
330  delete [] srcBands;
331  delete [] destBands;
332  delete [] nullPix;
333  theTile->validate();
334 
335  return theTile;
336 }
337 
339  T, const ossimIrect& tileRect, ossim_uint32 resLevel)
340 {
341  ossimRefPtr<ossimImageData> currentImageData=NULL;
342  ossim_uint32 band;
343  double currentWeight = 1.0;
344  double previousWeight = 1.0;
345  // double sumOfWeights = 1;
346  long offset = 0;
347  long row = 0;
348  long col = 0;
349  ossim_uint32 layerIdx = 0;
350  currentImageData = getNextNormTile(layerIdx, 0, tileRect, resLevel);
351 
352  if(!currentImageData.get()) // if we don't have one then return theTile
353  {
354  return theTile;
355  }
357  float** srcBands = new float*[theLargestNumberOfInputBands];
358  float** destBands = new float*[theLargestNumberOfInputBands];
359  float* nullPix = new float[theTile->getNumberOfBands()];
360 
361  previousWeight = theWeights[layerIdx];
362  // // now get the previous weight and then combine the two into one.
363  // let's assign the bands
364  for(band = 0; band < theLargestNumberOfInputBands; ++band)
365  {
366  destBands[band] = static_cast<float*>(theNormResult->getBuf(band));
367  nullPix[band] = static_cast<float>(theNormResult->getNullPix(band));
368  }
369  while(currentImageData.get())
370  {
371  ossimDataObjectStatus currentStatus = currentImageData->getDataObjectStatus();
372 
373  // set the current weight for the current tile.
374  currentWeight = theWeights[layerIdx];
375 
376  // sumOfWeights = previousWeight+currentWeight;
377  if( (currentStatus != OSSIM_EMPTY) &&
378  (currentStatus != OSSIM_NULL))
379  {
380  long h = (long)currentImageData->getHeight();
381  long w = (long)currentImageData->getWidth();
382  offset = 0;
383  ossim_uint32 minNumberOfBands = currentImageData->getNumberOfBands();
384 
385  // let's assign the bands
386  for(band = 0; band < minNumberOfBands; ++band)
387  {
388  srcBands[band] = static_cast<float*>(currentImageData->getBuf(band));
389  }
390  for(;band < theLargestNumberOfInputBands; ++band)
391  {
392  srcBands[band] = srcBands[minNumberOfBands - 1];
393  }
394 
395  if(currentStatus == OSSIM_PARTIAL)
396  {
397  for(row = 0; row < h; ++row)
398  {
399  for(col = 0; col < w; ++col)
400  {
401  if(!currentImageData->isNull(offset))
402  {
403  for(band = 0; band < theLargestNumberOfInputBands; ++band)
404  {
405  if(destBands[band][offset] != nullPix[band])
406  {
407  destBands[band][offset] = static_cast<float>((destBands[band][offset]*previousWeight +
408  srcBands[band][offset]*currentWeight)/(previousWeight+currentWeight));
409  }
410  else
411  {
412  destBands[band][offset] = srcBands[band][offset];
413  }
414  }
415  }
416  ++offset;
417  }
418  }
419  }
420  else
421  {
422  for(row = 0; row < h; ++row)
423  {
424  for(col = 0; col < w; ++col)
425  {
426  for(band = 0; band < theLargestNumberOfInputBands; ++band)
427  {
428  if(destBands[band][offset] != nullPix[band])
429  {
430  destBands[band][offset] = static_cast<float>((destBands[band][offset]*previousWeight+
431  srcBands[band][offset]*currentWeight)/(previousWeight + currentWeight));
432  }
433  else
434  {
435  destBands[band][offset] = srcBands[band][offset];
436  }
437  }
438  ++offset;
439  }
440  }
441  }
442  }
443  currentImageData = getNextNormTile(layerIdx, tileRect, resLevel);
444  previousWeight = (previousWeight+currentWeight)/2.0;
445  }
448  delete [] srcBands;
449  delete [] destBands;
450  delete [] nullPix;
451  theTile->validate();
452 
453  return theTile;
454 }
455 
457  const char* prefix)const
458 {
459  bool result = ossimImageMosaic::saveState(kwl, prefix);
460 
461  ossimString copyPrefix = prefix;
462  for(ossim_uint32 index = 0; index < theWeights.size(); ++index)
463  {
464  ossimString weightStr = ossimString("weight") +
465  ossimString::toString(index);
466  kwl.add(copyPrefix.c_str(),
467  weightStr.c_str(),
468  theWeights[index],
469  true);
470  }
471 
472  return result;
473 }
474 
476  const char* prefix)
477 {
478  bool result = ossimImageMosaic::loadState(kwl, prefix);
479  ossim_uint32 count = 0;
480  theWeights.clear();
481  if(result)
482  {
483  ossimString copyPrefix = prefix;
484  ossimString regExpression = ossimString("^(") + copyPrefix + "weight[0-9]+)";
485  ossim_uint32 result = kwl.getNumberOfSubstringKeys(regExpression);
486 
487  ossim_uint32 numberOfMatches = 0;
488  while(numberOfMatches < result)
489  {
490  ossimString value = ossimString("weight") + ossimString::toString(count);
491 
492  const char* lookup = kwl.find(copyPrefix.c_str(),
493  value.c_str());
494 
495  if(lookup)
496  {
497  ++numberOfMatches;
498  theWeights.push_back(ossimString(lookup).toDouble());
499  }
500 
501  ++count;
502  }
503  }
504 
505  return result;
506 }
507 
508 
510 {
511  if(numberOfWeights > theWeights.size())
512  {
513  ossim_uint32 length = numberOfWeights - (ossim_uint32) theWeights.size();
514  for(ossim_uint32 index= 0; index < length; ++ index)
515  {
516  theWeights.push_back(1.0);
517  }
518  }
519  else if(numberOfWeights < theWeights.size())
520  {
521  // copy the list
522  vector<double> temp(theWeights.begin(),
523  theWeights.begin()+numberOfWeights);
524  // now shrink
525  theWeights = temp;
526  }
527 }
528 
530 {
531  for(ossim_uint32 index = 0; index < theWeights.size(); ++index)
532  {
533  theWeights[index] = value;
534  }
535 }
536 
538 {
539  double sumWeights=0.0;
540  ossim_uint32 index = 0;
541  for(index = 0; index < theWeights.size(); ++index)
542  {
543  sumWeights+=theWeights[index];
544  }
545  if(sumWeights > 0.0)
546  {
547  for(index = 0; index < theWeights.size(); ++index)
548  {
549  theWeights[index] /= sumWeights;
550  }
551  }
552 }
553 
554 void ossimBlendMosaic::findMinMax(double& minValue, double& maxValue)const
555 {
556  if(theWeights.size() > 0)
557  {
558  minValue = maxValue = theWeights[0];
559 
560  for(ossim_uint32 index = 1; index < theWeights.size(); ++index)
561  {
562  minValue = minValue < theWeights[index]?minValue:theWeights[index];
563  maxValue = maxValue > theWeights[index]?maxValue:theWeights[index];
564  }
565  }
566 }
567 
568 void ossimBlendMosaic::setWeight(ossim_uint32 index, double weight)
569 {
570  if(index < theWeights.size())
571  {
572  theWeights[index] = weight;
573  }
574 }
575 
576 void ossimBlendMosaic::setWeights(const std::vector<double>& weights)
577 {
578  theWeights = weights;
579 }
580 
581 const vector<double>& ossimBlendMosaic::getWeights()const
582 {
583  return theWeights;
584 }
585 
587 {
588  if(index < theWeights.size())
589  {
590  return theWeights[index];
591  }
592  if(theWeights.size())
593  {
594  return theWeights[theWeights.size()-1];
595  }
596  return 0;
597 }
16 bit unsigned integer (15 bits used)
8 bit signed integer
virtual void initialize()
virtual ossim_uint32 getWidth() const
ossimRefPtr< ossimImageData > theNormResult
double getWeight(ossim_uint32 index) const
virtual bool isSourceEnabled() const
Definition: ossimSource.cpp:79
ossimRefPtr< ossimImageData > theTile
virtual ossim_uint32 getNumberOfBands() const
ossim_uint32 getNumberOfSubstringKeys(const ossimString &regularExpression) const
64 bit floating point
virtual void setImageRectangle(const ossimIrect &rect)
16 bit unsigned integer
Represents serializable keyword/value map.
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=NULL)
Method to the load (recreate) the state of an object from a keyword list.
bool valid() const
Definition: ossimRefPtr.h:75
const char * find(const char *key) const
virtual ossimRefPtr< ossimImageData > getNextNormTile(ossim_uint32 &returnedIdx, const ossim_uint32 index, const ossimIrect &tileRect, ossim_uint32 resLevel=0)
ossimRefPtr< ossimImageData > combineNorm(T, const ossimIrect &tileRect, ossim_uint32)
static ossimString toString(bool aValue)
Numeric to string methods.
16 bit signed integer
virtual ossimDataObjectStatus getDataObjectStatus() const
virtual ossim_uint32 getHeight() const
16 bit unsigned integer (14 bits used)
16 bit unsigned integer (13 bits used)
virtual ossimRefPtr< ossimImageData > getTile(const ossimIrect &origin, ossim_uint32 resLevel=0)
32 bit floating point
void findMinMax(double &minValue, double &maxValue) const
An image mosaic is a simple combiner that will just do a simple mosaic.
32 bit unsigned integer
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=NULL) const
Method to save the state of an object to a keyword list.
virtual void initialize()
Initialize the data buffer.
void setAllWeightsTo(double value)
bool isNull(ossim_uint32 offset) const
void add(const char *prefix, const ossimKeywordlist &kwl, bool overwrite=true)
void allocate()
Called on first getTile, will initialize all data needed.
virtual ossimRefPtr< ossimImageData > getNextTile(ossim_uint32 &returnedIdx, const ossim_uint32 startIdx, const ossimIrect &tileRect, ossim_uint32 resLevel=0)
virtual void initialize()
std::vector< ossimRefPtr< ossimConnectableObject > > ConnectableObjectList
ossim_uint32 theLargestNumberOfInputBands
yy_size_t size
virtual ossimDataObjectStatus validate() const
vector< double > theWeights
32 bit signed integer
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
unsigned int ossim_uint32
virtual const ossim_float64 * getNullPix() const
32 bit normalized floating point
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of an object to a keyword list.
virtual ossimRefPtr< ossimImageData > getTile(const ossimIrect &origin, ossim_uint32 resLevel=0)
virtual void copyNormalizedBufferToTile(ossim_float64 *buf)
Copies buf passed in to tile.
virtual bool hasDifferentInputs() const
void setWeight(ossim_uint32 index, double weight)
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)
ConnectableObjectList theInputObjectList
Holds a list of input objects.
void normalizeWeights()
Will find the min and max values and then normalize all weights to be from 0 to 1.
virtual const void * getBuf() const
ossimRefPtr< ossimImageData > combine(T, const ossimIrect &tileRect, ossim_uint32)
If our inputs have output of different scalar types then we must normalize so we can blend different ...
virtual ossim_uint32 getNumberOfInputs() const
Returns the number of input objects.
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 setNumberOfWeights(ossim_uint32 numberOfWeights)
8 bit unsigned integer
#define RTTI_DEF1(cls, name, b1)
Definition: ossimRtti.h:485
ossimDataObjectStatus
Definitions for data object status.
void setWeights(const std::vector< double > &weights)
virtual ~ossimBlendMosaic()
const std::vector< double > & getWeights() const
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
16 bit unsigned integer (12 bits used)