1 /*============================================================================
3 The Medical Imaging Interaction Toolkit (MITK)
5 Copyright (c) German Cancer Research Center (DKFZ)
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
11 ============================================================================*/
13 #ifndef IMAGETOITK_TXX_INCLUDED_C1C2FCD2
14 #define IMAGETOITK_TXX_INCLUDED_C1C2FCD2
16 #include "itkImportMitkImageContainer.h"
17 #include "mitkBaseProcess.h"
18 #include "mitkException.h"
19 #include "mitkImageReadAccessor.h"
20 #include "mitkImageToItk.h"
21 #include "mitkImageWriteAccessor.h"
25 template <typename TImageType>
26 struct SetLengthHelper
28 SetLengthHelper(TImageType *in) { m_Image = in; }
33 template <typename T, unsigned int VDimension>
34 struct SetLengthHelper<itk::Image<T, VDimension>>
36 typedef itk::Image<T, VDimension> TImageType;
38 SetLengthHelper(TImageType *in) { m_Image = in; }
39 void SetVectorLength(size_t) {}
44 template <typename T, unsigned int VDimension>
45 struct SetLengthHelper<itk::VectorImage<T, VDimension>>
47 typedef itk::VectorImage<T, VDimension> TImageType;
49 SetLengthHelper(TImageType *in) { m_Image = in; }
50 void SetVectorLength(size_t len) { m_Image->SetVectorLength(len); }
55 template <class TOutputImage>
56 void mitk::ImageToItk<TOutputImage>::SetInput(mitk::Image *input)
58 this->SetInput(static_cast<const Image *>(input));
62 template <class TOutputImage>
63 void mitk::ImageToItk<TOutputImage>::SetInput(const mitk::Image *input)
65 this->CheckInput(input);
66 // Process object is not const-correct so the const_cast is required here
67 itk::ProcessObject::PushFrontInput(input);
71 template <class TOutputImage>
72 mitk::Image *mitk::ImageToItk<TOutputImage>::GetInput(void)
74 if (this->GetNumberOfInputs() < 1)
79 return static_cast<mitk::Image *>(itk::ProcessObject::GetInput(0));
82 template <class TOutputImage>
83 const mitk::Image *mitk::ImageToItk<TOutputImage>::GetInput() const
85 if (this->GetNumberOfInputs() < 1)
90 return static_cast<const mitk::Image *>(itk::ProcessObject::GetInput(0));
93 template <class TOutputImage>
94 void mitk::ImageToItk<TOutputImage>::GenerateData()
97 mitk::Image::Pointer input = this->GetInput();
98 typename Superclass::OutputImageType::Pointer output = this->GetOutput();
100 unsigned long noBytes = input->GetDimension(0);
101 for (unsigned int i = 1; i < TOutputImage::GetImageDimension(); ++i)
103 noBytes = noBytes * input->GetDimension(i);
105 const mitk::PixelType pixelType = input->GetPixelType();
106 if (pixelType.GetPixelType() == itk::ImageIOBase::VECTOR)
108 noBytes *= pixelType.GetNumberOfComponents();
109 SetLengthHelper<typename Superclass::OutputImageType> helper(output.GetPointer());
110 helper.SetVectorLength(pixelType.GetNumberOfComponents());
113 std::unique_ptr<mitk::ImageAccessorBase> imageAccess;
116 imageAccess.reset(new mitk::ImageReadAccessor(input, nullptr, m_Options));
120 imageAccess.reset(new mitk::ImageWriteAccessor(input, nullptr, m_Options));
123 // hier wird momentan wohl nur der erste Channel verwendet??!!
124 if (imageAccess->GetData() == nullptr)
126 itkWarningMacro(<< "no image data to import in ITK image");
128 RegionType bufferedRegion;
129 output->SetBufferedRegion(bufferedRegion);
135 itkDebugMacro("copyMem ...");
139 memcpy(output->GetBufferPointer(), imageAccess->GetData(), sizeof(InternalPixelType) * noBytes);
143 itkDebugMacro("do not copyMem ...");
144 typedef itk::ImportMitkImageContainer<itk::SizeValueType, InternalPixelType> ImportContainerType;
145 typename ImportContainerType::Pointer import;
147 import = ImportContainerType::New();
148 import->Initialize();
150 itkDebugMacro(<< "size of container = " << import->Size());
151 // import->SetImageDataItem(m_ImageDataItem);
152 import->SetImageAccessor(imageAccess.release(), sizeof(InternalPixelType) * noBytes);
154 output->SetPixelContainer(import);
155 itkDebugMacro(<< "size of container = " << import->Size());
159 template <class TOutputImage>
160 void mitk::ImageToItk<TOutputImage>::UpdateOutputInformation()
162 mitk::Image::Pointer input = this->GetInput();
163 if (input.IsNotNull() && (input->GetSource().IsNotNull()) && input->GetSource()->Updating())
165 typename Superclass::OutputImageType::Pointer output = this->GetOutput();
166 unsigned long t1 = input->GetUpdateMTime() + 1;
167 if (t1 > this->m_OutputInformationMTime.GetMTime())
169 output->SetPipelineMTime(t1);
171 this->GenerateOutputInformation();
173 this->m_OutputInformationMTime.Modified();
177 Superclass::UpdateOutputInformation();
180 template <class TOutputImage>
181 void mitk::ImageToItk<TOutputImage>::GenerateOutputInformation()
183 mitk::Image::ConstPointer input = this->GetInput();
184 typename Superclass::OutputImageType::Pointer output = this->GetOutput();
186 // allocate size, origin, spacing, direction in types of output image
188 const unsigned int itkDimMin3 = (TOutputImage::ImageDimension > 3 ? TOutputImage::ImageDimension : 3);
189 const unsigned int itkDimMax3 = (TOutputImage::ImageDimension < 3 ? TOutputImage::ImageDimension : 3);
190 typename Superclass::OutputImageType::PointType::ValueType origin[itkDimMin3];
191 typename Superclass::OutputImageType::SpacingType::ComponentType spacing[itkDimMin3];
192 typename Superclass::OutputImageType::DirectionType direction;
194 // copy as much information as possible into size and spacing
196 for (i = 0; i < itkDimMax3; ++i)
198 size[i] = input->GetDimension(i);
199 spacing[i] = input->GetGeometry()->GetSpacing()[i];
201 for (; i < TOutputImage::ImageDimension; ++i)
204 size[i] = input->GetDimension(i);
208 // build region from size
212 region.SetIndex(start);
213 region.SetSize(size);
215 // copy as much information as possible into origin
216 const mitk::Point3D &mitkorigin = input->GetGeometry()->GetOrigin();
217 itk2vtk(mitkorigin, origin);
219 // copy as much information as possible into direction
220 direction.SetIdentity();
222 const AffineTransform3D::MatrixType &matrix = input->GetGeometry()->GetIndexToWorldTransform()->GetMatrix();
224 /// \warning 2D MITK images could have a 3D rotation, since they have a 3x3 geometry matrix.
225 /// If it is only a rotation around the axial plane normal, it can be express with a 2x2 matrix.
226 /// In this case, the ITK image conservs this information and is identical to the MITK image!
227 /// If the MITK image contains any other rotation, the ITK image will have no rotation at all.
228 /// Spacing is of course conserved in both cases.
230 // the following loop devides by spacing now to normalize columns.
231 // counterpart of InitializeByItk in mitkImage.h line 372 of revision 15092.
233 // Check if information is lost
234 if (TOutputImage::ImageDimension <= 2)
236 if ((TOutputImage::ImageDimension == 2) && ((matrix[0][2] != 0) || (matrix[1][2] != 0) || (matrix[2][0] != 0) ||
237 (matrix[2][1] != 0) || ((matrix[2][2] != 1) && (matrix[2][2] != -1))))
239 // The 2D MITK image contains 3D rotation information.
240 // This cannot be expressed in a 2D ITK image, so the ITK image will have no rotation
244 // The 2D MITK image can be converted to an 2D ITK image without information loss!
245 for (i = 0; i < itkDimMax3; ++i)
246 for (j = 0; j < itkDimMax3; ++j)
247 direction[i][j] = matrix[i][j] / spacing[j];
252 // Normal 3D image. Conversion possible without problem!
253 for (i = 0; i < itkDimMax3; ++i)
254 for (j = 0; j < itkDimMax3; ++j)
255 direction[i][j] = matrix[i][j] / spacing[j];
258 // set information into output image
259 output->SetRegions(region);
260 output->SetOrigin(origin);
261 output->SetSpacing(spacing);
262 output->SetDirection(direction);
265 template <class TOutputImage>
266 void mitk::ImageToItk<TOutputImage>::CheckInput(const mitk::Image *input) const
268 if (input == nullptr)
270 itkExceptionMacro(<< "image is null");
272 if (input->GetDimension() != TOutputImage::GetImageDimension())
274 itkExceptionMacro(<< "image has dimension " << input->GetDimension() << " instead of "
275 << TOutputImage::GetImageDimension());
278 if (!(input->GetPixelType() == mitk::MakePixelType<TOutputImage>(input->GetPixelType().GetNumberOfComponents())))
280 itkExceptionMacro(<< "image has wrong pixel type ");
284 template <class TOutputImage>
285 void mitk::ImageToItk<TOutputImage>::PrintSelf(std::ostream &os, itk::Indent indent) const
287 Superclass::PrintSelf(os, indent);
290 #endif // IMAGETOITK_TXX_INCLUDED_C1C2FCD2