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