1 /*
2  * Medical Image Registration ToolKit (MIRTK)
3  *
4  * Copyright 2008-2015 Imperial College London
5  * Copyright 2008-2015 Daniel Rueckert, Julia Schnabel
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 
20 #include "mirtk/ImageToImage.h"
21 
22 #include "mirtk/Memory.h"
23 #include "mirtk/Parallel.h"
24 #include "mirtk/Profiling.h"
25 
26 
27 namespace mirtk {
28 
29 // =============================================================================
30 // Multi-threaded execution
31 // =============================================================================
32 
33 // -----------------------------------------------------------------------------
34 template <class VoxelType>
35 class MultiThreadedImageToImage
36 {
37   /// Time frame to transform
38   int _t;
39 
40   /// Pointer to image transformation class
41   ImageToImage<VoxelType> *_Filter;
42 
43 public:
44 
MultiThreadedImageToImage(ImageToImage<VoxelType> * filter,int t)45   MultiThreadedImageToImage(ImageToImage<VoxelType> *filter, int t) {
46     _t = t;
47     _Filter = filter;
48   }
49 
operator ()(const blocked_range<int> & r) const50   void operator()(const blocked_range<int> &r) const
51   {
52     for (int k = r.begin(); k != r.end(); ++k)
53     for (int j = 0; j < _Filter->Input()->Y(); ++j)
54     for (int i = 0; i < _Filter->Input()->X(); ++i) {
55       _Filter->Output()->PutAsDouble(i, j, k, _t, _Filter->Run(i, j, k, _t));
56     }
57   }
58 };
59 
60 // =============================================================================
61 // Construction/Destruction
62 // =============================================================================
63 
64 // -----------------------------------------------------------------------------
65 template <class VoxelType>
ImageToImage()66 ImageToImage<VoxelType>::ImageToImage()
67 :
68   _Input(NULL),
69   _Output(NULL),
70   _Buffer(NULL)
71 {
72 }
73 
74 // -----------------------------------------------------------------------------
75 template <class VoxelType>
~ImageToImage()76 ImageToImage<VoxelType>::~ImageToImage()
77 {
78 }
79 
80 // =============================================================================
81 // Execution
82 // =============================================================================
83 
84 // ---------------------------------------------------------------------------
85 template <class VoxelType>
RequiresBuffering() const86 bool ImageToImage<VoxelType>::RequiresBuffering() const
87 {
88   return true;
89 }
90 
91 // ---------------------------------------------------------------------------
92 template <class VoxelType>
Initialize(bool initialize_output)93 void ImageToImage<VoxelType>::Initialize(bool initialize_output)
94 {
95   // Check inputs and outputs
96   if (_Input == NULL) {
97     cerr << this->NameOfClass() << "::Initialize: Filter has no input" << endl;
98     exit(1);
99   }
100 
101   if (_Output == NULL) {
102     cerr << this->NameOfClass() << "::Initialize: Filter has no output" << endl;
103     exit(1);
104   }
105 
106   if (_Input->IsEmpty()) {
107     cerr << this->NameOfClass() << "::Initialize: Input is empty" << endl;
108     exit(1);
109   }
110 
111   // Allocate buffer output if needed
112   if (this->RequiresBuffering()) {
113     if (_Input == _Output) {
114       _Buffer = _Output;
115       _Output = new GenericImage<VoxelType>;
116     } else {
117       _Buffer = NULL;
118     }
119   }
120 
121   // Make sure that output has the correct dimensions
122   if (initialize_output && _Input != _Output) {
123     _Output->Initialize(_Input->Attributes());
124   }
125 }
126 
127 // ---------------------------------------------------------------------------
128 template <class VoxelType>
Initialize()129 void ImageToImage<VoxelType>::Initialize()
130 {
131   Initialize(true);
132 }
133 
134 // ---------------------------------------------------------------------------
135 template <class VoxelType>
Finalize()136 void ImageToImage<VoxelType>::Finalize()
137 {
138   if (_Buffer) {
139     *_Buffer = *_Output;
140     swap(_Buffer, _Output);
141     Delete(_Buffer);
142   }
143 }
144 
145 // ---------------------------------------------------------------------------
146 template <class VoxelType>
Run(int,int,int,int)147 double ImageToImage<VoxelType>::Run(int, int, int, int)
148 {
149   cerr << "Filter " << this->NameOfClass() << " has no Run(int, int, int) ";
150   cerr << "member function. Using ImageToImage::Run." << endl;
151   return 0;
152 }
153 
154 // ---------------------------------------------------------------------------
155 template <class VoxelType>
Run()156 void ImageToImage<VoxelType>::Run()
157 {
158   MIRTK_START_TIMING();
159 
160   this->Initialize();
161 
162   for (int t = 0; t < _Input->T(); ++t) {
163     MultiThreadedImageToImage<VoxelType> eval(this, t);
164     parallel_for(blocked_range<int>(0, _Output->Z(), 1), eval);
165   }
166 
167   this->Finalize();
168 
169   MIRTK_DEBUG_TIMING(5, this->NameOfClass());
170 }
171 
172 // =============================================================================
173 // Explicit template instantiations
174 // =============================================================================
175 
176 template class ImageToImage<char>;
177 template class ImageToImage<unsigned char>;
178 template class ImageToImage<short>;
179 template class ImageToImage<unsigned short>;
180 template class ImageToImage<int>;
181 template class ImageToImage<unsigned int>;
182 template class ImageToImage<float>;
183 template class ImageToImage<double>;
184 template class ImageToImage<Float3>;
185 template class ImageToImage<Double3>;
186 template class ImageToImage<Float9>;
187 template class ImageToImage<Double9>;
188 
189 
190 } // namespace mirtk
191