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