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 * This file contains classes that can be used to drive an image-to-image
20 * type filter in or out of an itk pipeline for testing purposes.
21 */
22
23 #ifndef itkNullImageToImageFilterDriver_hxx
24 #define itkNullImageToImageFilterDriver_hxx
25
26 #include "itkPixelTraits.h"
27 #include "itkImage.h"
28 #include "itkImageToImageFilter.h"
29 #include "itkIndex.h"
30 #include <iostream>
31 #include <ctime>
32
33 namespace itk {
34
35 /**
36 * \class NullImageToImageFilterDriver
37 * \brief Drives an image-to-image type itk process object with null inputs and
38 * null outputs.
39 *
40 * Provides a non-pipeline framework for testing image-to-image
41 * filters. Allocates an input image and sets up an output image, then calls
42 * Update on the filter. Times the execution of the filter.
43 */
44
45 template <typename TInputImage, typename TOutputImage>
46 class NullImageToImageFilterDriver
47 {
48 public:
NullImageToImageFilterDriver()49 NullImageToImageFilterDriver():
50 m_Filter( nullptr )
51 {};
52
53 using ImageSizeType = typename TInputImage::SizeType;
54 using InputPixelType = typename TInputImage::PixelType;
55 enum {InputPixelDimension=PixelTraits<InputPixelType>::Dimension};
56
57 /**
58 * Set the image-to-image filter to drive.
59 */
SetFilter(ImageToImageFilter<TInputImage,TOutputImage> * filter)60 void SetFilter(ImageToImageFilter<TInputImage, TOutputImage> * filter)
61 { m_Filter = filter; }
62
63 /**
64 * Set the size of the input and output image.
65 */
SetImageSize(const ImageSizeType size)66 void SetImageSize(const ImageSizeType size)
67 { m_ImageSize = size; }
68
69 /**
70 * Drive the filter without using the itk pipeline.
71 */
72 void Execute();
73
74 protected:
75 struct DispatchBase {};
76 template<unsigned int VDimension>
77 struct Dispatch : public DispatchBase {};
78
79 void InitializePixel(InputPixelType &pixel);
80 void InitializePixel(const DispatchBase&, InputPixelType &pixel);
81 void InitializePixel(const Dispatch<1>&, InputPixelType &pixel);
82
83 private:
84 ImageToImageFilter<TInputImage, TOutputImage> *m_Filter;
85 ImageSizeType m_ImageSize;
86 };
87
88
89 template <typename TInputImage, typename TOutputImage>
90 void
91 NullImageToImageFilterDriver<TInputImage, TOutputImage>
InitializePixel(InputPixelType & pixel)92 ::InitializePixel(InputPixelType &pixel)
93 {
94 this->InitializePixel(Dispatch<InputPixelDimension>(), pixel);
95 }
96
97 template <typename TInputImage, typename TOutputImage>
98 void
99 NullImageToImageFilterDriver<TInputImage, TOutputImage>
InitializePixel(const DispatchBase &,InputPixelType & pixel)100 ::InitializePixel(const DispatchBase &, InputPixelType &pixel)
101 {
102 for (unsigned int i=0; i < InputPixelDimension; ++i)
103 {
104 pixel[i] = NumericTraits<typename PixelTraits<InputPixelType>::ValueType>::ZeroValue();
105 }
106 }
107
108 template <typename TInputImage, typename TOutputImage>
109 void
110 NullImageToImageFilterDriver<TInputImage, TOutputImage>
InitializePixel(const Dispatch<1> &,InputPixelType & pixel)111 ::InitializePixel(const Dispatch<1> &, InputPixelType &pixel)
112 {
113 pixel = NumericTraits<InputPixelType>::ZeroValue();
114 }
115
116 /**
117 * Drive the filter without using the itk pipeline
118 */
119 template <typename TInputImage, typename TOutputImage>
120 void
121 NullImageToImageFilterDriver<TInputImage, TOutputImage>
Execute()122 ::Execute()
123 {
124 enum { ImageDimension = TInputImage::ImageDimension };
125
126 // Set up input images
127 typename TInputImage::Pointer ip = TInputImage::New();
128 typename TOutputImage::IndexType index;
129 typename TOutputImage::RegionType region;
130
131 for (unsigned int i = 0; i < ImageDimension; ++i) index[i] = 0;
132 region.SetSize( m_ImageSize );
133 region.SetIndex( index);
134
135 // Allocate the input
136 ip->SetLargestPossibleRegion( region );
137 ip->SetBufferedRegion(region);
138 ip->SetRequestedRegion(region);
139 ip->Allocate();
140
141 // Construct a pixel to fill the image
142 InputPixelType pixel;
143 this->InitializePixel(pixel);
144 ip->FillBuffer(pixel);
145
146 // Setup the filter
147 m_Filter->SetInput(ip);
148
149 // print out the output object so we can see it modified times and regions
150 // std::cout << "Output object before filter execution" << std::endl
151 // << m_Filter->GetOutput() << std::endl;
152
153 using ImageFilterType = ImageToImageFilter<TInputImage, TOutputImage>;
154 typename ImageFilterType::Pointer sourceBefore =
155 dynamic_cast< ImageFilterType * >( m_Filter->GetOutput()->GetSource().GetPointer() );
156
157 // Execute the filter
158 clock_t start = ::clock();
159 m_Filter->UpdateLargestPossibleRegion();
160 clock_t stop = ::clock();
161
162 // print out the output object so we can see it modified times and regions
163 std::cout << "Output object after filter execution" << std::endl
164 << m_Filter->GetOutput() << std::endl;
165
166 typename ImageFilterType::Pointer sourceAfter =
167 dynamic_cast< ImageFilterType * >( m_Filter->GetOutput()->GetSource().GetPointer() );
168
169 std::cout << sourceBefore.GetPointer() << ", " << sourceAfter.GetPointer() << std::endl;
170 if (sourceBefore != sourceAfter.GetPointer())
171 {
172 std::cout << std::endl << "Pipeline corrupt, filter output source different after execution." << std::endl;
173 }
174 else
175 {
176 std::cout << std::endl << "Pipeline intact" << std::endl;
177 }
178
179 std::cout << "Execution time was approximately " << (stop - start)
180 << " clock cycles." << std::endl;
181 }
182
183 } // end namespace itk
184 #endif
185