Medical Imaging Interaction Toolkit  2018.4.99-b585543d
Medical Imaging Interaction Toolkit
mitkImageSource.cpp
Go to the documentation of this file.
1 /*============================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
13 #include "mitkImageSource.h"
14 
17 
19 {
20  // Create the output. We use static_cast<> here because we know the default
21  // output must be of type TOutputImage
22  OutputImageType::Pointer output = static_cast<OutputImageType *>(this->MakeOutput(0).GetPointer());
23  Superclass::SetNumberOfRequiredOutputs(1);
24  Superclass::SetNthOutput(0, output.GetPointer());
25 }
26 
27 itk::DataObject::Pointer mitk::ImageSource::MakeOutput(DataObjectPointerArraySizeType /*idx*/)
28 {
29  return static_cast<itk::DataObject *>(mitk::Image::New().GetPointer());
30 }
31 
32 itk::DataObject::Pointer mitk::ImageSource::MakeOutput(const DataObjectIdentifierType &name)
33 {
34  itkDebugMacro("MakeOutput(" << name << ")");
35  if (this->IsIndexedOutputName(name))
36  {
37  return this->MakeOutput(this->MakeIndexFromOutputName(name));
38  }
39  return static_cast<itk::DataObject *>(mitk::Image::New().GetPointer());
40 }
41 
42 //----------------------------------------------------------------------------
43 unsigned int mitk::ImageSource::SplitRequestedRegion(unsigned int i,
44  unsigned int num,
45  OutputImageRegionType &splitRegion)
46 {
47  // Get the output pointer
48  OutputImageType *outputPtr = this->GetOutput();
49  const SlicedData::SizeType &requestedRegionSize = outputPtr->GetRequestedRegion().GetSize();
50 
51  int splitAxis;
52  SlicedData::IndexType splitIndex;
53  SlicedData::SizeType splitSize;
54 
55  // Initialize the splitRegion to the output requested region
56  splitRegion = outputPtr->GetRequestedRegion();
57  splitIndex = splitRegion.GetIndex();
58  splitSize = splitRegion.GetSize();
59 
60  // split on the outermost dimension available
61  splitAxis = outputPtr->GetDimension() - 1;
62  while (requestedRegionSize[splitAxis] == 1)
63  {
64  --splitAxis;
65  if (splitAxis < 0)
66  { // cannot split
67  itkDebugMacro(" Cannot Split");
68  return 1;
69  }
70  }
71 
72  // determine the actual number of pieces that will be generated
73  SlicedData::SizeType::SizeValueType range = requestedRegionSize[splitAxis];
74  auto valuesPerThread = itk::Math::Ceil<unsigned int>(range / (double)num);
75  unsigned int maxThreadIdUsed = itk::Math::Ceil<unsigned int>(range / (double)valuesPerThread) - 1;
76 
77  // Split the region
78  if (i < maxThreadIdUsed)
79  {
80  splitIndex[splitAxis] += i * valuesPerThread;
81  splitSize[splitAxis] = valuesPerThread;
82  }
83  if (i == maxThreadIdUsed)
84  {
85  splitIndex[splitAxis] += i * valuesPerThread;
86  // last thread needs to process the "rest" dimension being split
87  splitSize[splitAxis] = splitSize[splitAxis] - i * valuesPerThread;
88  }
89 
90  // set the split region ivars
91  splitRegion.SetIndex(splitIndex);
92  splitRegion.SetSize(splitSize);
93 
94  itkDebugMacro(" Split Piece: " << splitRegion);
95 
96  return maxThreadIdUsed + 1;
97 }
98 
99 //----------------------------------------------------------------------------
100 
102 {
103  OutputImagePointer outputPtr;
104 
105  // Allocate the output memory
106  for (unsigned int i = 0; i < this->GetNumberOfOutputs(); i++)
107  {
108  outputPtr = this->GetOutput(i);
109  // outputPtr->SetBufferedRegion(outputPtr->GetRequestedRegion()); @FIXME???
110  // outputPtr->Allocate(); @FIXME???
111  }
112 }
113 
114 //----------------------------------------------------------------------------
115 
117 {
118  // Call a method that can be overriden by a subclass to allocate
119  // memory for the filter's outputs
120  this->AllocateOutputs();
121 
122  // Call a method that can be overridden by a subclass to perform
123  // some calculations prior to splitting the main computations into
124  // separate threads
126 
127  // Set up the multithreaded processing
128  ThreadStruct str;
129  str.Filter = this;
130 
131  this->GetMultiThreader()->SetNumberOfThreads(this->GetNumberOfThreads());
132  this->GetMultiThreader()->SetSingleMethod(this->ThreaderCallback, &str);
133 
134  // multithread the execution
135  this->GetMultiThreader()->SingleMethodExecute();
136 
137  // Call a method that can be overridden by a subclass to perform
138  // some calculations after all the threads have completed
140 }
141 
142 //----------------------------------------------------------------------------
143 // The execute method created by the subclass.
144 
146 {
147  itkExceptionMacro("subclass should override this method!!!");
148 }
149 
150 // Callback routine used by the threading library. This routine just calls
151 // the ThreadedGenerateData method after setting the correct region for this
152 // thread.
153 
154 ITK_THREAD_RETURN_TYPE mitk::ImageSource::ThreaderCallback(void *arg)
155 {
156  ThreadStruct *str;
157  itk::ThreadIdType total, threadId, threadCount;
158 
159  threadId = ((itk::MultiThreader::ThreadInfoStruct *)(arg))->ThreadID;
160  threadCount = ((itk::MultiThreader::ThreadInfoStruct *)(arg))->NumberOfThreads;
161 
162  str = (ThreadStruct *)(((itk::MultiThreader::ThreadInfoStruct *)(arg))->UserData);
163 
164  // execute the actual method with appropriate output region
165  // first find out how many pieces extent can be split into.
166  SlicedData::RegionType splitRegion;
167  total = str->Filter->SplitRequestedRegion(threadId, threadCount, splitRegion);
168 
169  if (threadId < total)
170  {
171  str->Filter->ThreadedGenerateData(splitRegion, threadId);
172  }
173  // else
174  // {
175  // otherwise don't use this thread. Sometimes the threads dont
176  // break up very well and it is just as efficient to leave a
177  // few threads idle.
178  // }
179 
180  return ITK_THREAD_RETURN_VALUE;
181 }
182 
184 {
185  Superclass::PrepareOutputs();
186 }
187 
189 {
190  Update();
191  return GetOutput()->GetVtkImageData();
192 }
193 
194 const vtkImageData *mitk::ImageSource::GetVtkImageData() const
195 {
196  return GetOutput()->GetVtkImageData();
197 }
198 
Superclass of all classes generating Images (instances of class Image) as output. ...
itk::DataObject::DataObjectIdentifierType DataObjectIdentifierType
static ITK_THREAD_RETURN_TYPE ThreaderCallback(void *arg)
Static function used as a "callback" by the MultiThreader.
itk::DataObject::Pointer MakeOutput(DataObjectPointerArraySizeType idx) override
Make a DataObject of the correct type to used as the specified output.
virtual vtkImageData * GetVtkImageData()
static void Update(vtkPolyData *)
Definition: mitkSurface.cpp:31
void PrepareOutputs() override
This method is intentionally left blank.
virtual vtkImageData * GetVtkImageData(int t=0, int n=0)
Get a volume at a specific time t of channel n as a vtkImageData.
Definition: mitkImage.cpp:217
SlicedData::RegionType OutputImageRegionType
virtual void ThreadedGenerateData(const OutputImageRegionType &outputRegionForThread, itk::ThreadIdType threadId)
If an imaging filter can be implemented as a multithreaded algorithm, the filter will provide an impl...
void GenerateData() override
A version of GenerateData() specific for image processing filters.
itk::Size< RegionDimension > SizeType
virtual unsigned int SplitRequestedRegion(unsigned int i, unsigned int num, OutputImageRegionType &splitRegion)
Split the output&#39;s RequestedRegion into "num" pieces, returning region "i" as "splitRegion".
virtual void BeforeThreadedGenerateData()
If an imaging filter needs to perform processing after the buffer has been allocated but before threa...
Internal structure used for passing image data into the threading library.
unsigned int GetDimension() const
Get dimension of the image.
Definition: mitkImage.cpp:106
itk::ImageRegion< RegionDimension > RegionType
Image class for storing images.
Definition: mitkImage.h:72
virtual const RegionType & GetRequestedRegion() const
static Pointer New()
virtual void AfterThreadedGenerateData()
If an imaging filter needs to perform processing after all processing threads have completed...
virtual void AllocateOutputs()
The GenerateData method normally allocates the buffers for all of the outputs of a filter...
OutputType * GetOutput()
Get the output data of this image source object.
#define mitkBaseDataSourceGetOutputDefinitions(className)