22 #ifndef otbBandMathImageFilter_hxx
23 #define otbBandMathImageFilter_hxx
26 #include "itkImageRegionIterator.h"
27 #include "itkNumericTraits.h"
28 #include "itkProgressReporter.h"
39 template <
class TImage>
44 this->SetNumberOfRequiredInputs(1);
50 m_ThreadUnderflow.SetSize(1);
51 m_ThreadOverflow.SetSize(1);
55 template <
class TImage>
60 template <
class TImage>
63 Superclass::PrintSelf(os, indent);
65 os << indent <<
"Expression: " << m_Expression << std::endl;
66 os << indent <<
"Computed values follow:" << std::endl;
67 os << indent <<
"UnderflowCount: " << m_UnderflowCount << std::endl;
68 os << indent <<
"OverflowCount: " << m_OverflowCount << std::endl;
69 os << indent <<
"itk::NumericTraits<PixelType>::NonpositiveMin() : " << itk::NumericTraits<PixelType>::NonpositiveMin() << std::endl;
70 os << indent <<
"itk::NumericTraits<PixelType>::max() : " << itk::NumericTraits<PixelType>::max() << std::endl;
73 template <
class TImage>
76 this->SetInput(idx,
const_cast<TImage*
>(image));
78 m_VVarName.resize(nbInput + 4);
79 std::ostringstream varName;
80 varName <<
"b" << nbInput;
81 m_VVarName[idx] = varName.str();
83 m_VVarName[idx + 1] =
"idxX";
84 m_VVarName[idx + 2] =
"idxY";
85 m_VVarName[idx + 3] =
"idxPhyX";
86 m_VVarName[idx + 4] =
"idxPhyY";
89 template <
class TImage>
92 this->SetInput(idx,
const_cast<TImage*
>(image));
93 m_VVarName.resize(this->GetNumberOfInputs() + 4);
94 m_VVarName[idx] = varName;
96 m_VVarName[idx + 1] =
"idxX";
97 m_VVarName[idx + 2] =
"idxY";
98 m_VVarName[idx + 3] =
"idxPhyX";
99 m_VVarName[idx + 4] =
"idxPhyY";
102 template <
class TImage>
105 m_VVarName[idx] = varName;
108 template <
typename TImage>
111 return const_cast<TImage*
>(this->GetInput(idx));
114 template <
typename TImage>
117 if (m_Expression != expression)
118 m_Expression = expression;
122 template <
typename TImage>
128 template <
typename TImage>
131 return m_VVarName.at(idx);
134 template <
typename TImage>
137 typename std::vector<ParserType::Pointer>::iterator itParser;
138 unsigned int nbThreads = this->GetNumberOfThreads();
139 unsigned int nbInputImages = this->GetNumberOfInputs();
140 unsigned int nbAccessIndex = 4;
142 unsigned int inputSize[2];
143 std::vector<std::string> tmpIdxVarNames;
145 tmpIdxVarNames.resize(nbAccessIndex);
147 tmpIdxVarNames.resize(nbAccessIndex);
148 tmpIdxVarNames[0] =
"idxX";
149 tmpIdxVarNames[1] =
"idxY";
150 tmpIdxVarNames[2] =
"idxPhyX";
151 tmpIdxVarNames[3] =
"idxPhyY";
154 inputSize[0] = this->GetNthInput(0)->GetLargestPossibleRegion().GetSize(0);
155 inputSize[1] = this->GetNthInput(0)->GetLargestPossibleRegion().GetSize(1);
157 for (
unsigned int p = 1; p < nbInputImages; p++)
159 if ((inputSize[0] != this->GetNthInput(p)->GetLargestPossibleRegion().GetSize(0)) ||
160 (inputSize[1] != this->GetNthInput(p)->GetLargestPossibleRegion().GetSize(1)))
162 itkExceptionMacro(<<
"Input images must have the same dimensions." << std::endl
163 <<
"band #1 is [" << inputSize[0] <<
";" << inputSize[1] <<
"]" << std::endl
164 <<
"band #" << p + 1 <<
" is [" << this->GetNthInput(p)->GetLargestPossibleRegion().GetSize(0) <<
";"
165 << this->GetNthInput(p)->GetLargestPossibleRegion().GetSize(1) <<
"]");
170 m_Spacing = this->GetNthInput(0)->GetSignedSpacing();
171 m_Origin = this->GetNthInput(0)->GetOrigin();
174 m_ThreadUnderflow.SetSize(nbThreads);
175 m_ThreadUnderflow.Fill(0);
176 m_ThreadOverflow.SetSize(nbThreads);
177 m_ThreadOverflow.Fill(0);
178 m_VParser.resize(nbThreads);
179 m_AImage.resize(nbThreads);
180 m_NbVar = nbInputImages + nbAccessIndex;
181 m_VVarName.resize(m_NbVar);
183 for (itParser = m_VParser.begin(); itParser < m_VParser.end(); itParser++)
185 *itParser = ParserType::New();
188 for (i = 0; i < nbThreads; ++i)
190 m_AImage[i].resize(m_NbVar);
191 m_VParser[i]->SetExpr(m_Expression);
193 for (j = 0; j < nbInputImages; ++j)
195 m_VParser[i]->DefineVar(m_VVarName[j], &(m_AImage[i][j]));
198 for (j = nbInputImages; j < nbInputImages + nbAccessIndex; ++j)
200 m_VVarName[j] = tmpIdxVarNames[j - nbInputImages];
201 m_VParser[i]->DefineVar(m_VVarName[j], &(m_AImage[i][j]));
206 template <
typename TImage>
209 unsigned int nbThreads = this->GetNumberOfThreads();
212 m_UnderflowCount = 0;
216 for (i = 0; i < nbThreads; ++i)
218 m_UnderflowCount += m_ThreadUnderflow[i];
219 m_OverflowCount += m_ThreadOverflow[i];
222 if ((m_UnderflowCount != 0) || (m_OverflowCount != 0))
224 <<
"The Following Parsed Expression : " << this->GetExpression() << std::endl
225 <<
"Generated " << m_UnderflowCount <<
" Underflow(s) "
226 <<
"And " << m_OverflowCount <<
" Overflow(s) " << std::endl
227 <<
"The Parsed Expression, The Inputs And The Output "
228 <<
"Type May Be Incompatible !");
231 template <
typename TImage>
236 unsigned int nbInputImages = this->GetNumberOfInputs();
238 typedef itk::ImageRegionConstIterator<TImage> ImageRegionConstIteratorType;
240 assert(nbInputImages);
241 std::vector<ImageRegionConstIteratorType> Vit(nbInputImages);
243 for (j = 0; j < nbInputImages; ++j)
245 Vit[j] = ImageRegionConstIteratorType(this->GetNthInput(j), outputRegionForThread);
248 itk::ImageRegionIterator<TImage> ot(this->GetOutput(), outputRegionForThread);
251 itk::ProgressReporter progress(
this, threadId, outputRegionForThread.GetNumberOfPixels());
253 std::vector<double>& threadImage = m_AImage[threadId];
255 long& threadUnderflow = m_ThreadUnderflow[threadId];
256 long& threadOverflow = m_ThreadOverflow[threadId];
257 ImageRegionConstIteratorType& firstImageRegion = Vit.front();
258 while (!firstImageRegion.IsAtEnd())
260 for (j = 0; j < nbInputImages; ++j)
262 threadImage[j] =
static_cast<double>(Vit[j].Get());
266 for (j = 0; j < 2; ++j)
268 threadImage[nbInputImages + j] =
static_cast<double>(firstImageRegion.GetIndex()[j]);
270 for (j = 0; j < 2; ++j)
272 threadImage[nbInputImages + 2 + j] =
273 static_cast<double>(m_Origin[j]) +
static_cast<double>(firstImageRegion.GetIndex()[j]) *
static_cast<double>(m_Spacing[j]);
279 value = threadParser->Eval();
281 catch (itk::ExceptionObject& err)
283 itkExceptionMacro(<< err);
288 if (value <
double(itk::NumericTraits<PixelType>::NonpositiveMin()))
290 ot.Set(itk::NumericTraits<PixelType>::NonpositiveMin());
295 else if (value >
double(itk::NumericTraits<PixelType>::max()))
297 ot.Set(itk::NumericTraits<PixelType>::max());
305 for (j = 0; j < nbInputImages; ++j)
312 progress.CompletedPixel();