1 /*===================================================================
3 The Medical Imaging Interaction Toolkit (MITK)
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 See LICENSE.txt or http://www.mitk.org for details.
15 ===================================================================*/
17 #ifndef IMAGETOITK_TXX_INCLUDED_C1C2FCD2
18 #define IMAGETOITK_TXX_INCLUDED_C1C2FCD2
20 #include "itkImportMitkImageContainer.h"
21 #include "mitkBaseProcess.h"
22 #include "mitkException.h"
23 #include "mitkImageReadAccessor.h"
24 #include "mitkImageToItk.h"
25 #include "mitkImageWriteAccessor.h"
27 template <typename TImageType>
28 struct SetLengthHelper
30 SetLengthHelper(TImageType *in) { m_Image = in; }
35 template <typename T, unsigned int VDimension>
36 struct SetLengthHelper<itk::Image<T, VDimension>>
38 typedef itk::Image<T, VDimension> TImageType;
40 SetLengthHelper(TImageType *in) { m_Image = in; }
41 void SetVectorLength(size_t) {}
46 template <typename T, unsigned int VDimension>
47 struct SetLengthHelper<itk::VectorImage<T, VDimension>>
49 typedef itk::VectorImage<T, VDimension> TImageType;
51 SetLengthHelper(TImageType *in) { m_Image = in; }
52 void SetVectorLength(size_t len) { m_Image->SetVectorLength(len); }
57 template <class TOutputImage>
58 void mitk::ImageToItk<TOutputImage>::SetInput(mitk::Image *input)
60 this->SetInput(static_cast<const Image *>(input));
64 template <class TOutputImage>
65 void mitk::ImageToItk<TOutputImage>::SetInput(const mitk::Image *input)
67 this->CheckInput(input);
68 // Process object is not const-correct so the const_cast is required here
69 itk::ProcessObject::PushFrontInput(input);
73 template <class TOutputImage>
74 mitk::Image *mitk::ImageToItk<TOutputImage>::GetInput(void)
76 if (this->GetNumberOfInputs() < 1)
81 return static_cast<mitk::Image *>(itk::ProcessObject::GetInput(0));
84 template <class TOutputImage>
85 const mitk::Image *mitk::ImageToItk<TOutputImage>::GetInput() const
87 if (this->GetNumberOfInputs() < 1)
92 return static_cast<const mitk::Image *>(itk::ProcessObject::GetInput(0));
95 template <class TOutputImage>
96 void mitk::ImageToItk<TOutputImage>::GenerateData()
99 mitk::Image::Pointer input = this->GetInput();
100 typename Superclass::OutputImageType::Pointer output = this->GetOutput();
102 unsigned long noBytes = input->GetDimension(0);
103 for (unsigned int i = 1; i < TOutputImage::GetImageDimension(); ++i)
105 noBytes = noBytes * input->GetDimension(i);
107 const mitk::PixelType pixelType = input->GetPixelType();
108 if (pixelType.GetPixelType() == itk::ImageIOBase::VECTOR)
110 noBytes *= pixelType.GetNumberOfComponents();
111 SetLengthHelper<typename Superclass::OutputImageType> helper(output.GetPointer());
112 helper.SetVectorLength(pixelType.GetNumberOfComponents());
115 mitk::ImageAccessorBase *imageAccess;
118 imageAccess = new mitk::ImageReadAccessor(input, static_cast<const ImageDataItem *>(nullptr), m_Options);
122 imageAccess = new mitk::ImageWriteAccessor(input, static_cast<const ImageDataItem *>(nullptr), m_Options);
125 // hier wird momentan wohl nur der erste Channel verwendet??!!
126 if (imageAccess->GetData() == nullptr)
128 itkWarningMacro(<< "no image data to import in ITK image");
130 RegionType bufferedRegion;
131 output->SetBufferedRegion(bufferedRegion);
137 itkDebugMacro("copyMem ...");
141 memcpy(output->GetBufferPointer(), imageAccess->GetData(), sizeof(InternalPixelType) * noBytes);
147 itkDebugMacro("do not copyMem ...");
148 typedef itk::ImportMitkImageContainer<unsigned long, InternalPixelType> ImportContainerType;
149 typename ImportContainerType::Pointer import;
151 import = ImportContainerType::New();
152 import->Initialize();
154 itkDebugMacro(<< "size of container = " << import->Size());
155 // import->SetImageDataItem(m_ImageDataItem);
156 import->SetImageAccessor(imageAccess, sizeof(InternalPixelType) * noBytes);
158 output->SetPixelContainer(import);
159 itkDebugMacro(<< "size of container = " << import->Size());
163 template <class TOutputImage>
164 void mitk::ImageToItk<TOutputImage>::UpdateOutputInformation()
166 mitk::Image::Pointer input = this->GetInput();
167 if (input.IsNotNull() && (input->GetSource().IsNotNull()) && input->GetSource()->Updating())
169 typename Superclass::OutputImageType::Pointer output = this->GetOutput();
170 unsigned long t1 = input->GetUpdateMTime() + 1;
171 if (t1 > this->m_OutputInformationMTime.GetMTime())
173 output->SetPipelineMTime(t1);
175 this->GenerateOutputInformation();
177 this->m_OutputInformationMTime.Modified();
181 Superclass::UpdateOutputInformation();
184 template <class TOutputImage>
185 void mitk::ImageToItk<TOutputImage>::GenerateOutputInformation()
187 mitk::Image::ConstPointer input = this->GetInput();
188 typename Superclass::OutputImageType::Pointer output = this->GetOutput();
190 // allocate size, origin, spacing, direction in types of output image
192 const unsigned int itkDimMin3 = (TOutputImage::ImageDimension > 3 ? TOutputImage::ImageDimension : 3);
193 const unsigned int itkDimMax3 = (TOutputImage::ImageDimension < 3 ? TOutputImage::ImageDimension : 3);
194 typename Superclass::OutputImageType::PointType::ValueType origin[itkDimMin3];
195 typename Superclass::OutputImageType::SpacingType::ComponentType spacing[itkDimMin3];
196 typename Superclass::OutputImageType::DirectionType direction;
198 // copy as much information as possible into size and spacing
200 for (i = 0; i < itkDimMax3; ++i)
202 size[i] = input->GetDimension(i);
203 spacing[i] = input->GetGeometry()->GetSpacing()[i];
205 for (; i < TOutputImage::ImageDimension; ++i)
208 size[i] = input->GetDimension(i);
212 // build region from size
216 region.SetIndex(start);
217 region.SetSize(size);
219 // copy as much information as possible into origin
220 const mitk::Point3D &mitkorigin = input->GetGeometry()->GetOrigin();
221 itk2vtk(mitkorigin, origin);
223 // copy as much information as possible into direction
224 direction.SetIdentity();
226 const AffineTransform3D::MatrixType &matrix = input->GetGeometry()->GetIndexToWorldTransform()->GetMatrix();
228 /// \warning 2D MITK images could have a 3D rotation, since they have a 3x3 geometry matrix.
229 /// If it is only a rotation around the axial plane normal, it can be express with a 2x2 matrix.
230 /// In this case, the ITK image conservs this information and is identical to the MITK image!
231 /// If the MITK image contains any other rotation, the ITK image will have no rotation at all.
232 /// Spacing is of course conserved in both cases.
234 // the following loop devides by spacing now to normalize columns.
235 // counterpart of InitializeByItk in mitkImage.h line 372 of revision 15092.
237 // Check if information is lost
238 if (TOutputImage::ImageDimension <= 2)
240 if ((TOutputImage::ImageDimension == 2) && ((matrix[0][2] != 0) || (matrix[1][2] != 0) || (matrix[2][0] != 0) ||
241 (matrix[2][1] != 0) || ((matrix[2][2] != 1) && (matrix[2][2] != -1))))
243 // The 2D MITK image contains 3D rotation information.
244 // This cannot be expressed in a 2D ITK image, so the ITK image will have no rotation
248 // The 2D MITK image can be converted to an 2D ITK image without information loss!
249 for (i = 0; i < itkDimMax3; ++i)
250 for (j = 0; j < itkDimMax3; ++j)
251 direction[i][j] = matrix[i][j] / spacing[j];
256 // Normal 3D image. Conversion possible without problem!
257 for (i = 0; i < itkDimMax3; ++i)
258 for (j = 0; j < itkDimMax3; ++j)
259 direction[i][j] = matrix[i][j] / spacing[j];
262 // set information into output image
263 output->SetRegions(region);
264 output->SetOrigin(origin);
265 output->SetSpacing(spacing);
266 output->SetDirection(direction);
269 template <class TOutputImage>
270 void mitk::ImageToItk<TOutputImage>::CheckInput(const mitk::Image *input) const
272 if (input == nullptr)
274 itkExceptionMacro(<< "image is null");
276 if (input->GetDimension() != TOutputImage::GetImageDimension())
278 itkExceptionMacro(<< "image has dimension " << input->GetDimension() << " instead of "
279 << TOutputImage::GetImageDimension());
282 if (!(input->GetPixelType() == mitk::MakePixelType<TOutputImage>(input->GetPixelType().GetNumberOfComponents())))
284 itkExceptionMacro(<< "image has wrong pixel type ");
288 template <class TOutputImage>
289 void mitk::ImageToItk<TOutputImage>::PrintSelf(std::ostream &os, itk::Indent indent) const
291 Superclass::PrintSelf(os, indent);
294 #endif // IMAGETOITK_TXX_INCLUDED_C1C2FCD2