OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossim3x3ConvolutionFilter.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: ossim3x3ConvolutionFilter.cpp 12956 2008-06-02 01:38:50Z dburken $
12 
13 #include <cstdlib>
15 #include <ossim/base/ossimIrect.h>
18 
19 RTTI_DEF1(ossim3x3ConvolutionFilter, "ossim3x3ConvolutionFilter", ossimImageSourceFilter);
20 
22  :ossimImageSourceFilter(owner),
23  theTile(NULL),
24  theNullPixValue(0),
25  theMinPixValue(0),
26  theMaxPixValue(0)
27 {
28  theKernel[0][0] = 0.0; theKernel[0][1] = 0.0; theKernel[0][2] = 0.0;
29  theKernel[1][0] = 0.0; theKernel[1][1] = 1.0; theKernel[1][2] = 0.0;
30  theKernel[2][0] = 0.0; theKernel[2][1] = 0.0; theKernel[2][2] = 0.0;
31 
32 }
33 
35 {
36 }
37 
39  const ossimIrect& tileRect,
40  ossim_uint32 resLevel)
41 {
43  {
44  return theTile;
45  }
46 
47  if(!isSourceEnabled())
48  {
49  return theInputConnection->getTile(tileRect, resLevel);
50  }
51 
52  //---
53  // We have a 3x3 matrix so stretch the rect out to cover
54  // the required pixels. We only need 1 pixel to the left
55  // and right of the center pixel.
56  //---
57  ossimIrect newRect(ossimIpt(tileRect.ul().x - 1,
58  tileRect.ul().y - 1),
59  ossimIpt(tileRect.lr().x + 1,
60  tileRect.lr().y + 1));
61 
63  resLevel);
64 
65  if(!data.valid() || !data->getBuf())
66  {
67  return data;
68  }
69 
70  // First time through or after an initialize()...
71  if (!theTile.valid())
72  {
73  allocate();
74  if (!theTile.valid()) // Should never happen!
75  {
76  return data;
77  }
78  }
79 
80  // First time through, after an initialize() or a setKernel()...
81  if (!theNullPixValue.size())
82  {
84  if (!theNullPixValue.size()) // Should never happen!
85  {
86  return data;
87  }
88  }
89 
90  theTile->setImageRectangle(tileRect);
91  theTile->makeBlank();
92 
93  switch(data->getScalarType())
94  {
95  case OSSIM_UCHAR:
96  {
97  if(data->getDataObjectStatus() == OSSIM_FULL)
98  {
99  convolveFull(static_cast<ossim_uint8>(0), data, theTile);
100  }
101  else
102  {
103  convolvePartial(static_cast<ossim_uint8>(0), data, theTile);
104  }
105  break;
106  }
107  case OSSIM_FLOAT:
109  {
110  if(data->getDataObjectStatus() == OSSIM_FULL)
111  {
112  convolveFull(static_cast<float>(0), data, theTile);
113  }
114  else
115  {
116  convolvePartial(static_cast<float>(0), data, theTile);
117  }
118  break;
119  }
120  case OSSIM_USHORT16:
121  case OSSIM_USHORT11:
122  case OSSIM_USHORT12:
123  case OSSIM_USHORT13:
124  case OSSIM_USHORT14:
125  case OSSIM_USHORT15:
126  {
127  if(data->getDataObjectStatus() == OSSIM_FULL)
128  {
129  convolveFull(static_cast<ossim_uint16>(0), data, theTile);
130  }
131  else
132  {
133  convolvePartial(static_cast<ossim_uint16>(0), data, theTile);
134  }
135  break;
136  }
137  case OSSIM_SSHORT16:
138  {
139  if(data->getDataObjectStatus() == OSSIM_FULL)
140  {
141  convolveFull(static_cast<ossim_sint16>(0), data, theTile);
142  }
143  else
144  {
145  convolvePartial(static_cast<ossim_sint16>(0), data, theTile);
146  }
147  break;
148  }
149  case OSSIM_DOUBLE:
151  {
152  if(data->getDataObjectStatus() == OSSIM_FULL)
153  {
154  convolveFull(static_cast<double>(0), data, theTile);
155  }
156  else
157  {
158  convolvePartial(static_cast<double>(0), data, theTile);
159  }
160  break;
161  }
162  default:
163  {
165  << "ossim3x3ConvolutionFilter::getTile WARNING:\n"
166  << "Scalar type = " << theTile->getScalarType()
167  << " Not supported by ossim3x3ConvolutionFilter" << endl;
168  break;
169  }
170  }
171  theTile->validate();
172 
173  return theTile;
174 }
175 
176 
178  T,
179  ossimRefPtr<ossimImageData> inputData,
180  ossimRefPtr<ossimImageData> outputData)
181 {
182  // let's set up some temporary variables so we don't
183  // have to call the functions in loops. Iknow that compilers
184  // typically optimize this out but if we are in debug mode
185  // with no optimization it will still run fast
186  //
187  double sum = 0.0;
188  ossim_int32 inputW = (ossim_int32)inputData->getWidth();
189  ossim_int32 outputW = (ossim_int32)outputData->getWidth();
190  ossim_int32 outputH = (ossim_int32)outputData->getHeight();
191  ossim_int32 numberOfBands = (ossim_int32)inputData->getNumberOfBands();
192  ossimIpt outputOrigin = outputData->getOrigin();
193  ossimIpt inputOrigin = inputData->getOrigin();
194 
195  ossim_int32 startInputOffset = std::abs(outputOrigin.y - inputOrigin.y)*
196  inputW + std::abs(outputOrigin.x - inputOrigin.x);
197  ossim_int32 ulKernelStart = -inputW - 1;
198  ossim_int32 leftKernelStart = -1;
199  ossim_int32 llKernelStart = inputW - 1;
200 
201  T* ulKernelStartBuf = NULL;
202  T* leftKernelStartBuf = NULL;
203  T* llKernelStartBuf = NULL;
204 
205  for(ossim_int32 band = 0; band < numberOfBands; ++band)
206  {
207  T* inputBuf = static_cast<T*>(inputData->getBuf(band))+startInputOffset;
208  T* outputBuf = static_cast<T*>(outputData->getBuf(band));
209  T maxPix = static_cast<T>(getMaxPixelValue(band));
210  T minPix = static_cast<T>(getMinPixelValue(band));
211  T nullPix = static_cast<T>(inputData->getNullPix(band));
212  T oNullPix = static_cast<T>(getNullPixelValue(band));
213 
214  if(inputBuf&&outputBuf)
215  {
216  for(ossim_int32 row = 0; row < outputW; ++row)
217  {
218  ossim_int32 rowOffset = inputW*row;
219  ulKernelStartBuf = inputBuf + (rowOffset + ulKernelStart);
220  leftKernelStartBuf = inputBuf + (rowOffset + leftKernelStart);
221  llKernelStartBuf = inputBuf + (rowOffset + llKernelStart);
222  for(ossim_int32 col = 0; col < outputH; ++col)
223  {
224 
225  if((ulKernelStartBuf[0] != nullPix)&&
226  (ulKernelStartBuf[1] != nullPix)&&
227  (ulKernelStartBuf[2] != nullPix)&&
228  (leftKernelStartBuf[0] != nullPix)&&
229  (leftKernelStartBuf[1] != nullPix)&&
230  (leftKernelStartBuf[2] != nullPix)&&
231  (llKernelStartBuf[0] != nullPix)&&
232  (llKernelStartBuf[1] != nullPix)&&
233  (llKernelStartBuf[2] != nullPix))
234  {
235  sum = theKernel[0][0]*(double)ulKernelStartBuf[0] +
236  theKernel[0][1]*(double)ulKernelStartBuf[1] +
237  theKernel[0][2]*(double)ulKernelStartBuf[2] +
238  theKernel[1][0]*(double)leftKernelStartBuf[0] +
239  theKernel[1][1]*(double)leftKernelStartBuf[1] +
240  theKernel[1][2]*(double)leftKernelStartBuf[2] +
241  theKernel[2][0]*(double)llKernelStartBuf[0] +
242  theKernel[2][1]*(double)llKernelStartBuf[1] +
243  theKernel[2][2]*(double)llKernelStartBuf[2];
244 
245  if(sum > maxPix)
246  {
247  *outputBuf = maxPix;
248  }
249  else if(sum < minPix)
250  {
251  *outputBuf = minPix;
252  }
253  else
254  {
255  *outputBuf = static_cast<T>(sum);
256  }
257  }
258  else {
259  *outputBuf = oNullPix;
260  }
261  //
262  // Need to implement the convolution here
263  //
264 
265  ++ulKernelStartBuf;
266  ++leftKernelStartBuf;
267  ++llKernelStartBuf;
268  ++outputBuf;
269  }
270  }
271  }
272  }
273 }
274 
276  T,
277  ossimRefPtr<ossimImageData> inputData,
278  ossimRefPtr<ossimImageData> outputData)
279 {
280  // let's set up some temporary variables so we don't
281  // have to call the functions in loops. Iknow that compilers
282  // typically optimize this out but if we are in debug mode
283  // with no optimization it will still run fast
284  //
285  double sum = 0.0;
286  ossim_int32 inputW = static_cast<ossim_int32>(inputData->getWidth());
287  ossim_uint32 outputW = outputData->getWidth();
288  ossim_uint32 outputH = outputData->getHeight();
289  ossim_uint32 numberOfBands = inputData->getNumberOfBands();
290  ossimIpt outputOrigin = outputData->getOrigin();
291  ossimIpt inputOrigin = inputData->getOrigin();
292 
293  ossim_int32 startInputOffset = std::abs(outputOrigin.y - inputOrigin.y)*
294  inputW + std::abs(outputOrigin.x - inputOrigin.x);
295  ossim_int32 ulKernelStart = -inputW - 1;
296  ossim_int32 leftKernelStart = -1;
297  ossim_int32 llKernelStart = inputW - 1;
298 
299  T* ulKernelStartBuf = NULL;
300  T* leftKernelStartBuf = NULL;
301  T* llKernelStartBuf = NULL;
302 
303  for(ossim_uint32 band = 0; band < numberOfBands; ++band)
304  {
305  T* inputBuf = static_cast<T*>(inputData->getBuf(band))+startInputOffset;
306  T* outputBuf = static_cast<T*>(outputData->getBuf(band));
307  T maxPix = static_cast<T>(getMaxPixelValue(band));
308  T minPix = static_cast<T>(getMinPixelValue(band));
309 
310  if(inputBuf&&outputBuf)
311  {
312  for(ossim_uint32 row = 0; row < outputW; ++row)
313  {
314  ossim_int32 rowOffset = inputW*row;
315  ulKernelStartBuf = inputBuf + (rowOffset + ulKernelStart);
316  leftKernelStartBuf = inputBuf + (rowOffset + leftKernelStart);
317  llKernelStartBuf = inputBuf + (rowOffset + llKernelStart);
318  for(ossim_uint32 col = 0; col < outputH; ++col)
319  {
320  sum = theKernel[0][0]*(double)ulKernelStartBuf[0] +
321  theKernel[0][1]*(double)ulKernelStartBuf[1] +
322  theKernel[0][2]*(double)ulKernelStartBuf[2] +
323  theKernel[1][0]*(double)leftKernelStartBuf[0] +
324  theKernel[1][1]*(double)leftKernelStartBuf[1] +
325  theKernel[1][2]*(double)leftKernelStartBuf[2] +
326  theKernel[2][0]*(double)llKernelStartBuf[0] +
327  theKernel[2][1]*(double)llKernelStartBuf[1] +
328  theKernel[2][2]*(double)llKernelStartBuf[2];
329 
330  if(sum > maxPix)
331  {
332  *outputBuf = maxPix;
333  }
334  else if(sum < minPix)
335  {
336  *outputBuf = minPix;
337  }
338  else
339  {
340  *outputBuf = static_cast<T>(sum);
341  }
342  //
343  // Need to implement the convolution here.
344  //
345 
346 
347  ++ulKernelStartBuf;
348  ++leftKernelStartBuf;
349  ++llKernelStartBuf;
350  ++outputBuf;
351  }
352  }
353  }
354  }
355 }
356 
358 {
359  //---
360  // NOTE:
361  // Since initialize get called often sequentially we will wipe things slick
362  // but not reallocate to avoid multiple delete/allocates.
363  //
364  // On the first getTile call things will be reallocated/computed.
365  //---
366  theTile = NULL;
367  clearNullMinMax();
368 }
369 
371 {
373  {
375 
376  theTile = idf->create(this,
377  this);
378 
379  theTile->initialize();
380  }
381 }
382 
384 {
385  if(!property) return;
386  if(property->getName() == "Kernel")
387  {
389  property.get());
390  if(matrixProperty)
391  {
392  theKernel[0][0] = (*matrixProperty)(0,0);
393  theKernel[1][0] = (*matrixProperty)(1,0);
394  theKernel[2][0] = (*matrixProperty)(2,0);
395  theKernel[0][1] = (*matrixProperty)(0,1);
396  theKernel[1][1] = (*matrixProperty)(1,1);
397  theKernel[2][1] = (*matrixProperty)(2,1);
398  theKernel[0][2] = (*matrixProperty)(0,2);
399  theKernel[1][2] = (*matrixProperty)(1,2);
400  theKernel[2][2] = (*matrixProperty)(2,2);
401 
402  }
403  else
404  {
406  }
407  }
408  else
409  {
411  }
412 }
413 
415 {
416  if(name == "Kernel")
417  {
418  ossimMatrixProperty* property = new ossimMatrixProperty(name);
419  property->resize(3,3);
420  (*property)(0,0) = theKernel[0][0];
421  (*property)(1,0) = theKernel[1][0];
422  (*property)(2,0) = theKernel[2][0];
423  (*property)(0,1) = theKernel[0][1];
424  (*property)(1,1) = theKernel[1][1];
425  (*property)(2,1) = theKernel[2][1];
426  (*property)(0,2) = theKernel[0][2];
427  (*property)(1,2) = theKernel[1][2];
428  (*property)(2,2) = theKernel[2][2];
429  property->setCacheRefreshBit();
430 
431  return property;
432  }
434 }
435 
436 void ossim3x3ConvolutionFilter::getPropertyNames(std::vector<ossimString>& propertyNames)const
437 {
439  propertyNames.push_back("Kernel");
440 }
441 
443  const char* prefix)const
444 {
445  kwl.add(prefix,
446  "rows",
447  3,
448  true);
449 
450  kwl.add(prefix,
451  "cols",
452  3,
453  true);
454 
455  for(ossim_int32 row = 0; row < 3; ++row)
456  {
457  for(ossim_int32 col =0; col < 3; ++col)
458  {
459  ossimString newPrefix = "m" +
460  ossimString::toString(row+1) + "_" +
461  ossimString::toString(col+1);
462  kwl.add(prefix,
463  newPrefix,
464  theKernel[row][col],
465  true);
466  }
467  }
468 
469 
470  return ossimImageSourceFilter::saveState(kwl, prefix);
471 }
472 
473 
475  const char* prefix)
476 {
477  ossimString newPrefix = prefix;
478  newPrefix += ossimString("m");
479 
480  for(ossim_int32 r = 0; r < 3; r++)
481  {
482  for(ossim_int32 c = 0; c < 3; c++)
483  {
484  theKernel[r][c] = 0.0;
485 
486  ossimString value = ossimString::toString(r+1);
487  value += "_";
488  value += ossimString::toString(c+1);
489 
490  const char* v = kwl.find(newPrefix.c_str(),
491  value.c_str());
492  if(v)
493  {
494  theKernel[r][c] = ossimString(v).toDouble();
495  }
496  }
497  }
498 
499  return ossimImageSourceFilter::loadState(kwl, prefix);
500 }
501 
502 void ossim3x3ConvolutionFilter::getKernel(double kernel[3][3])
503 {
504  kernel[0][0] = theKernel[0][0];
505  kernel[0][1] = theKernel[0][1];
506  kernel[0][2] = theKernel[0][2];
507  kernel[1][0] = theKernel[1][0];
508  kernel[1][1] = theKernel[1][1];
509  kernel[1][2] = theKernel[1][2];
510  kernel[2][0] = theKernel[2][0];
511  kernel[2][1] = theKernel[2][1];
512  kernel[2][2] = theKernel[2][2];
513 }
514 
515 void ossim3x3ConvolutionFilter::setKernel(double kernel[3][3])
516 {
517  theKernel[0][0] = kernel[0][0];
518  theKernel[0][1] = kernel[0][1];
519  theKernel[0][2] = kernel[0][2];
520  theKernel[1][0] = kernel[1][0];
521  theKernel[1][1] = kernel[1][1];
522  theKernel[1][2] = kernel[1][2];
523  theKernel[2][0] = kernel[2][0];
524  theKernel[2][1] = kernel[2][1];
525  theKernel[2][2] = kernel[2][2];
526 
527  // Will be recomputed first getTile call.
528  clearNullMinMax();
529 }
530 
532 {
533  if( isSourceEnabled() && (band < theNullPixValue.size()) )
534  {
535  return theNullPixValue[band];
536  }
537 
539 }
540 
542 {
543  if( isSourceEnabled() && (band < theMinPixValue.size()) )
544  {
545  return theMinPixValue[band];
546  }
547 
549 }
550 
552 {
553  if( isSourceEnabled() && (band < theMaxPixValue.size()) )
554  {
555  return theMaxPixValue[band];
556  }
557 
559 }
560 
562 {
563  theNullPixValue.clear();
564  theMinPixValue.clear();
565  theMaxPixValue.clear();
566 }
567 
569 {
570  const ossim_uint32 BANDS = getNumberOfOutputBands();
571 
572  theNullPixValue.resize(BANDS);
573  theMinPixValue.resize(BANDS);
574  theMaxPixValue.resize(BANDS);
575 
579 
580  for (ossim_uint32 band = 0; band < BANDS; ++band)
581  {
583  {
587  ossim_float64 tempMin = 0.0;
588  ossim_float64 tempMax = 0.0;
589  ossim_float64 k = 0.0;
590  for(int i=0;i<3;++i)
591  {
592  for(int j=0;j<3;++j)
593  {
594  k=theKernel[i][j];
595  tempMin += (k<0.0) ? k*inputMax : k*inputMin;
596  tempMax += (k>0.0) ? k*inputMax : k*inputMin;
597  }
598  }
599 
600  if((inputNull < getMinPixelValue(band)) ||
601  (inputNull > getMaxPixelValue(band)))
602  {
603  theNullPixValue[band] = inputNull;
604  }
605  else
606  {
608  }
609 
610  if((tempMin >= defaultMin) && (tempMin <= defaultMax))
611  {
612  theMinPixValue[band] = tempMin;
613  }
614  else
615  {
616  theMinPixValue[band] = defaultMin;
617  }
618 
619  if((tempMax >= defaultMin) && (tempMax <= defaultMax))
620  {
621  theMaxPixValue[band] = tempMax;
622  }
623  else
624  {
625  theMaxPixValue[band] = defaultMax;
626  }
627 
628  }
629  else // No input connection...
630  {
632  theMinPixValue[band] = defaultMin;
633  theMaxPixValue[band] = defaultMax;
634  }
635 
636  } // End of band loop.
637 }
16 bit unsigned integer (15 bits used)
virtual ossim_uint32 getWidth() const
virtual bool isSourceEnabled() const
Definition: ossimSource.cpp:79
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
virtual void setProperty(ossimRefPtr< ossimProperty > property)
virtual ossim_uint32 getNumberOfBands() const
virtual void setImageRectangle(const ossimIrect &rect)
Represents serializable keyword/value map.
ossim3x3ConvolutionFilter(ossimObject *owner=NULL)
virtual ossim_uint32 getNumberOfOutputBands() const
Returns the number of bands in a tile returned from this TileSource.
bool valid() const
Definition: ossimRefPtr.h:75
const char * find(const char *key) const
RTTI_DEF1(ossim3x3ConvolutionFilter, "ossim3x3ConvolutionFilter", ossimImageSourceFilter)
void allocate()
Allocates theTile.
static ossimString toString(bool aValue)
Numeric to string methods.
const ossimIpt & ul() const
Definition: ossimIrect.h:274
void convolvePartial(T, ossimRefPtr< ossimImageData > inputData, ossimRefPtr< ossimImageData > outputData)
virtual ossimDataObjectStatus getDataObjectStatus() const
virtual ossim_uint32 getHeight() const
16 bit unsigned integer (14 bits used)
16 bit unsigned integer (13 bits used)
void clearNullMinMax()
Clears data members theNullPixValue, theMinPixValue, and theMaxPixValue.
#define abs(a)
Definition: auxiliary.h:74
void convolveFull(T, ossimRefPtr< ossimImageData > inputData, ossimRefPtr< ossimImageData > outputData)
void computeNullMinMax()
Computes null, min, and max considering input connection and theKernel.
virtual void initialize()
Initialize the data buffer.
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 bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
OSSIM_DLL double defaultMin(ossimScalarType scalarType)
Definition: ossimCommon.cpp:73
static ossimImageDataFactory * instance()
virtual ossimDataObjectStatus validate() const
virtual void getPropertyNames(std::vector< ossimString > &propertyNames) const
OSSIM_DLL double defaultNull(ossimScalarType scalarType)
ossimImageSource * theInputConnection
unsigned int ossim_uint32
virtual const ossim_float64 * getNullPix() const
32 bit normalized floating point
virtual double getMinPixelValue(ossim_uint32 band=0) const
Returns the min pixel of the band.
double toDouble() const
#define PTR_CAST(T, p)
Definition: ossimRtti.h:321
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 > getTile(const ossimIrect &tileRect, ossim_uint32 resLevel=0)
virtual ossimRefPtr< ossimImageData > create(ossimSource *owner, ossimScalarType scalar, ossim_uint32 bands=1) const
virtual void getPropertyNames(std::vector< ossimString > &propertyNames) const
virtual void setKernel(double kernel[3][3])
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_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.
virtual double getMaxPixelValue(ossim_uint32 band=0) const
Returns the max pixel of the band.
ossim_int32 y
Definition: ossimIpt.h:142
virtual const void * getBuf() const
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) 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
ossim_int32 x
Definition: ossimIpt.h:141
virtual double getMaxPixelValue(ossim_uint32 band=0) const
Returns the max pixel of the band.
32 bit floating point
virtual double getNullPixelValue(ossim_uint32 band=0) const
Each band has a null pixel associated with it.
virtual void getKernel(double kernel[3][3])
16 bit unsigned iteger
64 bit floating point
16 bit signed integer
virtual const ossimIpt & getOrigin() const
virtual void setProperty(ossimRefPtr< ossimProperty > property)
virtual double getNullPixelValue(ossim_uint32 band=0) const
Each band has a null pixel associated with it.
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of an object to a keyword list.
ossimRefPtr< ossimImageData > theTile
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
8 bit unsigned iteger
const ossimString & getName() const
int ossim_int32
virtual ossimRefPtr< ossimImageData > getTile(const ossimIpt &origin, ossim_uint32 resLevel=0)
16 bit unsigned integer (12 bits used)