OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimBandAverageFilter.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: ossimBandAverageFilter.cpp 17206 2010-04-25 23:20:40Z dburken $
13 
14 // used for constructing and an ossimImageData object
16 
17 // used for error reporting and for general info reporting such as warnings
19 
20 #include <sstream>
21 #include <iterator>
22 
23 static const char* WEIGHTS_KW = "weights";
24 
26  "ossimBandAverageFilter",
28 
31  theTile(NULL)
32 {
33 }
34 
36  const std::vector<double>& weights)
37  :ossimImageSourceFilter(input),
38  theTile(NULL),
39  theWeights(weights)
40 {
41 }
42 
44 {
45 }
46 
48 {
49  if(isSourceEnabled())
50  {
51  return 1;
52  }
53 
55 }
56 
58 {
59  // first we will check to see if we have an input connection
60  //
62  {
63  // this will probably be null since we aren't initialized.
64  // we really need to creae a default blank tile in OSSIM that is returned
65  return theTile;
66  }
67 
68  ossimRefPtr<ossimImageData> inputData =
69  theInputConnection->getTile(rect, resLevel);
70 
71  if(!inputData.valid())
72  {
73  return inputData;
74  }
75 
76  // If we are disabled or if the data object is empty or NULL or
77  // not enough bands we don't need to run our algorithm so return the input
78  // tile.
79  if(!isSourceEnabled() ||
80  (inputData->getDataObjectStatus() == OSSIM_NULL)||
81  (inputData->getDataObjectStatus() == OSSIM_EMPTY)||
82  (inputData->getNumberOfBands() < 2))
83  {
84  return inputData;
85  }
86 
87  // check to see if we are initialized
88  if(!theTile.valid())
89  {
90  initialize();
91  }
92 
94 
95  // now lets set up the template method to operate in native type and run
96  // the algorithm
97  //
98  switch(inputData->getScalarType())
99  {
100  case OSSIM_UCHAR:
101  {
102  averageInput((ossim_uint8)0, // setup template variable
103  inputData);
104  break;
105  }
106  case OSSIM_USHORT11:
107  case OSSIM_USHORT12:
108  case OSSIM_USHORT13:
109  case OSSIM_USHORT14:
110  case OSSIM_USHORT15:
111  case OSSIM_USHORT16:
112  {
113  averageInput((ossim_uint16)0, // setup template variable
114  inputData);
115  break;
116  }
117  case OSSIM_SSHORT16:
118  {
119  averageInput((ossim_sint16)0, // setup template variable
120  inputData);
121  break;
122  }
124  case OSSIM_FLOAT:
125  {
126  averageInput((float)0, // setup template variable
127  inputData);
128  break;
129  }
131  case OSSIM_DOUBLE:
132  {
133  averageInput((double)0, // setup template variable
134  inputData);
135  break;
136  }
137  default:
138  {
141  "Unsupported scalar type in file %d at line %d",
142  __FILE__,
143  __LINE__);
144 
145 
146  theTile->makeBlank();
147  break;
148  }
149  }
150 
151  theTile->validate();
152 
153 
154  return theTile;
155 }
156 
157 
158 
160 {
162 
163  // theInputConnection is defined in ossimImageSourceFilter
164  // It is automatically set when an input is connected to this
165  // object
167  {
169 
170  // now initialize the tile
171  theTile->initialize();
172  checkWeights();
173  }
174 }
175 
177 {
178  if(!isSourceEnabled())
179  {
181  }
182  // lets use the first band's null value as our null
184 }
185 
187 {
189  {
191  }
192 
193  // loop through each band and find the min pix value
194  ossim_uint32 bandIndex = 0;
196  double minValue = ossim::defaultMax(OSSIM_DOUBLE);
197  for(bandIndex = 0; bandIndex < inputBands; ++bandIndex)
198  {
199  double minPix = theInputConnection->getMinPixelValue(bandIndex);
200 
201  if(minPix < minValue)
202  {
203  minValue = minPix;
204  }
205  }
206 
207  return minValue;
208 }
209 
211 {
212  if(!isSourceEnabled())
213  {
215  }
216 
217  // loop through each band and find the max pix value
218  ossim_uint32 bandIndex = 0;
220  double maxValue = ossim::defaultMin(OSSIM_DOUBLE);
221  for(bandIndex = 0; bandIndex < inputBands; ++bandIndex)
222  {
223  double maxPix = theInputConnection->getMaxPixelValue(bandIndex);
224 
225  if(maxPix > maxValue)
226  {
227  maxValue = maxPix;
228  }
229  }
230 
231  return maxValue;
232 }
233 
235 {
236  // we have not been initialzed yet
237  //
238  if(!theTile)
239  {
240  return;
241  }
242 
243  // Check to see if the weights array is the same size as the input
244  // list. If not then resize it and populate them with the same weight
245  // value. It does not matter if they sum to one since we will perform
246  // a weighted average in the execution of the algorithm
247  //
249  {
251 
252  std::fill(theWeights.begin(), theWeights.end(), 1);
253  }
254 }
255 
256 
258  T /* dummyVariable */, // used only for template type, value ignored
259  ossimRefPtr<ossimImageData> inputDataObject)
260 {
261  // since we have already checked the input for empty or
262  // null we will now execute the algorithm. We will make
263  //
264  //
265  std::vector<T*> inputBands(inputDataObject->getNumberOfBands());
266  std::vector<double> nullValues(inputDataObject->getNumberOfBands());
267  ossim_uint32 i = 0;
268 
269  // for efficiency we will copy the band pointers and
270  // null values so we don't have extra function calls
271  // on a per band basis
272  //
273  for(i = 0; i < inputDataObject->getNumberOfBands(); ++i)
274  {
275  inputBands[i] = static_cast<T*>(inputDataObject->getBuf(i));
276  nullValues[i] = inputDataObject->getNullPix(i);
277  }
278 
279  // store the output buffer pointer
280  T* outputBuf = static_cast<T*>(theTile->getBuf(0));
281 
282  // setup index values and boundary values
283  ossim_uint32 upperBound = theTile->getWidth()*theTile->getHeight();
284  ossim_uint32 bandIndex = 0;
285  ossim_uint32 numberOfBands = inputDataObject->getNumberOfBands();
286  double outputNullPix = theTile->getNullPix(0);
287 
288  for(i = 0; i < upperBound; ++i)
289  {
290  double value=0.0;
291  double sumWeights=0.0;
292 
293  // loop over each band only using the valid pixel data
294  // in the weighted average.
295  //
296  for(bandIndex = 0; bandIndex < numberOfBands; ++bandIndex)
297  {
298  // if valid then muliply the value by the weight and add it to
299  // current pixel value
300  if(*inputBands[bandIndex] != nullValues[bandIndex])
301  {
302  value += theWeights[bandIndex]*((double)*inputBands[bandIndex]);
303  sumWeights += theWeights[bandIndex];
304  }
305  // increment to the next pixel for the next time around
306  ++inputBands[bandIndex];
307  }
308 
309  // check to see if we had any valid data. If we did the weight
310  // should be greater than 0
311  if(sumWeights != 0.0)
312  {
313  value /= sumWeights;
314  }
315  else
316  {
317  // else we set the pixel to the output null value
318  value = outputNullPix;
319  }
320  // store the result in the outputBuffer.
321  *outputBuf = static_cast<T>(value);
322 
323  // advance the output buffer to the next pixel value
324  ++outputBuf;
325  }
326 }
327 
328 
330  const char* prefix)
331 {
332  // get the value of the stored keyword
333  ossimString weightString = kwl.find(prefix, WEIGHTS_KW);
334  weightString = weightString.trim();
335 
336 
337  theWeights.clear();
338  if(weightString != "")
339  {
340  // split the string list into an array of strings
341  std::vector<ossimString> weightList = weightString.split(" ");
342 
343  // resize the weights to the size of the weight list
344  //
345  theWeights.resize(weightList.size());
346  ossim_uint32 i = 0;
347 
348  // now store the weights to the array
349  for(i = 0; i < theWeights.size(); ++i)
350  {
351  theWeights[i] = weightList[i].toDouble();
352  }
353  }
354 
355  // call base class to continue the load state
356  return ossimImageSourceFilter::loadState(kwl, prefix);
357 }
358 
360  const char* prefix)const
361 {
362  std::stringstream out;
363 
364  // copy the weights to a memory stream separated by space
365  std::copy(theWeights.begin(),
366  theWeights.end(),
367  ostream_iterator<double>(out, " "));
368 
369  ossimString weightString = out.str();
370  weightString = weightString.trim();
371 
372 
373  kwl.add(prefix, // prefix to help uniquely id or attributes
374  WEIGHTS_KW, // the keyword to identity our attribute
375  weightString.c_str(), // the value
376  true); // overwrite if already in the keywordlist
377 
378  // call base classes save to allow us to pass the information up
379  return ossimImageSourceFilter::saveState(kwl, prefix);
380 }
381 
383 {
384  if(band < theWeights.size())
385  {
386  return theWeights[band];
387  }
388 
389  return 0.0;
390 }
391 
393 {
394  if(band < theWeights.size())
395  {
396  theWeights[band] = fabs(weight);
397  }
398 }
OSSIMDLLEXPORT void ossimSetError(const char *className, ossim_int32 error, const char *fmtString=0,...)
16 bit unsigned integer (15 bits used)
virtual ossim_uint32 getWidth() const
virtual bool isSourceEnabled() const
Definition: ossimSource.cpp:79
virtual void initialize()
allocates its tile buffer
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Saves its weights to a keywordlist.
double getWeight(ossim_uint32 band) const
simple access method to get a weight
virtual ossim_uint32 getNumberOfBands() const
std::basic_stringstream< char > stringstream
Class for char mixed input and output memory streams.
Definition: ossimIosFwd.h:38
virtual void setImageRectangle(const ossimIrect &rect)
ossimRefPtr< ossimImageData > theTile
This filter outputs a single band that is the weighted average of all the input bands retrieved from ...
Represents serializable keyword/value map.
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
void split(std::vector< ossimString > &result, const ossimString &separatorList, bool skipBlankFields=false) const
Splits this string into a vector of strings (fields) using the delimiter list specified.
virtual ossimDataObjectStatus getDataObjectStatus() const
virtual ossim_uint32 getHeight() const
16 bit unsigned integer (14 bits used)
static const ossimErrorCode OSSIM_ERROR
virtual ossimString getClassName() const
Definition: ossimObject.cpp:64
16 bit unsigned integer (13 bits used)
unsigned short ossim_uint16
virtual void initialize()
Initialize the data buffer.
virtual double getMinPixelValue(ossim_uint32 band=0) const
Returns the min pixel of the band.
void add(const char *prefix, const ossimKeywordlist &kwl, bool overwrite=true)
OSSIM_DLL double defaultMin(ossimScalarType scalarType)
Definition: ossimCommon.cpp:73
static ossimImageDataFactory * instance()
virtual ossimDataObjectStatus validate() const
signed short ossim_sint16
ossimImageSource * theInputConnection
unsigned int ossim_uint32
virtual const ossim_float64 * getNullPix() const
32 bit normalized floating point
ossimString trim(const ossimString &valueToTrim=ossimString(" \\)) const
this will strip lead and trailing character passed in.
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
loads its weights to a keywordlist
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 double getMinPixelValue(ossim_uint32 band=0) const
We will use the min of all bands as our min.
virtual ossimRefPtr< ossimImageData > create(ossimSource *owner, ossimScalarType scalar, ossim_uint32 bands=1) const
void setWeight(ossim_uint32 band, double weight)
Sinple access method to set the weight of a band, We make sure that it is a positive 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)
OSSIM_DLL double defaultMax(ossimScalarType scalarType)
virtual ossimRefPtr< ossimImageData > getTile(const ossimIrect &rect, ossim_uint32 resLevel=0)
Since this filter is going to operate in native pixel type we will use a tmeplate method to do this...
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.
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 double getNullPixelValue(ossim_uint32 band=0) const
Since we are merging all bands we will use the null pix of the first input band as our null pix...
RTTI_DEF1(ossimBandAverageFilter, "ossimBandAverageFilter", ossimImageSourceFilter)
32 bit floating point
virtual ossim_uint32 getNumberOfOutputBands() const
The data object argument is deprecated and should not be used.
std::vector< double > theWeights
virtual double getMaxPixelValue(ossim_uint32 band=0) const
We will use the max of all bands as our max.
16 bit unsigned iteger
64 bit floating point
16 bit signed integer
unsigned char ossim_uint8
virtual double getNullPixelValue(ossim_uint32 band=0) const
Each band has a null pixel associated with it.
8 bit unsigned iteger
virtual ossimRefPtr< ossimImageData > getTile(const ossimIpt &origin, ossim_uint32 resLevel=0)
16 bit unsigned integer (12 bits used)
void averageInput(T dummyVariable, ossimRefPtr< ossimImageData > inputDataObject)