OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimConvolutionSource.cpp
Go to the documentation of this file.
1 // Copyright (C) 2000 ImageLinks Inc.
2 //
3 // License: LGPL
4 //
5 // See LICENSE.txt file in the top level directory for more details.
6 //
7 // Author: Garrett Potts
8 //
9 //*******************************************************************
10 // $Id: ossimConvolutionSource.cpp 18602 2010-12-28 05:49:36Z gpotts $
11 
18 
19 static const ossimKeyword NUMBER_OF_MATRICES = ossimKeyword("number_of_matrices", "");
20 static const ossimKeyword NUMBER_OF_ROWS = ossimKeyword("rows", "");
21 static const ossimKeyword NUMBER_OF_COLS = ossimKeyword("cols", "");
22 
23 RTTI_DEF1(ossimConvolutionSource, "ossimConvolutionSource", ossimImageSourceFilter);
24 
27  theTile(NULL)
28 {
29 }
30 
32  const NEWMAT::Matrix& convolutionMatrix)
33  : ossimImageSourceFilter(inputSource),
34  theTile(NULL)
35 {
36  theConvolutionKernelList.push_back(new ossimDiscreteConvolutionKernel(convolutionMatrix));
38  initialize();
39 }
40 
42  const vector<NEWMAT::Matrix>& convolutionList)
43  : ossimImageSourceFilter(inputSource),
44  theTile(NULL)
45 {
46  setConvolutionList(convolutionList);
47 }
48 
50 {
52 }
53 
54 void ossimConvolutionSource::setConvolution(const double* kernel,
55  int nrows,
56  int ncols,
57  bool doWeightedAverage)
58 {
59  NEWMAT::Matrix m(nrows, ncols);
60  const double* tempPtr = kernel;
61  for(int row = 0; row < nrows; ++row)
62  {
63  for(int col = 0; col < ncols; ++col)
64  {
65  m[row][col] =*tempPtr;
66  ++tempPtr;
67  }
68  }
69 
70  setConvolution(m, doWeightedAverage);
71 }
72 
73 void ossimConvolutionSource::setConvolutionList(const vector<NEWMAT::Matrix>& convolutionList,
74  bool doWeightedAverage)
75 {
77  ossim_uint32 idx;
78  for(idx = 0; idx < convolutionList.size(); ++idx)
79  {
80  theConvolutionKernelList.push_back(new ossimDiscreteConvolutionKernel(convolutionList[idx],
81  doWeightedAverage));
82  }
83 
85 }
86 
88  const ossimIrect& tileRect,
89  ossim_uint32 resLevel)
90 {
92 
93  if((!isSourceEnabled())||
94  (theConvolutionKernelList.size() < 1))
95  {
96  return theInputConnection->getTile(tileRect, resLevel);
97  }
98 
99  if(!theTile.valid())
100  {
101  allocate();
102  if(!theTile.valid()) // Throw exception???
103  {
104  return theInputConnection->getTile(tileRect, resLevel);
105  }
106  }
107 
108  ossim_uint32 w = tileRect.width();
109  ossim_uint32 h = tileRect.height();
110  ossim_uint32 tw = theTile->getWidth();
112  theTile->setWidth(w);
113  theTile->setHeight(h);
114  if((w*h)!=(tw*th))
115  {
116  theTile->initialize();
117  theTile->makeBlank();
118  }
119  else
120  {
121  theTile->makeBlank();
122  }
123  theTile->setOrigin(tileRect.ul());
124  long offsetX = (theMaxKernelWidth)/2;
125  long offsetY = (theMaxKernelHeight)/2;
126  ossimIrect requestRect(tileRect.ul().x - offsetX,
127  tileRect.ul().y - offsetY,
128  tileRect.lr().x + offsetX,
129  tileRect.lr().y + offsetY);
130 
132  resLevel);
133 
134  if(!input.valid() ||
135  (input->getDataObjectStatus() == OSSIM_NULL)||
136  (input->getDataObjectStatus() == OSSIM_EMPTY))
137  {
138  return input;
139  }
140  switch(theTile->getScalarType())
141  {
142  case OSSIM_UCHAR:
143  {
144  if(theConvolutionKernelList.size() == 1)
145  {
146  convolve(static_cast<ossim_uint8>(0),
147  input,
149  }
150  else
151  {
153  ossim_uint32 idx;
154  for(idx = 0; idx < upperBound; ++idx)
155  {
156  convolve(static_cast<ossim_uint8>(0),
157  input,
159  input->loadTile(theTile.get());
160  }
161  }
162  break;
163  }
164  case OSSIM_USHORT16:
165  case OSSIM_USHORT11:
166  case OSSIM_USHORT12:
167  case OSSIM_USHORT13:
168  case OSSIM_USHORT14:
169  case OSSIM_USHORT15:
170  {
171  if(theConvolutionKernelList.size() == 1)
172  {
173  convolve(static_cast<ossim_uint16>(0),
174  input,
176  }
177  else
178  {
180  ossim_uint32 idx;
181  for(idx = 0; idx < upperBound; ++idx)
182  {
183  convolve(static_cast<ossim_uint16>(0),
184  input,
186  input->loadTile(theTile.get());
187  }
188  }
189  break;
190  }
191  case OSSIM_SSHORT16:
192  {
193  if(theConvolutionKernelList.size() == 1)
194  {
195  convolve(static_cast<ossim_sint16>(0),
196  input,
198  }
199  else
200  {
202  ossim_uint32 idx;
203  for(idx = 0; idx < upperBound; ++idx)
204  {
205  convolve(static_cast<ossim_sint16>(0),
206  input,
208  input->loadTile(theTile.get());
209  }
210  }
211  break;
212  }
213  case OSSIM_FLOAT:
215  {
216  if(theConvolutionKernelList.size() == 1)
217  {
218  convolve(static_cast<float>(0),
219  input,
221  }
222  else
223  {
225  ossim_uint32 idx;
226  for(idx = 0; idx < upperBound; ++idx)
227  {
228  convolve(static_cast<float>(0),
229  input,
231  input->loadTile(theTile.get());
232  }
233  }
234  break;
235  }
236  case OSSIM_DOUBLE:
238  {
239  if(theConvolutionKernelList.size() == 1)
240  {
241  convolve(static_cast<double>(0),
242  input,
244  }
245  else
246  {
248  ossim_uint32 idx;
249  for(idx = 0; idx < upperBound; ++idx)
250  {
251  convolve(static_cast<double>(0),
252  input,
254  input->loadTile(theTile.get());
255  }
256  }
257  break;
258  }
259  default:
260  {
261  theTile->loadTile(input.get());
262  }
263  }
264  theTile->validate();
265  return theTile;
266 }
267 
268 template <class T>
269 void ossimConvolutionSource::convolve(T /* dummyVariable */,
270  ossimRefPtr<ossimImageData> inputTile,
272 {
273  ossimIpt startOrigin = theTile->getOrigin();
274 
275  // Make sure that the patch is not empty or NULL
276  //
277  ossimIpt startDelta(startOrigin.x - inputTile->getOrigin().x,
278  startOrigin.y - inputTile->getOrigin().y);
279 
281  // let's setup some variables that we will need to do the
282  // convolution algorithm.
283  //
284  ossimIrect patchRect = inputTile->getImageRectangle();
285  long tileHeight = theTile->getHeight();
286  long tileWidth = theTile->getWidth();
287  long outputBands = theTile->getNumberOfBands();
288  long convolutionWidth = kernel->getWidth();
289  long convolutionHeight = kernel->getHeight();
290  long convolutionOffsetX= convolutionWidth/2;
291  long convolutionOffsetY= convolutionHeight/2;
292  long patchWidth = patchRect.width();
293  long convolutionTopLeftOffset = 0;
294  long convolutionCenterOffset = 0;
295 
296  long outputOffset = 0;
297  T np = 0;
298 
299  const double minPix = ossim::defaultMin(getOutputScalarType());
300  const double maxPix = ossim::defaultMax(getOutputScalarType());
301 // const double* maxPix = inputTile->getMaxPix();
302  const double* nullPix = inputTile->getNullPix();
303  double convolveResult = 0;
304 
305  if(status == OSSIM_PARTIAL) // must check for NULLS
306  {
307  for(long y = 0; y <tileHeight; y++)
308  {
309  convolutionCenterOffset = patchWidth*(startDelta.y + y) + startDelta.x;
310  convolutionTopLeftOffset = patchWidth*(startDelta.y + y - convolutionOffsetY) + startDelta.x-convolutionOffsetX;
311 
312  for(long x =0; x < tileWidth; x++)
313  {
314  if(!inputTile->isNull(convolutionCenterOffset))
315  {
316  for(long b = 0; b < outputBands; ++b)
317  {
318  T* buf = (T*)(inputTile->getBuf(b)) + convolutionTopLeftOffset;
319  T* outBuf = (T*)(theTile->getBuf(b));
320  kernel->convolveSubImage(buf,
321  patchWidth,
322  convolveResult,
323  (T)nullPix[b]);
324 
325  convolveResult = convolveResult < minPix? minPix:convolveResult;
326  convolveResult = convolveResult > maxPix? maxPix:convolveResult;
327 
328  outBuf[outputOffset] = (T)convolveResult;
329  }
330  }
331  else
332  {
333  theTile->setNull(outputOffset);
334 
335  }
336  ++convolutionCenterOffset;
337  ++convolutionTopLeftOffset;
338  ++outputOffset;
339  }
340  }
341  }
342  else // do not need to check for nulls here.
343  {
344  for(long b = 0; b < outputBands; ++b)
345  {
346  double convolveResult = 0;
347  const T* buf = (const T*)inputTile->getBuf(b);
348  T* outBuf = (T*)(theTile->getBuf(b));
349  np =(T)nullPix[b];
350  outputOffset = 0;
351 
352  for(long y = 0; y <tileHeight; y++)
353  {
354  convolutionTopLeftOffset = patchWidth*(startDelta.y + y - convolutionOffsetY) + startDelta.x-convolutionOffsetX;
355 
356  for(long x =0; x < tileWidth; x++)
357  {
358  kernel->convolveSubImage(&buf[convolutionTopLeftOffset],
359  patchWidth,
360  convolveResult,
361  np);
362 // NOT SURE IF I WANT TO CLAMP IN A CONVOLUTION SOURCE
363 // seems better to clamp to a scalar range instead of an input min max
364  convolveResult = convolveResult < minPix? (T)minPix:convolveResult;
365  convolveResult = convolveResult > maxPix?(T)maxPix:convolveResult;
366  outBuf[outputOffset] = (T)convolveResult;
367  ++outputOffset;
368  ++convolutionTopLeftOffset;
369  }
370  }
371  }
372  }
373 }
374 
376 {
378  theTile = NULL;
379 }
380 
382 {
384  {
387  theTile->initialize();
388  }
389 }
390 
392  const char* prefix)const
393 {
394  ossim_uint32 numberOfMatrices = 0;
395  for(ossim_uint32 m = 0; m < theConvolutionKernelList.size();++m)
396  {
398  {
399  ++numberOfMatrices;
400  const NEWMAT::Matrix& kernel = theConvolutionKernelList[m]->getKernel();
401  ossimString mPrefix = "m" +
402  ossimString::toString(numberOfMatrices) +
403  ".";
404  kwl.add(prefix,
405  (mPrefix + "rows").c_str(),
406  kernel.Nrows(),
407  true);
408 
409  kwl.add(prefix,
410  (mPrefix + "cols").c_str(),
411  kernel.Ncols(),
412  true);
413 
414  for(ossim_int32 row = 0; row < kernel.Nrows(); ++row)
415  {
416  for(ossim_int32 col =0; col < kernel.Ncols(); ++col)
417  {
418  ossimString newPrefix = mPrefix +
419  ossimString::toString(row+1) + "_" +
420  ossimString::toString(col+1);
421  kwl.add(prefix,
422  newPrefix,
423  kernel[row][col],
424  true);
425  }
426  }
427  }
428  }
429 
430 
431  kwl.add(prefix,
432  NUMBER_OF_MATRICES,
433  numberOfMatrices,
434  true);
435 
436  return ossimImageSourceFilter::saveState(kwl, prefix);
437 }
438 
439 
441  const char* prefix)
442 {
444 
445  const char* numberOfMatrices = kwl.find(prefix, NUMBER_OF_MATRICES);
446 
447  ossim_int32 matrixCount = ossimString(numberOfMatrices).toLong();
448  ossim_int32 numberOfMatches = 0;
449  ossim_int32 index = 0;
450  while(numberOfMatches < matrixCount)
451  {
452  ossimString newPrefix = prefix;
453  newPrefix += ossimString("m");
454  newPrefix += ossimString::toString(index);
455  newPrefix += ossimString(".");
456 
457  const char* rows = kwl.find((newPrefix+NUMBER_OF_ROWS.key()).c_str());
458  const char* cols = kwl.find((newPrefix+NUMBER_OF_COLS.key()).c_str());
459 
460  if(rows&&cols)
461  {
462  ++numberOfMatches;
463  ossim_int32 numberOfRows = ossimString(rows).toLong();
464  ossim_int32 numberOfCols = ossimString(cols).toLong();
465  NEWMAT::Matrix convolutionMatrix(numberOfRows, numberOfCols);
466 
467 
468  for(ossim_int32 r = 1; r <= numberOfRows; r++)
469  {
470  for(ossim_int32 c = 1; c <= numberOfCols; c++)
471  {
472  convolutionMatrix[r-1][c-1] = 0.0;
473 
475  value += "_";
476  value += ossimString::toString(c);
477 
478  const char* v = kwl.find(newPrefix.c_str(),
479  value.c_str());
480  if(v)
481  {
482  convolutionMatrix[r-1][c-1] = ossimString(v).toDouble();
483  }
484  }
485  }
486  theConvolutionKernelList.push_back(new ossimDiscreteConvolutionKernel(convolutionMatrix));
487  }
488  ++index;
489  }
491  return ossimImageSourceFilter::loadState(kwl, prefix);
492 }
493 
495 {
496  ossim_uint32 index;
497 
498  if(theConvolutionKernelList.size() > 0)
499  {
502 
503  for(index = 1; index < theConvolutionKernelList.size(); ++index)
504  {
505  ossim_int32 w = theConvolutionKernelList[index]->getWidth();
506  ossim_int32 h = theConvolutionKernelList[index]->getHeight();
509  }
510  }
511 }
512 
514 {
515  for(ossim_int32 index = 0; index < (ossim_int32)theConvolutionKernelList.size(); ++index)
516  {
517  delete theConvolutionKernelList[index];
518  }
519 
520  theConvolutionKernelList.clear();
521 }
522 
523 void ossimConvolutionSource::setConvolution(const NEWMAT::Matrix& convolutionMatrix, bool doWeightedAverage)
524 {
525  std::vector<NEWMAT::Matrix> m;
526 
527  m.push_back(convolutionMatrix);
528 
529  setConvolutionList(m, doWeightedAverage);
530 }
16 bit unsigned integer (15 bits used)
virtual ossim_uint32 getWidth() const
ossim_uint32 x
virtual bool isSourceEnabled() const
Definition: ossimSource.cpp:79
virtual ossim_uint32 getNumberOfBands() const
Represents serializable keyword/value map.
ossim_uint32 y
bool valid() const
Definition: ossimRefPtr.h:75
const char * find(const char *key) const
RTTI_DEF1(ossimConvolutionSource, "ossimConvolutionSource", ossimImageSourceFilter)
ossim_uint32 height() const
Definition: ossimIrect.h:487
static ossimString toString(bool aValue)
Numeric to string methods.
ossimRefPtr< ossimImageData > theTile
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 bool saveState(ossimKeywordlist &kwl, const char *prefix=NULL) const
Method to save the state of an object to a keyword list.
ossimRefPtr< ossimImageData > getTile(const ossimIrect &tileRect, ossim_uint32 resLevel=0)
virtual void initialize()
Initialize the data buffer.
bool isNull(ossim_uint32 offset) const
void add(const char *prefix, const ossimKeywordlist &kwl, bool overwrite=true)
virtual void loadTile(const void *src, const ossimIrect &src_rect, ossimInterleaveType il_type)
virtual void setHeight(ossim_uint32 height)
OSSIM_DLL double defaultMin(ossimScalarType scalarType)
Definition: ossimCommon.cpp:73
static ossimImageDataFactory * instance()
void convolve(T dummyVariable, ossimRefPtr< ossimImageData > inputTile, ossimDiscreteConvolutionKernel *kernel)
virtual ossimDataObjectStatus validate() const
virtual void setConvolution(const double *kernel, int nrows, int ncols, bool doWeightedAverage=false)
ossimImageSource * theInputConnection
unsigned int ossim_uint32
virtual const ossim_float64 * getNullPix() const
32 bit normalized floating point
double toDouble() const
virtual void setWidth(ossim_uint32 width)
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.
const ossimIpt & lr() const
Definition: ossimIrect.h:276
virtual ossimRefPtr< ossimImageData > create(ossimSource *owner, ossimScalarType scalar, ossim_uint32 bands=1) const
ossim_uint32 width() const
Definition: ossimIrect.h:500
void setNull(ossim_uint32 offset)
virtual void setOrigin(const ossimIpt &origin)
std::vector< ossimDiscreteConvolutionKernel *> theConvolutionKernelList
return status
virtual ossimScalarType getScalarType() const
virtual void makeBlank()
Initializes data to null pixel values.
64 bit normalized floating point
virtual void setConvolutionList(const vector< NEWMAT::Matrix > &convolutionList, bool doWeightedAverage=false)
16 bit unsigned integer (11 bits used)
long toLong() const
toLong&#39;s deprecated, please use the toInts...
OSSIM_DLL double defaultMax(ossimScalarType scalarType)
virtual ossimScalarType getOutputScalarType() const
This will be used to query the output pixel type of the tile source.
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of an object to a keyword list.
ossim_int32 y
Definition: ossimIpt.h:142
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=NULL)
virtual const void * getBuf() const
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
virtual void convolveSubImage(const float *data, long dataWidth, double &result, float nullPixel=OSSIM_DEFAULT_NULL_PIX_FLOAT) const
ossim_int32 x
Definition: ossimIpt.h:141
ossimDataObjectStatus
Definitions for data object status.
32 bit floating point
16 bit unsigned iteger
64 bit floating point
16 bit signed integer
virtual const ossimIpt & getOrigin() const
8 bit unsigned iteger
int ossim_int32
const char * key() const
virtual ossimRefPtr< ossimImageData > getTile(const ossimIpt &origin, ossim_uint32 resLevel=0)
16 bit unsigned integer (12 bits used)