1 /*=========================================================================
2  *
3  *  Copyright Insight Software Consortium
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18 
19 #include "itkMath.h"
20 #include "itkTanImageFilter.h"
21 #include "itkTanImageAdaptor.h"
22 #include "itkSubtractImageFilter.h"
23 #include "itkTestingMacros.h"
24 
itkTanImageFilterAndAdaptorTest(int,char * [])25 int itkTanImageFilterAndAdaptorTest( int, char* [] )
26 {
27 
28   // Define the dimension of the images
29   constexpr unsigned int ImageDimension = 3;
30 
31   // Declare the pixel types of the images
32   using PixelType = float;
33 
34   // Declare the types of the images
35   using InputImageType = itk::Image< PixelType, ImageDimension >;
36   using OutputImageType = itk::Image< PixelType, ImageDimension >;
37 
38   // Declare appropriate Iterator types for each image
39   using InputIteratorType = itk::ImageRegionIteratorWithIndex<InputImageType>;
40   using OutputIteratorType = itk::ImageRegionIteratorWithIndex<OutputImageType>;
41 
42   // Declare the type of the index to access images
43   using IndexType = itk::Index< ImageDimension >;
44 
45   // Declare the type of the size
46   using SizeType = itk::Size< ImageDimension >;
47 
48   // Declare the type of the Region
49   using RegionType = itk::ImageRegion< ImageDimension >;
50 
51   // Create the input image
52   InputImageType::Pointer inputImage = InputImageType::New();
53 
54   // Define its size, and start index
55   SizeType size;
56   size[0] = 2;
57   size[1] = 2;
58   size[2] = 2;
59 
60   IndexType start;
61   start[0] = 0;
62   start[1] = 0;
63   start[2] = 0;
64 
65   RegionType region;
66   region.SetIndex( start );
67   region.SetSize( size );
68 
69   // Initialize the input image
70   inputImage->SetLargestPossibleRegion( region );
71   inputImage->SetBufferedRegion( region );
72   inputImage->SetRequestedRegion( region );
73   inputImage->Allocate();
74 
75   // Create one iterator for the input image (this is a light object)
76   InputIteratorType it( inputImage, inputImage->GetBufferedRegion() );
77 
78   // Initialize the content of the input image
79   const double value = itk::Math::pi / 6.0;
80   it.GoToBegin();
81   while( !it.IsAtEnd() )
82     {
83     it.Set( value );
84     ++it;
85     }
86 
87   // Declare the type for the Tan filter
88   using FilterType = itk::TanImageFilter< InputImageType,
89                                OutputImageType >;
90 
91   // Create the filter
92   FilterType::Pointer filter = FilterType::New();
93 
94   EXERCISE_BASIC_OBJECT_METHODS( filter, TanImageFilter,
95     UnaryGeneratorImageFilter );
96 
97   // Set the input image
98   filter->SetInput( inputImage );
99 
100 
101   // Execute the filter
102   filter->Update();
103 
104   // Get the filter output
105   OutputImageType::Pointer outputImage = filter->GetOutput();
106 
107   // Create an iterator for going through the image output
108   OutputIteratorType ot( outputImage, outputImage->GetRequestedRegion() );
109 
110   // Check the content of the result image
111   const OutputImageType::PixelType epsilon = 1e-6;
112   ot.GoToBegin();
113   it.GoToBegin();
114   while( !ot.IsAtEnd() )
115     {
116     const InputImageType::PixelType  input  = it.Get();
117     const OutputImageType::PixelType output = ot.Get();
118     const OutputImageType::PixelType tangent = std::tan(input);
119     if( !itk::Math::FloatAlmostEqual( tangent, output, 10, epsilon ) )
120       {
121       std::cerr.precision( static_cast< int >( itk::Math::abs( std::log10( epsilon ) ) ) );
122       std::cerr << "Error " << std::endl;
123       std::cerr << " std::tan( " << input << ") = " << tangent << std::endl;
124       std::cerr << " differs from " << output;
125       std::cerr << " by more than " << epsilon << std::endl;
126       return EXIT_FAILURE;
127       }
128     ++ot;
129     ++it;
130     }
131 
132   //
133   // Test the itk::TanImageAdaptor
134 
135   using AdaptorType = itk::TanImageAdaptor< InputImageType,
136                           OutputImageType::PixelType >;
137 
138   AdaptorType::Pointer tanAdaptor = AdaptorType::New();
139 
140   EXERCISE_BASIC_OBJECT_METHODS( tanAdaptor, TanImageAdaptor,
141     ImageAdaptor );
142 
143   tanAdaptor->SetImage( inputImage );
144 
145   using DiffFilterType = itk::SubtractImageFilter<
146                         OutputImageType,
147                         AdaptorType,
148                         OutputImageType >;
149 
150   DiffFilterType::Pointer diffFilter = DiffFilterType::New();
151 
152   diffFilter->SetInput1( outputImage );
153   diffFilter->SetInput2( tanAdaptor );
154 
155   diffFilter->Update();
156 
157   // Get the filter output
158   OutputImageType::Pointer diffImage = diffFilter->GetOutput();
159 
160   // Check the content of the diff image
161   //
162 
163   // Create an iterator for going through the image output
164   OutputIteratorType dt( diffImage, diffImage->GetRequestedRegion() );
165 
166   dt.GoToBegin();
167   while( !dt.IsAtEnd() )
168     {
169     const OutputImageType::PixelType diff = dt.Get();
170     if( std::fabs( diff ) > epsilon )
171       {
172       std::cerr << "Error comparing results with Adaptors" << std::endl;
173       std::cerr << " difference = " << diff << std::endl;
174       std::cerr << " differs from 0 ";
175       std::cerr << " by more than " << epsilon << std::endl;
176       return EXIT_FAILURE;
177       }
178     ++dt;
179     }
180 
181   return EXIT_SUCCESS;
182 }
183