Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkItkImageIO.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,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 #include "mitkItkImageIO.h"
18 
20 #include <mitkCoreServices.h>
21 #include <mitkCustomMimeType.h>
22 #include <mitkIOMimeTypes.h>
24 #include <mitkImage.h>
25 #include <mitkImageReadAccessor.h>
26 #include <mitkLocaleSwitch.h>
27 
28 #include <itkImage.h>
29 #include <itkImageFileReader.h>
30 #include <itkImageIOFactory.h>
31 #include <itkImageIORegion.h>
32 #include <itkMetaDataObject.h>
33 
34 #include <algorithm>
35 
36 namespace mitk
37 {
38  const char *const PROPERTY_NAME_TIMEGEOMETRY_TYPE = "org.mitk.timegeometry.type";
39  const char *const PROPERTY_NAME_TIMEGEOMETRY_TIMEPOINTS = "org.mitk.timegeometry.timepoints";
40  const char *const PROPERTY_KEY_TIMEGEOMETRY_TYPE = "org_mitk_timegeometry_type";
41  const char *const PROPERTY_KEY_TIMEGEOMETRY_TIMEPOINTS = "org_mitk_timegeometry_timepoints";
42 
44  : AbstractFileIO(other), m_ImageIO(dynamic_cast<itk::ImageIOBase *>(other.m_ImageIO->Clone().GetPointer()))
45  {
46  this->InitializeDefaultMetaDataKeys();
47  }
48 
49  std::vector<std::string> ItkImageIO::FixUpImageIOExtensions(const std::string &imageIOName)
50  {
51  std::vector<std::string> extensions;
52  // Try to fix-up some known ITK image IO classes
53  if (imageIOName == "GiplImageIO")
54  {
55  extensions.push_back("gipl");
56  extensions.push_back("gipl.gz");
57  }
58  else if (imageIOName == "GDCMImageIO")
59  {
60  extensions.push_back("gdcm");
61  extensions.push_back("dcm");
62  extensions.push_back("DCM");
63  extensions.push_back("dc3");
64  extensions.push_back("DC3");
65  extensions.push_back("ima");
66  extensions.push_back("img");
67  }
68  else if (imageIOName == "PNGImageIO")
69  {
70  extensions.push_back("png");
71  extensions.push_back("PNG");
72  }
73  else if (imageIOName == "StimulateImageIO")
74  {
75  extensions.push_back("spr");
76  }
77  else if (imageIOName == "HDF5ImageIO")
78  {
79  extensions.push_back("hdf");
80  extensions.push_back("h4");
81  extensions.push_back("hdf4");
82  extensions.push_back("h5");
83  extensions.push_back("hdf5");
84  extensions.push_back("he4");
85  extensions.push_back("he5");
86  extensions.push_back("hd5");
87  }
88  else if (imageIOName == "GE4ImageIO" || imageIOName == "GE5ImageIO")
89  {
90  extensions.push_back("");
91  }
92 
93  if (!extensions.empty())
94  {
95  MITK_DEBUG << "Fixing up known extensions for " << imageIOName;
96  }
97 
98  return extensions;
99  }
100 
101  ItkImageIO::ItkImageIO(itk::ImageIOBase::Pointer imageIO)
102  : AbstractFileIO(Image::GetStaticNameOfClass()), m_ImageIO(imageIO)
103  {
104  if (m_ImageIO.IsNull())
105  {
106  mitkThrow() << "ITK ImageIOBase argument must not be NULL";
107  }
108 
111 
112  std::vector<std::string> readExtensions = m_ImageIO->GetSupportedReadExtensions();
113 
114  if (readExtensions.empty())
115  {
116  std::string imageIOName = m_ImageIO->GetNameOfClass();
117  MITK_DEBUG << "ITK ImageIOBase " << imageIOName << " does not provide read extensions";
118  readExtensions = FixUpImageIOExtensions(imageIOName);
119  }
120 
121  CustomMimeType customReaderMimeType;
122  customReaderMimeType.SetCategory("Images");
123  for (std::vector<std::string>::const_iterator iter = readExtensions.begin(), endIter = readExtensions.end();
124  iter != endIter;
125  ++iter)
126  {
127  std::string extension = *iter;
128  if (!extension.empty() && extension[0] == '.')
129  {
130  extension.assign(iter->begin() + 1, iter->end());
131  }
132  customReaderMimeType.AddExtension(extension);
133  }
134  this->AbstractFileReader::SetMimeType(customReaderMimeType);
135 
136  std::vector<std::string> writeExtensions = imageIO->GetSupportedWriteExtensions();
137  if (writeExtensions.empty())
138  {
139  std::string imageIOName = imageIO->GetNameOfClass();
140  MITK_DEBUG << "ITK ImageIOBase " << imageIOName << " does not provide write extensions";
141  writeExtensions = FixUpImageIOExtensions(imageIOName);
142  }
143 
144  if (writeExtensions != readExtensions)
145  {
146  CustomMimeType customWriterMimeType;
147  customWriterMimeType.SetCategory("Images");
148  for (std::vector<std::string>::const_iterator iter = writeExtensions.begin(), endIter = writeExtensions.end();
149  iter != endIter;
150  ++iter)
151  {
152  std::string extension = *iter;
153  if (!extension.empty() && extension[0] == '.')
154  {
155  extension.assign(iter->begin() + 1, iter->end());
156  }
157  customWriterMimeType.AddExtension(extension);
158  }
159  this->AbstractFileWriter::SetMimeType(customWriterMimeType);
160  }
161 
162  std::string description = std::string("ITK ") + imageIO->GetNameOfClass();
163  this->SetReaderDescription(description);
164  this->SetWriterDescription(description);
165 
166  this->RegisterService();
167  }
168 
170  : AbstractFileIO(Image::GetStaticNameOfClass(), mimeType, std::string("ITK ") + imageIO->GetNameOfClass()),
171  m_ImageIO(imageIO)
172  {
173  if (m_ImageIO.IsNull())
174  {
175  mitkThrow() << "ITK ImageIOBase argument must not be NULL";
176  }
177 
180 
181  if (rank)
182  {
183  this->AbstractFileReader::SetRanking(rank);
184  this->AbstractFileWriter::SetRanking(rank);
185  }
186 
187  this->RegisterService();
188  }
189 
192  std::vector<TimePointType> ConvertMetaDataObjectToTimePointList(const itk::MetaDataObjectBase *data)
193  {
194  const itk::MetaDataObject<std::string> *timeGeometryTimeData =
195  dynamic_cast<const itk::MetaDataObject<std::string> *>(data);
196  std::vector<TimePointType> result;
197 
198  if (timeGeometryTimeData)
199  {
200  std::string dataStr = timeGeometryTimeData->GetMetaDataObjectValue();
201  std::stringstream stream(dataStr);
202  TimePointType tp;
203  while (stream >> tp)
204  {
205  result.push_back(tp);
206  }
207  }
208 
209  return result;
210  };
211 
212  std::vector<BaseData::Pointer> ItkImageIO::Read()
213  {
214  std::vector<BaseData::Pointer> result;
215  mitk::LocaleSwitch localeSwitch("C");
216 
217  Image::Pointer image = Image::New();
218 
219  const unsigned int MINDIM = 2;
220  const unsigned int MAXDIM = 4;
221 
222  const std::string path = this->GetLocalFileName();
223 
224  MITK_INFO << "loading " << path << " via itk::ImageIOFactory... " << std::endl;
225 
226  // Check to see if we can read the file given the name or prefix
227  if (path.empty())
228  {
229  mitkThrow() << "Empty filename in mitk::ItkImageIO ";
230  }
231 
232  // Got to allocate space for the image. Determine the characteristics of
233  // the image.
234  m_ImageIO->SetFileName(path);
235  m_ImageIO->ReadImageInformation();
236 
237  unsigned int ndim = m_ImageIO->GetNumberOfDimensions();
238  if (ndim < MINDIM || ndim > MAXDIM)
239  {
240  MITK_WARN << "Sorry, only dimensions 2, 3 and 4 are supported. The given file has " << ndim
241  << " dimensions! Reading as 4D.";
242  ndim = MAXDIM;
243  }
244 
245  itk::ImageIORegion ioRegion(ndim);
246  itk::ImageIORegion::SizeType ioSize = ioRegion.GetSize();
247  itk::ImageIORegion::IndexType ioStart = ioRegion.GetIndex();
248 
249  unsigned int dimensions[MAXDIM];
250  dimensions[0] = 0;
251  dimensions[1] = 0;
252  dimensions[2] = 0;
253  dimensions[3] = 0;
254 
255  ScalarType spacing[MAXDIM];
256  spacing[0] = 1.0f;
257  spacing[1] = 1.0f;
258  spacing[2] = 1.0f;
259  spacing[3] = 1.0f;
260 
261  Point3D origin;
262  origin.Fill(0);
263 
264  unsigned int i;
265  for (i = 0; i < ndim; ++i)
266  {
267  ioStart[i] = 0;
268  ioSize[i] = m_ImageIO->GetDimensions(i);
269  if (i < MAXDIM)
270  {
271  dimensions[i] = m_ImageIO->GetDimensions(i);
272  spacing[i] = m_ImageIO->GetSpacing(i);
273  if (spacing[i] <= 0)
274  spacing[i] = 1.0f;
275  }
276  if (i < 3)
277  {
278  origin[i] = m_ImageIO->GetOrigin(i);
279  }
280  }
281 
282  ioRegion.SetSize(ioSize);
283  ioRegion.SetIndex(ioStart);
284 
285  MITK_INFO << "ioRegion: " << ioRegion << std::endl;
286  m_ImageIO->SetIORegion(ioRegion);
287  void *buffer = new unsigned char[m_ImageIO->GetImageSizeInBytes()];
288  m_ImageIO->Read(buffer);
289 
290  image->Initialize(MakePixelType(m_ImageIO), ndim, dimensions);
291  image->SetImportChannel(buffer, 0, Image::ManageMemory);
292 
293  const itk::MetaDataDictionary &dictionary = m_ImageIO->GetMetaDataDictionary();
294 
295  // access direction of itk::Image and include spacing
296  mitk::Matrix3D matrix;
297  matrix.SetIdentity();
298  unsigned int j, itkDimMax3 = (ndim >= 3 ? 3 : ndim);
299  for (i = 0; i < itkDimMax3; ++i)
300  for (j = 0; j < itkDimMax3; ++j)
301  matrix[i][j] = m_ImageIO->GetDirection(j)[i];
302 
303  // re-initialize PlaneGeometry with origin and direction
304  PlaneGeometry *planeGeometry = image->GetSlicedGeometry(0)->GetPlaneGeometry(0);
305  planeGeometry->SetOrigin(origin);
306  planeGeometry->GetIndexToWorldTransform()->SetMatrix(matrix);
307 
308  // re-initialize SlicedGeometry3D
309  SlicedGeometry3D *slicedGeometry = image->GetSlicedGeometry(0);
310  slicedGeometry->InitializeEvenlySpaced(planeGeometry, image->GetDimension(2));
311  slicedGeometry->SetSpacing(spacing);
312 
313  MITK_INFO << slicedGeometry->GetCornerPoint(false, false, false);
314  MITK_INFO << slicedGeometry->GetCornerPoint(true, true, true);
315 
316  // re-initialize TimeGeometry
317  TimeGeometry::Pointer timeGeometry;
318 
319  if (dictionary.HasKey(PROPERTY_NAME_TIMEGEOMETRY_TYPE) || dictionary.HasKey(PROPERTY_KEY_TIMEGEOMETRY_TYPE))
320  { // also check for the name because of backwards compatibility. Past code version stored with the name and not with
321  // the key
322  itk::MetaDataObject<std::string>::ConstPointer timeGeometryTypeData = nullptr;
323  if (dictionary.HasKey(PROPERTY_NAME_TIMEGEOMETRY_TYPE))
324  {
325  timeGeometryTypeData =
326  dynamic_cast<const itk::MetaDataObject<std::string> *>(dictionary.Get(PROPERTY_NAME_TIMEGEOMETRY_TYPE));
327  }
328  else
329  {
330  timeGeometryTypeData =
331  dynamic_cast<const itk::MetaDataObject<std::string> *>(dictionary.Get(PROPERTY_KEY_TIMEGEOMETRY_TYPE));
332  }
333 
334  if (timeGeometryTypeData->GetMetaDataObjectValue() == ArbitraryTimeGeometry::GetStaticNameOfClass())
335  {
336  MITK_INFO << "used time geometry: " << ArbitraryTimeGeometry::GetStaticNameOfClass() << std::endl;
337  typedef std::vector<TimePointType> TimePointVector;
338  TimePointVector timePoints;
339 
340  if (dictionary.HasKey(PROPERTY_NAME_TIMEGEOMETRY_TIMEPOINTS))
341  {
342  timePoints = ConvertMetaDataObjectToTimePointList(dictionary.Get(PROPERTY_NAME_TIMEGEOMETRY_TIMEPOINTS));
343  }
344  else if (dictionary.HasKey(PROPERTY_KEY_TIMEGEOMETRY_TIMEPOINTS))
345  {
346  timePoints = ConvertMetaDataObjectToTimePointList(dictionary.Get(PROPERTY_KEY_TIMEGEOMETRY_TIMEPOINTS));
347  }
348 
349  if (timePoints.size() - 1 != image->GetDimension(3))
350  {
351  MITK_ERROR << "Stored timepoints (" << timePoints.size() - 1 << ") and size of image time dimension ("
352  << image->GetDimension(3) << ") do not match. Switch to ProportionalTimeGeometry fallback"
353  << std::endl;
354  }
355  else
356  {
358  TimePointVector::const_iterator pos = timePoints.begin();
359  TimePointVector::const_iterator prePos = pos++;
360 
361  for (; pos != timePoints.end(); ++prePos, ++pos)
362  {
363  arbitraryTimeGeometry->AppendTimeStepClone(slicedGeometry, *pos, *prePos);
364  }
365 
366  timeGeometry = arbitraryTimeGeometry;
367  }
368  }
369  }
370 
371  if (timeGeometry.IsNull())
372  { // Fallback. If no other valid time geometry has been created, create a ProportionalTimeGeometry
373  MITK_INFO << "used time geometry: " << ProportionalTimeGeometry::GetStaticNameOfClass() << std::endl;
375  propTimeGeometry->Initialize(slicedGeometry, image->GetDimension(3));
376  timeGeometry = propTimeGeometry;
377  }
378 
379  image->SetTimeGeometry(timeGeometry);
380 
381  buffer = NULL;
382  MITK_INFO << "number of image components: " << image->GetPixelType().GetNumberOfComponents() << std::endl;
383 
384  for (itk::MetaDataDictionary::ConstIterator iter = dictionary.Begin(), iterEnd = dictionary.End(); iter != iterEnd;
385  ++iter)
386  {
387  if (iter->second->GetMetaDataObjectTypeInfo() == typeid(std::string))
388  {
389  const std::string &key = iter->first;
390  std::string assumedPropertyName = key;
391  std::replace(assumedPropertyName.begin(), assumedPropertyName.end(), '_', '.');
392 
393  std::string mimeTypeName = GetMimeType()->GetName();
394 
395  // Check if there is already a info for the key and our mime type.
397 
398  auto predicate = [mimeTypeName](const PropertyPersistenceInfo::ConstPointer &x) {
399  return x.IsNotNull() && x->GetMimeTypeName() == mimeTypeName;
400  };
401  auto finding = std::find_if(infoList.begin(), infoList.end(), predicate);
402 
403  if (finding == infoList.end())
404  {
405  auto predicateWild = [](const PropertyPersistenceInfo::ConstPointer &x) {
406  return x.IsNotNull() && x->GetMimeTypeName() == PropertyPersistenceInfo::ANY_MIMETYPE_NAME();
407  };
408  finding = std::find_if(infoList.begin(), infoList.end(), predicateWild);
409  }
410 
412 
413  if (finding != infoList.end())
414  {
415  assumedPropertyName = (*finding)->GetName();
416  info = *finding;
417  }
418  else
419  { // we have not found anything suitable so we generate our own info
421  newInfo->SetNameAndKey(assumedPropertyName, key);
422  newInfo->SetMimeTypeName(PropertyPersistenceInfo::ANY_MIMETYPE_NAME());
423  info = newInfo;
424  }
425 
426  std::string value =
427  dynamic_cast<itk::MetaDataObject<std::string> *>(iter->second.GetPointer())->GetMetaDataObjectValue();
428 
429  mitk::BaseProperty::Pointer loadedProp = info->GetDeserializationFunction()(value);
430 
431  image->SetProperty(assumedPropertyName.c_str(), loadedProp);
432 
433  // Read properties should be persisted unless they are default properties
434  // which are written anyway
435  bool isDefaultKey(false);
436 
437  for (const auto &defaultKey : m_DefaultMetaDataKeys)
438  {
439  if (defaultKey.length() <= assumedPropertyName.length())
440  {
441  // does the start match the default key
442  if (assumedPropertyName.substr(0, defaultKey.length()).find(defaultKey) != std::string::npos)
443  {
444  isDefaultKey = true;
445  break;
446  }
447  }
448  }
449 
450  if (!isDefaultKey)
451  {
453  }
454  }
455  }
456 
457  MITK_INFO << "...finished!" << std::endl;
458 
459  result.push_back(image.GetPointer());
460  return result;
461  }
462 
464  {
465  return m_ImageIO->CanReadFile(GetLocalFileName().c_str()) ? IFileReader::Supported : IFileReader::Unsupported;
466  }
467 
469  {
470  const mitk::Image *image = dynamic_cast<const mitk::Image *>(this->GetInput());
471 
472  if (image == NULL)
473  {
474  mitkThrow() << "Cannot write non-image data";
475  }
476 
477  // Switch the current locale to "C"
478  LocaleSwitch localeSwitch("C");
479 
480  // Clone the image geometry, because we might have to change it
481  // for writing purposes
482  BaseGeometry::Pointer geometry = image->GetGeometry()->Clone();
483 
484  // Check if geometry information will be lost
485  if (image->GetDimension() == 2 && !geometry->Is2DConvertable())
486  {
487  MITK_WARN << "Saving a 2D image with 3D geometry information. Geometry information will be lost! You might "
488  "consider using Convert2Dto3DImageFilter before saving.";
489 
490  // set matrix to identity
492  affTrans->SetIdentity();
493  mitk::Vector3D spacing = geometry->GetSpacing();
494  mitk::Point3D origin = geometry->GetOrigin();
495  geometry->SetIndexToWorldTransform(affTrans);
496  geometry->SetSpacing(spacing);
497  geometry->SetOrigin(origin);
498  }
499 
500  LocalFile localFile(this);
501  const std::string path = localFile.GetFileName();
502 
503  MITK_INFO << "Writing image: " << path << std::endl;
504 
505  try
506  {
507  // Implementation of writer using itkImageIO directly. This skips the use
508  // of templated itkImageFileWriter, which saves the multiplexing on MITK side.
509 
510  const unsigned int dimension = image->GetDimension();
511  const unsigned int *const dimensions = image->GetDimensions();
512  const mitk::PixelType pixelType = image->GetPixelType();
513  const mitk::Vector3D mitkSpacing = geometry->GetSpacing();
514  const mitk::Point3D mitkOrigin = geometry->GetOrigin();
515 
516  // Due to templating in itk, we are forced to save a 4D spacing and 4D Origin,
517  // though they are not supported in MITK
518  itk::Vector<double, 4u> spacing4D;
519  spacing4D[0] = mitkSpacing[0];
520  spacing4D[1] = mitkSpacing[1];
521  spacing4D[2] = mitkSpacing[2];
522  spacing4D[3] = 1; // There is no support for a 4D spacing. However, we should have a valid value here
523 
524  itk::Vector<double, 4u> origin4D;
525  origin4D[0] = mitkOrigin[0];
526  origin4D[1] = mitkOrigin[1];
527  origin4D[2] = mitkOrigin[2];
528  origin4D[3] = 0; // There is no support for a 4D origin. However, we should have a valid value here
529 
530  // Set the necessary information for imageIO
531  m_ImageIO->SetNumberOfDimensions(dimension);
532  m_ImageIO->SetPixelType(pixelType.GetPixelType());
533  m_ImageIO->SetComponentType(pixelType.GetComponentType() < PixelComponentUserType ?
534  static_cast<itk::ImageIOBase::IOComponentType>(pixelType.GetComponentType()) :
535  itk::ImageIOBase::UNKNOWNCOMPONENTTYPE);
536  m_ImageIO->SetNumberOfComponents(pixelType.GetNumberOfComponents());
537 
538  itk::ImageIORegion ioRegion(dimension);
539 
540  for (unsigned int i = 0; i < dimension; i++)
541  {
542  m_ImageIO->SetDimensions(i, dimensions[i]);
543  m_ImageIO->SetSpacing(i, spacing4D[i]);
544  m_ImageIO->SetOrigin(i, origin4D[i]);
545 
546  mitk::Vector3D mitkDirection;
547  mitkDirection.SetVnlVector(geometry->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(i));
548  itk::Vector<double, 4u> direction4D;
549  direction4D[0] = mitkDirection[0];
550  direction4D[1] = mitkDirection[1];
551  direction4D[2] = mitkDirection[2];
552 
553  // MITK only supports a 3x3 direction matrix. Due to templating in itk, however, we must
554  // save a 4x4 matrix for 4D images. in this case, add an homogneous component to the matrix.
555  if (i == 3)
556  {
557  direction4D[3] = 1; // homogenous component
558  }
559  else
560  {
561  direction4D[3] = 0;
562  }
563  vnl_vector<double> axisDirection(dimension);
564  for (unsigned int j = 0; j < dimension; j++)
565  {
566  axisDirection[j] = direction4D[j] / spacing4D[i];
567  }
568  m_ImageIO->SetDirection(i, axisDirection);
569 
570  ioRegion.SetSize(i, image->GetLargestPossibleRegion().GetSize(i));
571  ioRegion.SetIndex(i, image->GetLargestPossibleRegion().GetIndex(i));
572  }
573 
574  // use compression if available
575  m_ImageIO->UseCompressionOn();
576 
577  m_ImageIO->SetIORegion(ioRegion);
578  m_ImageIO->SetFileName(path);
579 
580  // Handle time geometry
581  const ArbitraryTimeGeometry *arbitraryTG = dynamic_cast<const ArbitraryTimeGeometry *>(image->GetTimeGeometry());
582  if (arbitraryTG)
583  {
584  itk::EncapsulateMetaData<std::string>(m_ImageIO->GetMetaDataDictionary(),
587 
588  std::stringstream stream;
589  stream << arbitraryTG->GetTimeBounds(0)[0];
590  for (TimeStepType pos = 0; pos < arbitraryTG->CountTimeSteps(); ++pos)
591  {
592  stream << " " << arbitraryTG->GetTimeBounds(pos)[1];
593  }
594  std::string data = stream.str();
595 
596  itk::EncapsulateMetaData<std::string>(
597  m_ImageIO->GetMetaDataDictionary(), PROPERTY_KEY_TIMEGEOMETRY_TIMEPOINTS, data);
598  }
599 
600  // Handle properties
601  mitk::PropertyList::Pointer imagePropertyList = image->GetPropertyList();
602 
603  for (const auto &property : *imagePropertyList->GetMap())
604  {
607 
608  if (infoList.empty())
609  {
610  continue;
611  }
612 
613  std::string value = infoList.front()->GetSerializationFunction()(property.second);
614 
616  {
617  continue;
618  }
619 
620  std::string key = infoList.front()->GetKey();
621 
622  itk::EncapsulateMetaData<std::string>(m_ImageIO->GetMetaDataDictionary(), key, value);
623  }
624 
625  ImageReadAccessor imageAccess(image);
626  m_ImageIO->Write(imageAccess.GetData());
627  }
628  catch (const std::exception &e)
629  {
630  mitkThrow() << e.what();
631  }
632  }
633 
635  {
636  // Check if the image dimension is supported
637  const Image *image = dynamic_cast<const Image *>(this->GetInput());
638  if (image == NULL)
639  {
640  // We cannot write a null object, DUH!
642  }
643 
644  if (!m_ImageIO->SupportsDimension(image->GetDimension()))
645  {
646  // okay, dimension is not supported. We have to look at a special case:
647  // 3D-Image with one slice. We can treat that as a 2D image.
648  if ((image->GetDimension() == 3) && (image->GetSlicedGeometry()->GetSlices() == 1))
649  return IFileWriter::Supported;
650  else
652  }
653 
654  // Check if geometry information will be lost
655  if (image->GetDimension() == 2 && !image->GetGeometry()->Is2DConvertable())
656  {
658  }
659  return IFileWriter::Supported;
660  }
661 
662  ItkImageIO *ItkImageIO::IOClone() const { return new ItkImageIO(*this); }
664  {
665  this->m_DefaultMetaDataKeys.push_back("NRRD.space");
666  this->m_DefaultMetaDataKeys.push_back("NRRD.kinds");
667  this->m_DefaultMetaDataKeys.push_back(PROPERTY_NAME_TIMEGEOMETRY_TYPE);
668  this->m_DefaultMetaDataKeys.push_back(PROPERTY_NAME_TIMEGEOMETRY_TIMEPOINTS);
669  this->m_DefaultMetaDataKeys.push_back("ITK.InputFilterName");
670  }
671 }
static const char * GetStaticNameOfClass()
itk::SmartPointer< Self > Pointer
void SetSpacing(const mitk::Vector3D &aSpacing, bool enforceSetSpacing=false)
Set the spacing (m_Spacing).
Pointer Clone() const
#define MITK_INFO
Definition: mitkLogMacros.h:22
virtual TimeBounds GetTimeBounds() const
Get the time bounds (in ms) it returns GetMinimumTimePoint() and GetMaximumTimePoint() results as bou...
virtual InfoResultType GetInfoByKey(const std::string &persistenceKey, bool allowKeyRegEx=true) const =0
Get the persistence info that will use the specified key.
#define MITK_ERROR
Definition: mitkLogMacros.h:24
double ScalarType
const char *const PROPERTY_NAME_TIMEGEOMETRY_TIMEPOINTS
ItkImageIO(itk::ImageIOBase::Pointer imageIO)
#define MITK_DEBUG
Definition: mitkLogMacros.h:26
STL namespace.
std::vector< TimePointType > ConvertMetaDataObjectToTimePointList(const itk::MetaDataObjectBase *data)
const void * GetData() const
Gives const access to the data.
DataCollection - Class to facilitate loading/accessing structured data.
const mitk::TimeGeometry * GetTimeGeometry() const
Return the TimeGeometry of the data as const pointer.
Definition: mitkBaseData.h:52
itk::ImageIOBase::IOPixelType GetPixelType() const
std::string GetLocalFileName() const
Get a local file name for reading.
virtual void InitializeEvenlySpaced(mitk::PlaneGeometry *geometry2D, unsigned int slices)
Completely initialize this instance as evenly-spaced with slices parallel to the provided PlaneGeomet...
static void info(const char *fmt,...)
Definition: svm.cpp:100
itk::SmartPointer< const Self > ConstPointer
static const int PixelComponentUserType
void SetMimeType(const CustomMimeType &mimeType)
The CustomMimeType class represents a custom mime-type which may be registered as a service object...
void SetRanking(int ranking)
Set the service ranking for this file writer.
void SetMimeTypePrefix(const std::string &prefix)
virtual ConfidenceLevel GetWriterConfidenceLevel() const override
virtual void Write() override
Write the base data to the specified location or output stream.
MITKCORE_EXPORT mitk::PixelType MakePixelType(vtkImageData *vtkimagedata)
deduct the PixelType for a given vtk image
unsigned int * GetDimensions() const
Get the sizes of all dimensions as an integer-array.
Definition: mitkImage.cpp:1308
static std::string DEFAULT_BASE_NAME()
#define MITK_WARN
Definition: mitkLogMacros.h:23
Convenience class to temporarily change the current locale.
static IPropertyPersistence * GetPropertyPersistence(us::ModuleContext *context=us::GetModuleContext())
Get an IPropertyPersistence instance.
virtual ConfidenceLevel GetReaderConfidenceLevel() const override
std::pair< us::ServiceRegistration< IFileReader >, us::ServiceRegistration< IFileWriter > > RegisterService(us::ModuleContext *context=us::GetModuleContext())
#define mitkThrow()
void SetOrigin(const Point3D &origin)
Set the origin, i.e. the upper-left corner of the plane.
virtual InfoResultType GetInfo(const std::string &propertyName, bool allowNameRegEx=true) const =0
Get the persistence info for a specific base data property.
virtual std::vector< std::string > FixUpImageIOExtensions(const std::string &imageIOName)
virtual const BaseData * GetInput() const override
Get the input data set via SetInput().
Image class for storing images.
Definition: mitkImage.h:76
mitk::PropertyList::Pointer GetPropertyList() const
Get the data's property list.
const char *const PROPERTY_NAME_TIMEGEOMETRY_TYPE
void SetReaderDescription(const std::string &description)
const RegionType & GetLargestPossibleRegion() const
static const char * GetStaticNameOfClass()
mitk::ScalarType TimePointType
A local file representation for streams.
std::string GetName() const
Returns the unique name for the MimeType.
std::vcl_size_t TimeStepType
static const std::string VALUE_CANNOT_BE_CONVERTED_TO_STRING
Default return value if a property which can not be returned as string.
int GetComponentType() const
Get the component type (the scalar (!) type). Each element may contain m_NumberOfComponents (more tha...
const mitk::PixelType GetPixelType(int n=0) const
Returns the PixelType of channel n.
Definition: mitkImage.cpp:105
virtual void InitializeDefaultMetaDataKeys()
void AddExtension(const std::string &extension)
Point3D GetCornerPoint(int id) const
Get the position of the corner number id (in world coordinates)
static Pointer New()
virtual unsigned int GetSlices() const
Get the number of slices.
Describes the geometry of a data object consisting of slices.
void SetRanking(int ranking)
Set the service ranking for this file reader.
void SetWriterDescription(const std::string &description)
void SetCategory(const std::string &category)
const CustomMimeType * GetMimeType() const
vcl_size_t GetNumberOfComponents() const
Get the number of components of which each element consists.
virtual std::vector< itk::SmartPointer< BaseData > > Read() override
Reads a path or stream and creates a list of BaseData objects.
const char *const PROPERTY_KEY_TIMEGEOMETRY_TIMEPOINTS
static const char * replace[]
This is a dictionary to replace long names of classes, modules, etc. to shorter versions in the conso...
void SetMimeType(const CustomMimeType &mimeType)
static std::string GetName(std::string fileName, std::string suffix)
ConfidenceLevel
A confidence level describing the confidence of the reader or writer in handling the given data...
Definition: mitkIFileIO.h:49
SlicedGeometry3D * GetSlicedGeometry(unsigned int t=0) const
Convenience access method for the geometry, which is of type SlicedGeometry3D (or a sub-class of it)...
Describes a two-dimensional, rectangular plane.
virtual bool AddInfo(const PropertyPersistenceInfo *info, bool overwrite=false)=0
Add persistence info for a specific base data property. If there is already a property info instance ...
const char *const PROPERTY_KEY_TIMEGEOMETRY_TYPE
std::list< PropertyPersistenceInfo::ConstPointer > InfoResultType
unsigned int GetDimension() const
Get dimension of the image.
Definition: mitkImage.cpp:110
virtual bool Is2DConvertable()
Checks, if the given geometry can be converted to 2D without information loss e.g. when a 2D image is saved, the matrix is usually cropped to 2x2, and when you load it back to MITK it will be filled with standard values. This function checks, if information would be lost during this procedure.
ImageReadAccessor class to get locked read access for a particular image part.
mitk::BaseGeometry * GetGeometry(int t=0) const
Return the geometry, which is a TimeGeometry, of the data as non-const pointer.
Definition: mitkBaseData.h:129
Abstract class for implementing a reader and writer.
Pointer Clone() const
virtual TimeStepType CountTimeSteps() const
Returns the number of time steps.
Class for defining the data type of pixels.
Definition: mitkPixelType.h:55
mitk::AffineTransform3D * GetIndexToWorldTransform()
Get the transformation used to convert from index to world coordinates.
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.