Orfeo Toolbox  3.16
itkImageSource.txx
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Insight Segmentation & Registration Toolkit
4  Module: $RCSfile: itkImageSource.txx,v $
5  Language: C++
6  Date: $Date: 2009-11-03 12:24:24 $
7  Version: $Revision: 1.69 $
8 
9  Copyright (c) Insight Software Consortium. All rights reserved.
10  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
11 
12  Portions of this code are covered under the VTK copyright.
13  See VTKCopyright.txt or http://www.kitware.com/VTKCopyright.htm for details.
14 
15  This software is distributed WITHOUT ANY WARRANTY; without even
16  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
17  PURPOSE. See the above copyright notices for more information.
18 
19 =========================================================================*/
20 #ifndef __itkImageSource_txx
21 #define __itkImageSource_txx
22 #include "itkImageSource.h"
23 
24 #include "vnl/vnl_math.h"
25 
26 namespace itk
27 {
28 
32 template<class TOutputImage>
35 {
36  // Create the output. We use static_cast<> here because we know the default
37  // output must be of type TOutputImage
38  typename TOutputImage::Pointer output
39  = static_cast<TOutputImage*>(this->MakeOutput(0).GetPointer());
41  this->ProcessObject::SetNthOutput(0, output.GetPointer());
42 
43  // Set the default behavior of an image source to NOT release its
44  // output bulk data prior to GenerateData() in case that bulk data
45  // can be reused (an thus avoid a costly deallocate/allocate cycle).
46  this->ReleaseDataBeforeUpdateFlagOff();
47 }
48 
52 template<class TOutputImage>
55 ::MakeOutput(unsigned int)
56 {
57  return static_cast<DataObject*>(TOutputImage::New().GetPointer());
58 }
59 
63 template<class TOutputImage>
67 {
68  if (this->GetNumberOfOutputs() < 1)
69  {
70  return 0;
71  }
72 
73  // we assume that the first output is of the templated type
74  return static_cast<TOutputImage*>
75  (this->ProcessObject::GetOutput(0));
76 }
77 
78 
82 template<class TOutputImage>
85 ::GetOutput(unsigned int idx)
86 {
87  TOutputImage* out = dynamic_cast<TOutputImage*>
88  (this->ProcessObject::GetOutput(idx));
89  if ( out == NULL ) {
90  itkWarningMacro ( << "dynamic_cast to output type failed" );
91  }
92  return out;
93 }
94 
98 template<class TOutputImage>
99 void
102 {
103  this->GraftNthOutput(0, graft);
104 }
105 
106 
110 template<class TOutputImage>
111 void
113 ::GraftNthOutput(unsigned int idx, DataObject *graft)
114 {
115  if ( idx >= this->GetNumberOfOutputs() )
116  {
117  itkExceptionMacro(<<"Requested to graft output " << idx <<
118  " but this filter only has " << this->GetNumberOfOutputs() << " Outputs.");
119  }
120 
121  if ( !graft )
122  {
123  itkExceptionMacro(<<"Requested to graft output that is a NULL pointer" );
124  }
125 
126  // we use the process object method since all out output may not be
127  // of the same type
128  DataObject * output = this->ProcessObject::GetOutput(idx);
129 
130  // Call GraftImage to copy meta-information, regions, and the pixel container
131  output->Graft( graft );
132 }
133 
134 //----------------------------------------------------------------------------
135 template <class TOutputImage>
136 int
138 ::SplitRequestedRegion(int i, int num, OutputImageRegionType& splitRegion)
139 {
140  // Get the output pointer
141  OutputImageType * outputPtr = this->GetOutput();
142  const typename TOutputImage::SizeType& requestedRegionSize
143  = outputPtr->GetRequestedRegion().GetSize();
144 
145  int splitAxis;
146  typename TOutputImage::IndexType splitIndex;
147  typename TOutputImage::SizeType splitSize;
148 
149  // Initialize the splitRegion to the output requested region
150  splitRegion = outputPtr->GetRequestedRegion();
151  splitIndex = splitRegion.GetIndex();
152  splitSize = splitRegion.GetSize();
153 
154  // split on the outermost dimension available
155  splitAxis = outputPtr->GetImageDimension() - 1;
156  while (requestedRegionSize[splitAxis] == 1)
157  {
158  --splitAxis;
159  if (splitAxis < 0)
160  { // cannot split
161  itkDebugMacro(" Cannot Split");
162  return 1;
163  }
164  }
165 
166  // determine the actual number of pieces that will be generated
167  typename TOutputImage::SizeType::SizeValueType range = requestedRegionSize[splitAxis];
168  int valuesPerThread = Math::Ceil<int>(range/(double)num);
169  int maxThreadIdUsed = Math::Ceil<int>(range/(double)valuesPerThread) - 1;
170 
171  // Split the region
172  if (i < maxThreadIdUsed)
173  {
174  splitIndex[splitAxis] += i*valuesPerThread;
175  splitSize[splitAxis] = valuesPerThread;
176  }
177  if (i == maxThreadIdUsed)
178  {
179  splitIndex[splitAxis] += i*valuesPerThread;
180  // last thread needs to process the "rest" dimension being split
181  splitSize[splitAxis] = splitSize[splitAxis] - i*valuesPerThread;
182  }
183 
184  // set the split region ivars
185  splitRegion.SetIndex( splitIndex );
186  splitRegion.SetSize( splitSize );
187 
188  itkDebugMacro(" Split Piece: " << splitRegion );
189 
190  return maxThreadIdUsed + 1;
191 }
192 
193 //----------------------------------------------------------------------------
194 template <class TOutputImage>
195 void
198 {
199  typedef ImageBase<OutputImageDimension> ImageBaseType;
200  typename ImageBaseType::Pointer outputPtr;
201 
202  // Allocate the output memory
203  for (unsigned int i=0; i < this->GetNumberOfOutputs(); i++)
204  {
205 
206  // Check whether the output is an image of the appropriate
207  // dimension (use ProcessObject's version of the GetInput()
208  // method since it returns the input as a pointer to a
209  // DataObject as opposed to the subclass version which
210  // static_casts the input to an TInputImage).
211  outputPtr = dynamic_cast< ImageBaseType *>( this->ProcessObject::GetOutput(i) );
212 
213  if ( outputPtr )
214  {
215  outputPtr->SetBufferedRegion( outputPtr->GetRequestedRegion() );
216  outputPtr->Allocate();
217  }
218  }
219 }
220 
221 //----------------------------------------------------------------------------
222 template <class TOutputImage>
223 void
226 {
227  // Call a method that can be overriden by a subclass to allocate
228  // memory for the filter's outputs
229  this->AllocateOutputs();
230 
231  // Call a method that can be overridden by a subclass to perform
232  // some calculations prior to splitting the main computations into
233  // separate threads
234  this->BeforeThreadedGenerateData();
235 
236  // Set up the multithreaded processing
237  ThreadStruct str;
238  str.Filter = this;
239 
240  this->GetMultiThreader()->SetNumberOfThreads(this->GetNumberOfThreads());
241  this->GetMultiThreader()->SetSingleMethod(this->ThreaderCallback, &str);
242 
243  // multithread the execution
244  this->GetMultiThreader()->SingleMethodExecute();
245 
246  // Call a method that can be overridden by a subclass to perform
247  // some calculations after all the threads have completed
248  this->AfterThreadedGenerateData();
249 
250 }
251 
252 
253 //----------------------------------------------------------------------------
254 // The execute method created by the subclass.
255 template <class TOutputImage>
256 void
259  int)
260 {
261 // The following code is equivalent to:
262 // itkExceptionMacro("subclass should override this method!!!");
263 // The ExceptionMacro is not used because gcc warns that a
264 // 'noreturn' function does return
265  OStringStream message;
266  message << "itk::ERROR: " << this->GetNameOfClass()
267  << "(" << this << "): " << "Subclass should override this method!!!";
268  ExceptionObject e_(__FILE__, __LINE__, message.str().c_str(),ITK_LOCATION);
269  throw e_;
270 }
271 
272 // Callback routine used by the threading library. This routine just calls
273 // the ThreadedGenerateData method after setting the correct region for this
274 // thread.
275 template <class TOutputImage>
278 ::ThreaderCallback( void *arg )
279 {
280  ThreadStruct *str;
281  int total, threadId, threadCount;
282 
283  threadId = ((MultiThreader::ThreadInfoStruct *)(arg))->ThreadID;
284  threadCount = ((MultiThreader::ThreadInfoStruct *)(arg))->NumberOfThreads;
285 
286  str = (ThreadStruct *)(((MultiThreader::ThreadInfoStruct *)(arg))->UserData);
287 
288  // execute the actual method with appropriate output region
289  // first find out how many pieces extent can be split into.
290  typename TOutputImage::RegionType splitRegion;
291  total = str->Filter->SplitRequestedRegion(threadId, threadCount,
292  splitRegion);
293 
294  if (threadId < total)
295  {
296  str->Filter->ThreadedGenerateData(splitRegion, threadId);
297  }
298  // else
299  // {
300  // otherwise don't use this thread. Sometimes the threads dont
301  // break up very well and it is just as efficient to leave a
302  // few threads idle.
303  // }
304 
306 }
307 
308 
309 } // end namespace itk
310 
311 #endif

Generated at Sat Feb 2 2013 23:44:50 for Orfeo Toolbox with doxygen 1.8.1.1