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