OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimFeatherMosaic.cpp
Go to the documentation of this file.
1 //*******************************************************************
2 // Copyright (C) 2000 ImageLinks Inc.
3 //
4 // License: LGPL
5 //
6 // See LICENSE.txt file in the top level directory for more details.
7 //
8 // Author: Garrett Potts
9 //
10 //*************************************************************************
11 // $Id: ossimFeatherMosaic.cpp 15766 2009-10-20 12:37:09Z gpotts $
12 
14 #include <ossim/base/ossimDpt.h>
17 #include <ossim/base/ossimLine.h>
18 #include <ossim/base/ossimTrace.h>
19 
20 static ossimTrace traceDebug("ossimFeatherMosaic:debug");
21 
22 RTTI_DEF1(ossimFeatherMosaic, "ossimFeatherMosaic", ossimImageMosaic);
23 
26  theInputFeatherInformation(NULL),
27  theAlphaSum(NULL),
28  theResult(NULL),
29  theFeatherInfoSize(0)
30 {
31 }
32 
34  :ossimImageMosaic(inputSources),
35  theInputFeatherInformation(NULL),
36  theAlphaSum(NULL),
37  theResult(NULL),
38  theFeatherInfoSize(0)
39 {
40  initialize();
41 }
42 
44 {
46  {
49  }
51 }
52 
54  ossim_uint32 resLevel)
55 {
56  long w = tileRect.width();
57  long h = tileRect.height();
58  ossimIpt origin = tileRect.ul();
59 
60  if(!isSourceEnabled())
61  {
62  return ossimImageMosaic::getTile(tileRect, resLevel);
63  }
65  {
66  initialize();
67 
69  {
70  return ossimImageMosaic::getTile(tileRect, resLevel);
71  }
72  }
74  theAlphaSum->setImageRectangle(tileRect);
75  theResult->setImageRectangle(tileRect);
76 
77  if(size == 0)
78  {
80  }
81 
82  if(size == 1)
83  {
84  return ossimImageMosaic::getTile(tileRect, resLevel);
85  }
86 
87  long tileW = theTile->getWidth();
88  long tileH = theTile->getHeight();
89  if((w != tileW)||
90  (h != tileH))
91  {
92  theTile->setWidth(w);
93  theTile->setHeight(h);
94  if((w*h)!=(tileW*tileH))
95  {
97  }
98  }
99  theTile->setOrigin(origin);
100  theTile->makeBlank();
101 
102  switch(theTile->getScalarType())
103  {
104  case OSSIM_UCHAR:
105  {
106  return combine(static_cast<ossim_uint8>(0),
107  tileRect, resLevel);
108  }
109  case OSSIM_USHORT16:
110  case OSSIM_USHORT11:
111  case OSSIM_USHORT12:
112  case OSSIM_USHORT13:
113  case OSSIM_USHORT14:
114  case OSSIM_USHORT15:
115  {
116  return combine(static_cast<ossim_uint16>(0),
117  tileRect, resLevel);
118  }
119  case OSSIM_SSHORT16:
120  {
121  return combine(static_cast<ossim_sint16>(0),
122  tileRect, resLevel);
123  }
124  case OSSIM_DOUBLE:
126  {
127  return combine(static_cast<double>(0),
128  tileRect, resLevel);
129  }
130  case OSSIM_FLOAT:
132  {
133  return combine(static_cast<float>(0),
134  tileRect, resLevel);
135  }
137  default:
138  {
140  << "ossimFeatherMosaic::getTile: error, unknown scalar type!!!"
141  << std::endl;
142  }
143  }
145 }
146 
147 
149  T,
150  const ossimIrect& tileRect,
151  ossim_uint32 resLevel)
152 {
153  ossimRefPtr<ossimImageData> currentImageData;
154  ossim_uint32 band;
155  long upperBound = theTile->getWidth()*theTile->getHeight();
156  long offset = 0;
157  long row = 0;
158  long col = 0;
159  long numberOfTilesProcessed = 0;
160  float *sumBand = static_cast<float*>(theAlphaSum->getBuf());
161  float *bandRes = NULL;
162  ossimIpt point;
163 
164  theAlphaSum->fill(0.0);
165  theResult->fill(0.0);
166 
167  T** srcBands = new T*[theLargestNumberOfInputBands];
168  T** destBands = new T*[theLargestNumberOfInputBands];
169  ossim_uint32 layerIdx = 0;
170  currentImageData = getNextTile(layerIdx,
171  0,
172  tileRect,
173  resLevel);
174  if(!currentImageData.valid())
175  {
176  delete [] srcBands;
177  delete [] destBands;
178  return currentImageData;
179  }
180  ossim_uint32 minNumberOfBands = currentImageData->getNumberOfBands();
181  for(band = 0; band < minNumberOfBands; ++band)
182  {
183  srcBands[band] = static_cast<T*>(currentImageData->getBuf(band));
184  destBands[band] = static_cast<T*>(theTile->getBuf(band));
185  }
186  // if the src is smaller than the destination in number
187  // of bands we will just duplicate the last band.
188  for(;band < theLargestNumberOfInputBands; ++band)
189  {
190  srcBands[band] = srcBands[minNumberOfBands - 1];
191  destBands[band] = static_cast<T*>(theTile->getBuf(band));
192  }
193 
194  // most of the time we will not overlap so let's
195  // copy the first tile into destination and check later.
196  //
197  for(band = 0; band < theTile->getNumberOfBands();++band)
198  {
199  T* destBand = destBands[band];
200  T* srcBand = srcBands[band];
201  if(destBand&&srcBand)
202  {
203  for(offset = 0; offset < upperBound;++offset)
204  {
205  *destBand = *srcBand;
206  ++srcBand; ++destBand;
207  }
208  }
209  }
210  theTile->setDataObjectStatus(currentImageData->getDataObjectStatus());
211 
212  while(currentImageData.valid())
213  {
214  ossimDataObjectStatus currentStatus = currentImageData->getDataObjectStatus();
215  point = currentImageData->getOrigin();
216  long h = (long)currentImageData->getHeight();
217  long w = (long)currentImageData->getWidth();
218  if( (currentStatus != OSSIM_EMPTY) &&
219  (currentStatus != OSSIM_NULL))
220  {
221  ++numberOfTilesProcessed;
222  offset = 0;
223  minNumberOfBands = currentImageData->getNumberOfBands();
224  for(band = 0; band < minNumberOfBands; ++band)
225  {
226  srcBands[band] = static_cast<T*>(currentImageData->getBuf(band));
227  }
228  // if the src is smaller than the destination in number
229  // of bands we will just duplicate the last band.
230  for(;band < theLargestNumberOfInputBands; ++band)
231  {
232  srcBands[band] = srcBands[minNumberOfBands - 1];
233  }
234  if(currentStatus == OSSIM_PARTIAL)
235  {
236  for(row = 0; row < h; ++row)
237  {
238  for(col = 0; col < w; ++col)
239  {
240  if(!currentImageData->isNull(offset))
241  {
242  double weight = computeWeight(layerIdx,
243  ossimDpt(point.x+col,
244  point.y+row));
245 
246  for(band = 0; band < theLargestNumberOfInputBands; ++band)
247  {
248  bandRes = static_cast<float*>(theResult->getBuf(band));
249  bandRes[offset] += (srcBands[band][offset]*weight);
250  }
251  sumBand[offset] += weight;
252  }
253  ++offset;
254  }
255  }
256  }
257  else
258  {
259  offset = 0;
260 
261  for(row = 0; row < h; ++row)
262  {
263  for(col = 0; col < w; ++col)
264  {
265  double weight = computeWeight(layerIdx,
266  ossimDpt(point.x+col,
267  point.y+row));
268 
269  for(band = 0; band < theLargestNumberOfInputBands; ++band)
270  {
271  bandRes = static_cast<float*>(theResult->getBuf(band));
272 
273  bandRes[offset] += (srcBands[band][offset]*weight);
274  }
275  sumBand[offset] += weight;
276  ++offset;
277  }
278  }
279  }
280  }
281  currentImageData = getNextTile(layerIdx, tileRect, resLevel);
282  }
283  upperBound = theTile->getWidth()*theTile->getHeight();
284 
285  if(numberOfTilesProcessed > 1)
286  {
287  const double* minPix = theTile->getMinPix();
288  const double* maxPix = theTile->getMaxPix();
289  const double* nullPix= theTile->getNullPix();
290  for(offset = 0; offset < upperBound;++offset)
291  {
292  for(band = 0; band < theTile->getNumberOfBands();++band)
293  {
294  T* destBand = static_cast<T*>(theTile->getBuf(band));
295  float* weightedBand = static_cast<float*>(theResult->getBuf(band));
296 
297  // this should be ok to test 0.0 instead of
298  // FLT_EPSILON range for 0 since we set it.
299  if(sumBand[offset] != 0.0)
300  {
301  weightedBand[offset] = (weightedBand[offset])/sumBand[offset];
302  if(weightedBand[offset]<minPix[band])
303  {
304  weightedBand[offset] = minPix[band];
305  }
306  else if(weightedBand[offset] > maxPix[band])
307  {
308  weightedBand[offset] = maxPix[band];
309  }
310  }
311  else
312  {
313  weightedBand[offset] = nullPix[band];
314  }
315  destBand[offset] = static_cast<T>(weightedBand[offset]);
316  }
317  }
318  theTile->validate();
319  }
320 
321  delete [] srcBands;
322  delete [] destBands;
323 
324  return theTile;
325 }
326 
328  const ossimDpt& point)const
329 {
331  double result = 0.0;
332  ossimDpt delta = point-info.theCenter;
333 
334  double length1 = fabs(delta.x*info.theAxis1.x + delta.y*info.theAxis1.y)/info.theAxis1Length;
335  double length2 = fabs(delta.x*info.theAxis2.x + delta.y*info.theAxis2.y)/info.theAxis2Length;
336 
337  if(length1 > length2)
338  {
339  result = (1.0 - length1);
340  }
341  else
342  {
343  result = (1.0 - length2);
344  }
345  if(result < 0) result = 0;
346 
347  return result;
348 }
349 
351 {
353 
354  allocate();
355  if(theTile.valid())
356  {
357  theAlphaSum = new ossimImageData(this,
358  OSSIM_FLOAT,
359  1,
360  theTile->getWidth(),
361  theTile->getHeight());
362  theResult = new ossimImageData(this,
363  OSSIM_FLOAT,
365  theTile->getWidth(),
366  theTile->getHeight());
369  }
370  std::vector<ossimIpt> validVertices;
371  if(!getNumberOfInputs()) return;
372 
374  {
375  delete [] theInputFeatherInformation;
377  }
380  for(long index = 0; index < theFeatherInfoSize; ++ index)
381  {
382  validVertices.clear();
384  if(temp)
385  {
386  temp->getValidImageVertices(validVertices, OSSIM_CLOCKWISE_ORDER);
387  theInputFeatherInformation[index].setVertexList(validVertices);
388  }
389  }
390 }
391 
392 
394 {
395  setVertexList(validVertices);
396 }
397 
398 
399 void ossimFeatherMosaic::ossimFeatherInputInformation::setVertexList(const std::vector<ossimIpt>& validVertices)
400 {
401  const char* MODULE = "ossimFeatherMosaic::ossimFeatherInputInformation::setVertexList()";
402 
403  theValidVertices = validVertices;
404 
405  theCenter = ossimDpt(0,0);
406  theAxis1 = ossimDpt(1, 0);
407  theAxis2 = ossimDpt(0, 1);
408  theAxis1Length = 1;
409  theAxis2Length = 1;
410 
411  double xSum=0.0, ySum=0.0;
412  ossim_uint32 upperBound = (ossim_uint32)validVertices.size();
413  if(upperBound)
414  {
415  for(ossim_uint32 index = 0; index < upperBound; ++index)
416  {
417  xSum += validVertices[index].x;
418  ySum += validVertices[index].y;
419  }
420 
421  theCenter.x = xSum/upperBound;
422  theCenter.y = ySum/upperBound;
423 
424  // for now we just want a quick implementation of something
425  // and we know that we have 4 vertices for the bounding valid
426  // vertices.
427  //
428  if(upperBound == 4)
429  {
430  ossimDpt edgeDirection1 = validVertices[1] - validVertices[0];
431  ossimDpt edgeDirection2 = validVertices[2] - validVertices[1];
432 
433  theAxis1 = ossimDpt(-edgeDirection1.y, edgeDirection1.x);
434 
435  theAxis2 = ossimDpt(-edgeDirection2.y, edgeDirection2.x);
436 
437  theAxis1 = theAxis1/theAxis1.length();
438  theAxis2 = theAxis2/theAxis2.length();
439 
440  ossimLine line1(theCenter,
441  theCenter + theAxis1*2);
442  ossimLine line2(validVertices[1],
443  validVertices[0]);
444  ossimLine line3(theCenter,
445  theCenter + theAxis2*2);
446  ossimLine line4(validVertices[2],
447  validVertices[1]);
448 
449  ossimDpt intersectionPoint1 = line1.intersectInfinite(line2);
450  ossimDpt intersectionPoint2 = line3.intersectInfinite(line4);
451 
452 
453  theAxis1Length = ossim::round<int>((theCenter-intersectionPoint1).length());
454  theAxis2Length = ossim::round<int>((theCenter-intersectionPoint2).length());
455 
456  if(traceDebug())
457  {
458  CLOG << "theAxis1Length: " << theAxis1Length << endl
459  << "theAxis2Length: " << theAxis2Length << endl
460  << "center: " << theCenter << endl;
461  }
462  }
463  }
464 }
465 
468 {
469  out << "center: " << data.theCenter << endl
470  << "axis1: " << data.theAxis1 << endl
471  << "axis2: " << data.theAxis2 << endl
472  << "axis1_length: " << data.theAxis1Length << endl
473  << "axis2_length: " << data.theAxis2Length << endl
474  << "valid vertices: " << endl;
475  std::copy(data.theValidVertices.begin(),
476  data.theValidVertices.end(),
477  std::ostream_iterator<ossimDpt>(out, "\n"));
478  return out;
479 }
ossimRefPtr< ossimImageData > theAlphaSum
16 bit unsigned integer (15 bits used)
virtual ossim_uint32 getWidth() const
virtual bool isSourceEnabled() const
Definition: ossimSource.cpp:79
void fill(ossim_uint32 band, ossim_float64 value)
will fill the entire band with the value.
ossimFeatherInputInformation(const vector< ossimIpt > &validVertices=vector< ossimIpt >())
long theFeatherInfoSize
Will hold the count for the feather information list.
ossimRefPtr< ossimImageData > theTile
virtual const ossim_float64 * getMaxPix() const
virtual ossim_uint32 getNumberOfBands() const
ossimRefPtr< ossimImageData > combine(T dummyVariableNotUsed, const ossimIrect &tileRect, ossim_uint32 resLevel)
The dummy variable is used for the template type.
#define CLOG
Definition: ossimTrace.h:23
virtual void setImageRectangle(const ossimIrect &rect)
This is only visible by this class and will remain here unless we want to move it later...
bool valid() const
Definition: ossimRefPtr.h:75
double y
Definition: ossimDpt.h:165
ossim_uint32 height() const
Definition: ossimIrect.h:487
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 ossimRefPtr< ossimImageData > getTile(const ossimIrect &origin, ossim_uint32 resLevel=0)
Performs a spatial blend accross overlapping regions.
An image mosaic is a simple combiner that will just do a simple mosaic.
void setVertexList(const vector< ossimIpt > &validVertices)
virtual void initialize()
Initialize the data buffer.
ossimConnectableObject * getInput(ossim_uint32 index=0)
returns the object at the specified index.
bool isNull(ossim_uint32 offset) const
void allocate()
Called on first getTile, will initialize all data needed.
virtual void setHeight(ossim_uint32 height)
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
ossimDpt intersectInfinite(const ossimLine &line) const
Definition: ossimLine.cpp:20
friend ostream & operator<<(ostream &out, const ossimFeatherInputInformation &data)
ossim_uint32 theLargestNumberOfInputBands
yy_size_t size
virtual ossimDataObjectStatus validate() const
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.
unsigned int ossim_uint32
virtual const ossim_float64 * getNullPix() const
32 bit normalized floating point
#define PTR_CAST(T, p)
Definition: ossimRtti.h:321
virtual void setWidth(ossim_uint32 width)
ossim_uint32 width() const
Definition: ossimIrect.h:500
virtual void setOrigin(const ossimIpt &origin)
virtual const ossim_float64 * getMinPix() const
ossimRefPtr< ossimImageData > theResult
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)
ossim_int32 y
Definition: ossimIpt.h:142
virtual const void * getBuf() const
virtual ossim_uint32 getNumberOfInputs() const
Returns the number of input objects.
double x
Definition: ossimDpt.h:164
virtual void setDataObjectStatus(ossimDataObjectStatus status) const
Full list found in ossimConstants.h.
virtual ossimRefPtr< ossimImageData > getTile(const ossimIrect &origin, ossim_uint32 resLevel=0)
ossim_int32 x
Definition: ossimIpt.h:141
virtual double computeWeight(long index, const ossimDpt &point) const
ossimDataObjectStatus
Definitions for data object status.
RTTI_DEF1(ossimFeatherMosaic, "ossimFeatherMosaic", ossimImageMosaic)
32 bit floating point
ossimFeatherInputInformation * theInputFeatherInformation
will hold an array of input information
16 bit unsigned iteger
64 bit floating point
16 bit signed integer
virtual const ossimIpt & getOrigin() const
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
16 bit unsigned integer (12 bits used)