]> Creatis software - clitk.git/blob - filters/clitkImageArithmGenericFilter.txx
Reformatted using new coding style
[clitk.git] / filters / clitkImageArithmGenericFilter.txx
1 /*=========================================================================
2   Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
3
4   Authors belong to:
5   - University of LYON              http://www.universite-lyon.fr/
6   - Léon Bérard cancer center       http://oncora1.lyon.fnclcc.fr
7   - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
8
9   This software is distributed WITHOUT ANY WARRANTY; without even
10   the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11   PURPOSE.  See the copyright notices for more information.
12
13   It is distributed under dual licence
14
15   - BSD        See included LICENSE.txt file
16   - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17 ======================================================================-====*/
18 #ifndef CLITKIMAGEARITHMGENERICFILTER_TXX
19 #define CLITKIMAGEARITHMGENERICFILTER_TXX
20 namespace clitk
21 {
22
23 //--------------------------------------------------------------------
24 template<class args_info_type>
25 ImageArithmGenericFilter<args_info_type>::ImageArithmGenericFilter()
26   :ImageToImageGenericFilter<Self>("ImageArithmGenericFilter"),mTypeOfOperation(0)
27 {
28   InitializeImageType<2>();
29   InitializeImageType<3>();
30   InitializeImageType<4>();
31   mIsOperationUseASecondImage = false;
32   mOverwriteInputImage = true;
33 }
34 //--------------------------------------------------------------------
35
36
37 //--------------------------------------------------------------------
38 template<class args_info_type>
39 template<unsigned int Dim>
40 void ImageArithmGenericFilter<args_info_type>::InitializeImageType()
41 {
42   ADD_DEFAULT_IMAGE_TYPES(Dim);
43 }
44 //--------------------------------------------------------------------
45
46
47 //--------------------------------------------------------------------
48 template<class args_info_type>
49 void ImageArithmGenericFilter<args_info_type>::EnableOverwriteInputImage(bool b)
50 {
51   mOverwriteInputImage = b;
52 }
53 //--------------------------------------------------------------------
54
55
56 //--------------------------------------------------------------------
57 template<class args_info_type>
58 void ImageArithmGenericFilter<args_info_type>::SetArgsInfo(const args_info_type & a)
59 {
60   mArgsInfo=a;
61
62   // Set value
63   SetIOVerbose(mArgsInfo.verbose_flag);
64   mTypeOfOperation = mArgsInfo.operation_arg;
65   mDefaultPixelValue = mArgsInfo.pixelValue_arg;
66   mScalar = mArgsInfo.scalar_arg;
67   mOutputIsFloat = mArgsInfo.setFloatOutput_flag;
68
69   if (mArgsInfo.imagetypes_flag) this->PrintAvailableImageTypes();
70
71   if (mArgsInfo.input1_given) AddInputFilename(mArgsInfo.input1_arg);
72   if (mArgsInfo.input2_given) {
73     mIsOperationUseASecondImage = true;
74     AddInputFilename(mArgsInfo.input2_arg);
75   }
76
77   if (mArgsInfo.output_given) SetOutputFilename(mArgsInfo.output_arg);
78
79   // Check type of operation (with scalar or with other image)
80   if ((mArgsInfo.input2_given) && (mArgsInfo.scalar_given)) {
81     std::cerr << "ERROR : you cannot provide both --scalar and --input2 option" << std::endl;
82     exit(-1);
83   }
84   if ((!mArgsInfo.input2_given) && (!mArgsInfo.scalar_given)) {
85     if (mArgsInfo.operation_arg < 5) {
86       std::cerr << "Such operation need the --scalar option." << std::endl;
87       exit(-1);
88     }
89   }
90 }
91 //--------------------------------------------------------------------
92
93
94 //--------------------------------------------------------------------
95 template<class args_info_type>
96 template<class ImageType>
97 void ImageArithmGenericFilter<args_info_type>::UpdateWithInputImageType()
98 {
99   // Read input1
100   typename ImageType::Pointer input1 = this->template GetInput<ImageType>(0);
101
102   // Set input image iterator
103   typedef itk::ImageRegionIterator<ImageType> IteratorType;
104   IteratorType it(input1, input1->GetLargestPossibleRegion());
105
106   // typedef input2
107   typename ImageType::Pointer input2 = this->template GetInput<ImageType>(1);
108   IteratorType it2;
109
110   if (mIsOperationUseASecondImage) {
111     // Read input2
112     input2 = this->template GetInput<ImageType>(1);
113     // Set input image iterator
114     it2 = IteratorType(input2, input2->GetLargestPossibleRegion());
115   }
116
117   // Check if overwrite and outputisfloat and pixeltype is not float -> do not overwrite
118   if (mOverwriteInputImage && mOutputIsFloat && (typeid(typename ImageType::PixelType) != typeid(float))) {
119     // std::cerr << "Warning. Could not use both mOverwriteInputImage and mOutputIsFloat, because input is "
120     //                     << typeid(PixelType).name()
121     //                     << std::endl;
122     mOverwriteInputImage = false;
123   }
124
125   // ---------------- Overwrite input Image ---------------------
126   if (mOverwriteInputImage) {
127     // Set output iterator (to input1)
128     IteratorType ito = IteratorType(input1, input1->GetLargestPossibleRegion());
129     if (mIsOperationUseASecondImage) ComputeImage(it, it2, ito);
130     else ComputeImage(it, ito);
131     this->template SetNextOutput<ImageType>(input1);
132   }
133
134   // ---------------- Create new output Image ---------------------
135   else {
136     if (mOutputIsFloat) {
137       // Create output image
138       typedef itk::Image<float,ImageType::ImageDimension> OutputImageType;
139       typename OutputImageType::Pointer output = OutputImageType::New();
140       output->SetRegions(input1->GetLargestPossibleRegion());
141       output->SetOrigin(input1->GetOrigin());
142       output->SetSpacing(input1->GetSpacing());
143       output->Allocate();
144       // Set output iterator
145       typedef itk::ImageRegionIterator<OutputImageType> IteratorOutputType;
146       IteratorOutputType ito = IteratorOutputType(output, output->GetLargestPossibleRegion());
147       if (mIsOperationUseASecondImage) ComputeImage(it, it2, ito);
148       else ComputeImage(it, ito);
149       this->template SetNextOutput<OutputImageType>(output);
150     } else {
151       // Create output image
152       typedef ImageType OutputImageType;
153       typename OutputImageType::Pointer output = OutputImageType::New();
154       output->SetRegions(input1->GetLargestPossibleRegion());
155       output->SetOrigin(input1->GetOrigin());
156       output->SetSpacing(input1->GetSpacing());
157       output->Allocate();
158       // Set output iterator
159       typedef itk::ImageRegionIterator<OutputImageType> IteratorOutputType;
160       IteratorOutputType ito = IteratorOutputType(output, output->GetLargestPossibleRegion());
161       if (mIsOperationUseASecondImage) ComputeImage(it, it2, ito);
162       else ComputeImage(it, ito);
163       this->template SetNextOutput<OutputImageType>(output);
164     }
165   }
166 }
167 //--------------------------------------------------------------------
168
169 //--------------------------------------------------------------------
170 template<class args_info_type>
171 template<class Iter1, class Iter2, class Iter3>
172 void  ImageArithmGenericFilter<args_info_type>::ComputeImage(Iter1 it1, Iter2 it2, Iter3 ito)
173 {
174   it1.GoToBegin();
175   it2.GoToBegin();
176   ito.GoToBegin();
177   typedef typename Iter3::PixelType PixelType;
178
179   switch (mTypeOfOperation) {
180   case 0: // Addition
181     while (!ito.IsAtEnd()) {
182       ito.Set(PixelTypeDownCast<double, PixelType>((double)it1.Get() + (double)it2.Get()) );
183       ++it1;
184       ++it2;
185       ++ito;
186     }
187     break;
188   case 1: // Multiply
189     while (!ito.IsAtEnd()) {
190       ito.Set(PixelTypeDownCast<double, PixelType>((double)it1.Get() * (double)it2.Get()) );
191       ++it1;
192       ++it2;
193       ++ito;
194     }
195     break;
196   case 2: // Divide
197     while (!ito.IsAtEnd()) {
198       if (it1.Get() != 0)
199         ito.Set(PixelTypeDownCast<double, PixelType>((double)it1.Get() / (double)it2.Get()));
200       else ito.Set(mDefaultPixelValue);
201       ++it1;
202       ++it2;
203       ++ito;
204     }
205     break;
206   case 3: // Max
207     while (!ito.IsAtEnd()) {
208       if (it1.Get() < it2.Get()) ito.Set(PixelTypeDownCast<double, PixelType>(it2.Get()));
209       ++it1;
210       ++it2;
211       ++ito;
212     }
213     break;
214   case 4: // Min
215     while (!ito.IsAtEnd()) {
216       if (it1.Get() > it2.Get()) ito.Set(PixelTypeDownCast<double, PixelType>(it2.Get()));
217       ++it1;
218       ++it2;
219       ++ito;
220     }
221     break;
222   case 5: // Absolute difference
223     while (!ito.IsAtEnd()) {
224       ito.Set(PixelTypeDownCast<double, PixelType>(fabs((double)it2.Get()-(double)it1.Get())));
225       ++it1;
226       ++it2;
227       ++ito;
228     }
229     break;
230   case 6: // Squared differences
231     while (!ito.IsAtEnd()) {
232       ito.Set(PixelTypeDownCast<double, PixelType>(pow((double)it1.Get()-(double)it2.Get(),2)));
233       ++it1;
234       ++it2;
235       ++ito;
236     }
237     break;
238   case 7: // Difference
239     while (!ito.IsAtEnd()) {
240       ito.Set(PixelTypeDownCast<double, PixelType>((double)it1.Get()-(double)it2.Get()));
241       ++it1;
242       ++it2;
243       ++ito;
244     }
245     break;
246   case 8: // Relative Difference
247     while (!ito.IsAtEnd()) {
248       if (it1.Get() != 0) ito.Set(PixelTypeDownCast<double, PixelType>(((double)it1.Get()-(double)it2.Get()))/(double)it1.Get());
249       else ito.Set(0.0);
250       ++it1;
251       ++it2;
252       ++ito;
253     }
254     break;
255   default: // error ?
256     std::cerr << "ERROR : the operation number (" << mTypeOfOperation << ") is not known." << std::endl;
257     exit(-1);
258   }
259 }
260 //--------------------------------------------------------------------
261
262
263 //--------------------------------------------------------------------
264 template<class args_info_type>
265 template<class Iter1, class Iter2>
266 void clitk::ImageArithmGenericFilter<args_info_type>::ComputeImage(Iter1 it, Iter2 ito)
267 {
268   ito.GoToBegin();
269   it.GoToBegin();
270   typedef typename Iter2::PixelType PixelType;
271
272   // Perform operation
273   switch (mTypeOfOperation) {
274   case 0: // Addition
275     while (!it.IsAtEnd()) {
276       ito.Set(clitk::PixelTypeDownCast<double, PixelType>((double)it.Get() + mScalar) );
277       ++it;
278       ++ito;
279     }
280     break;
281   case 1: // Multiply
282     while (!it.IsAtEnd()) {
283       ito.Set(PixelTypeDownCast<double, PixelType>((double)it.Get() * mScalar) );
284       ++it;
285       ++ito;
286     }
287     break;
288   case 2: // Inverse
289     while (!it.IsAtEnd()) {
290       if (it.Get() != 0)
291         ito.Set(PixelTypeDownCast<double, PixelType>(mScalar / (double)it.Get()));
292       else ito.Set(mDefaultPixelValue);
293       ++it;
294       ++ito;
295     }
296     break;
297   case 3: // Max
298     while (!it.IsAtEnd()) {
299       if (it.Get() < mScalar) ito.Set(PixelTypeDownCast<double, PixelType>(mScalar));
300       else ito.Set(PixelTypeDownCast<double, PixelType>(it.Get()));
301       ++it;
302       ++ito;
303     }
304     break;
305   case 4: // Min
306     while (!it.IsAtEnd()) {
307       if (it.Get() > mScalar) ito.Set(PixelTypeDownCast<double, PixelType>(mScalar));
308       else ito.Set(PixelTypeDownCast<double, PixelType>(it.Get()));
309       ++it;
310       ++ito;
311     }
312     break;
313   case 5: // Absolute value
314     while (!it.IsAtEnd()) {
315       if (it.Get() <= 0) ito.Set(PixelTypeDownCast<double, PixelType>(-it.Get()));
316       // <= zero to avoid warning for unsigned types
317       else ito.Set(PixelTypeDownCast<double, PixelType>(it.Get()));
318       ++it;
319       ++ito;
320     }
321     break;
322   case 6: // Squared value
323     while (!it.IsAtEnd()) {
324       ito.Set(PixelTypeDownCast<double, PixelType>((double)it.Get()*(double)it.Get()));
325       ++it;
326       ++ito;
327     }
328     break;
329   case 7: // Log
330     while (!it.IsAtEnd()) {
331       if (it.Get() > 0)
332         ito.Set(PixelTypeDownCast<double, PixelType>(log((double)it.Get())));
333       else ito.Set(mDefaultPixelValue);
334       ++it;
335       ++ito;
336     }
337     break;
338   case 8: // exp
339     while (!it.IsAtEnd()) {
340       ito.Set(PixelTypeDownCast<double, PixelType>(exp((double)it.Get())));
341       ++it;
342       ++ito;
343     }
344     break;
345   case 9: // sqrt
346     while (!it.IsAtEnd()) {
347       if (it.Get() > 0)
348         ito.Set(PixelTypeDownCast<double, PixelType>(sqrt((double)it.Get())));
349       else {
350         if (it.Get() ==0) ito.Set(0);
351         else ito.Set(mDefaultPixelValue);
352       }
353       ++it;
354       ++ito;
355     }
356     break;
357   default: // error ?
358     std::cerr << "ERROR : the operation number (" << mTypeOfOperation << ") is not known." << std::endl;
359     exit(-1);
360   }
361 }
362 //--------------------------------------------------------------------
363
364 } // end namespace
365
366 #endif  //#define CLITKIMAGEARITHMGENERICFILTER_TXX