29 #include <itkImageFileReader.h>
30 #include <itkImageIOFactory.h>
31 #include <itkImageIORegion.h>
32 #include <itkMetaDataObject.h>
44 :
AbstractFileIO(other), m_ImageIO(dynamic_cast<
itk::ImageIOBase *>(other.m_ImageIO->
Clone().GetPointer()))
46 this->InitializeDefaultMetaDataKeys();
49 std::vector<std::string> ItkImageIO::FixUpImageIOExtensions(
const std::string &imageIOName)
51 std::vector<std::string> extensions;
53 if (imageIOName ==
"GiplImageIO")
55 extensions.push_back(
"gipl");
56 extensions.push_back(
"gipl.gz");
58 else if (imageIOName ==
"GDCMImageIO")
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");
68 else if (imageIOName ==
"PNGImageIO")
70 extensions.push_back(
"png");
71 extensions.push_back(
"PNG");
73 else if (imageIOName ==
"StimulateImageIO")
75 extensions.push_back(
"spr");
77 else if (imageIOName ==
"HDF5ImageIO")
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");
88 else if (imageIOName ==
"GE4ImageIO" || imageIOName ==
"GE5ImageIO")
90 extensions.push_back(
"");
93 if (!extensions.empty())
95 MITK_DEBUG <<
"Fixing up known extensions for " << imageIOName;
104 if (m_ImageIO.IsNull())
106 mitkThrow() <<
"ITK ImageIOBase argument must not be NULL";
112 std::vector<std::string> readExtensions = m_ImageIO->GetSupportedReadExtensions();
114 if (readExtensions.empty())
116 std::string imageIOName = m_ImageIO->GetNameOfClass();
117 MITK_DEBUG <<
"ITK ImageIOBase " << imageIOName <<
" does not provide read extensions";
123 for (std::vector<std::string>::const_iterator iter = readExtensions.begin(), endIter = readExtensions.end();
127 std::string extension = *iter;
128 if (!extension.empty() && extension[0] ==
'.')
130 extension.assign(iter->begin() + 1, iter->end());
136 std::vector<std::string> writeExtensions = imageIO->GetSupportedWriteExtensions();
137 if (writeExtensions.empty())
139 std::string imageIOName = imageIO->GetNameOfClass();
140 MITK_DEBUG <<
"ITK ImageIOBase " << imageIOName <<
" does not provide write extensions";
144 if (writeExtensions != readExtensions)
148 for (std::vector<std::string>::const_iterator iter = writeExtensions.begin(), endIter = writeExtensions.end();
152 std::string extension = *iter;
153 if (!extension.empty() && extension[0] ==
'.')
155 extension.assign(iter->begin() + 1, iter->end());
162 std::string description = std::string(
"ITK ") + imageIO->GetNameOfClass();
173 if (m_ImageIO.IsNull())
175 mitkThrow() <<
"ITK ImageIOBase argument must not be NULL";
194 const itk::MetaDataObject<std::string> *timeGeometryTimeData =
195 dynamic_cast<const itk::MetaDataObject<std::string> *
>(data);
196 std::vector<TimePointType> result;
198 if (timeGeometryTimeData)
200 std::string dataStr = timeGeometryTimeData->GetMetaDataObjectValue();
201 std::stringstream stream(dataStr);
205 result.push_back(tp);
214 std::vector<BaseData::Pointer> result;
219 const unsigned int MINDIM = 2;
220 const unsigned int MAXDIM = 4;
224 MITK_INFO <<
"loading " << path <<
" via itk::ImageIOFactory... " << std::endl;
229 mitkThrow() <<
"Empty filename in mitk::ItkImageIO ";
234 m_ImageIO->SetFileName(path);
235 m_ImageIO->ReadImageInformation();
237 unsigned int ndim = m_ImageIO->GetNumberOfDimensions();
238 if (ndim < MINDIM || ndim > MAXDIM)
240 MITK_WARN <<
"Sorry, only dimensions 2, 3 and 4 are supported. The given file has " << ndim
241 <<
" dimensions! Reading as 4D.";
245 itk::ImageIORegion ioRegion(ndim);
246 itk::ImageIORegion::SizeType ioSize = ioRegion.GetSize();
247 itk::ImageIORegion::IndexType ioStart = ioRegion.GetIndex();
249 unsigned int dimensions[MAXDIM];
265 for (i = 0; i < ndim; ++i)
268 ioSize[i] = m_ImageIO->GetDimensions(i);
271 dimensions[i] = m_ImageIO->GetDimensions(i);
272 spacing[i] = m_ImageIO->GetSpacing(i);
278 origin[i] = m_ImageIO->GetOrigin(i);
282 ioRegion.SetSize(ioSize);
283 ioRegion.SetIndex(ioStart);
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);
290 image->Initialize(
MakePixelType(m_ImageIO), ndim, dimensions);
293 const itk::MetaDataDictionary &dictionary = m_ImageIO->GetMetaDataDictionary();
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];
304 PlaneGeometry *planeGeometry = image->GetSlicedGeometry(0)->GetPlaneGeometry(0);
319 if (dictionary.HasKey(PROPERTY_NAME_TIMEGEOMETRY_TYPE) || dictionary.HasKey(PROPERTY_KEY_TIMEGEOMETRY_TYPE))
323 if (dictionary.HasKey(PROPERTY_NAME_TIMEGEOMETRY_TYPE))
325 timeGeometryTypeData =
326 dynamic_cast<const itk::MetaDataObject<std::string> *
>(dictionary.Get(PROPERTY_NAME_TIMEGEOMETRY_TYPE));
330 timeGeometryTypeData =
331 dynamic_cast<const itk::MetaDataObject<std::string> *
>(dictionary.Get(PROPERTY_KEY_TIMEGEOMETRY_TYPE));
337 typedef std::vector<TimePointType> TimePointVector;
338 TimePointVector timePoints;
340 if (dictionary.HasKey(PROPERTY_NAME_TIMEGEOMETRY_TIMEPOINTS))
344 else if (dictionary.HasKey(PROPERTY_KEY_TIMEGEOMETRY_TIMEPOINTS))
349 if (timePoints.size() - 1 != image->GetDimension(3))
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"
358 TimePointVector::const_iterator pos = timePoints.begin();
359 TimePointVector::const_iterator prePos = pos++;
361 for (; pos != timePoints.end(); ++prePos, ++pos)
363 arbitraryTimeGeometry->AppendTimeStepClone(slicedGeometry, *pos, *prePos);
366 timeGeometry = arbitraryTimeGeometry;
371 if (timeGeometry.IsNull())
375 propTimeGeometry->Initialize(slicedGeometry, image->GetDimension(3));
376 timeGeometry = propTimeGeometry;
379 image->SetTimeGeometry(timeGeometry);
382 MITK_INFO <<
"number of image components: " << image->GetPixelType().GetNumberOfComponents() << std::endl;
384 for (itk::MetaDataDictionary::ConstIterator iter = dictionary.Begin(), iterEnd = dictionary.End(); iter != iterEnd;
387 if (iter->second->GetMetaDataObjectTypeInfo() ==
typeid(std::string))
389 const std::string &key = iter->first;
390 std::string assumedPropertyName = key;
391 std::replace(assumedPropertyName.begin(), assumedPropertyName.end(),
'_',
'.');
399 return x.IsNotNull() && x->GetMimeTypeName() == mimeTypeName;
401 auto finding = std::find_if(infoList.begin(), infoList.end(), predicate);
403 if (finding == infoList.end())
408 finding = std::find_if(infoList.begin(), infoList.end(), predicateWild);
413 if (finding != infoList.end())
415 assumedPropertyName = (*finding)->GetName();
421 newInfo->SetNameAndKey(assumedPropertyName, key);
427 dynamic_cast<itk::MetaDataObject<std::string> *
>(iter->second.GetPointer())->GetMetaDataObjectValue();
431 image->SetProperty(assumedPropertyName.c_str(), loadedProp);
435 bool isDefaultKey(
false);
437 for (
const auto &defaultKey : m_DefaultMetaDataKeys)
439 if (defaultKey.length() <= assumedPropertyName.length())
442 if (assumedPropertyName.substr(0, defaultKey.length()).find(defaultKey) != std::string::npos)
457 MITK_INFO <<
"...finished!" << std::endl;
459 result.push_back(image.GetPointer());
474 mitkThrow() <<
"Cannot write non-image data";
485 if (image->
GetDimension() == 2 && !geometry->Is2DConvertable())
487 MITK_WARN <<
"Saving a 2D image with 3D geometry information. Geometry information will be lost! You might "
488 "consider using Convert2Dto3DImageFilter before saving.";
492 affTrans->SetIdentity();
495 geometry->SetIndexToWorldTransform(affTrans);
496 geometry->SetSpacing(spacing);
497 geometry->SetOrigin(origin);
503 MITK_INFO <<
"Writing image: " << path << std::endl;
511 const unsigned int *
const dimensions = image->
GetDimensions();
518 itk::Vector<double, 4u> spacing4D;
519 spacing4D[0] = mitkSpacing[0];
520 spacing4D[1] = mitkSpacing[1];
521 spacing4D[2] = mitkSpacing[2];
524 itk::Vector<double, 4u> origin4D;
525 origin4D[0] = mitkOrigin[0];
526 origin4D[1] = mitkOrigin[1];
527 origin4D[2] = mitkOrigin[2];
531 m_ImageIO->SetNumberOfDimensions(dimension);
534 static_cast<itk::ImageIOBase::IOComponentType
>(pixelType.
GetComponentType()) :
535 itk::ImageIOBase::UNKNOWNCOMPONENTTYPE);
538 itk::ImageIORegion ioRegion(dimension);
540 for (
unsigned int i = 0; i < dimension; i++)
542 m_ImageIO->SetDimensions(i, dimensions[i]);
543 m_ImageIO->SetSpacing(i, spacing4D[i]);
544 m_ImageIO->SetOrigin(i, origin4D[i]);
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];
563 vnl_vector<double> axisDirection(dimension);
564 for (
unsigned int j = 0; j < dimension; j++)
566 axisDirection[j] = direction4D[j] / spacing4D[i];
568 m_ImageIO->SetDirection(i, axisDirection);
575 m_ImageIO->UseCompressionOn();
577 m_ImageIO->SetIORegion(ioRegion);
578 m_ImageIO->SetFileName(path);
584 itk::EncapsulateMetaData<std::string>(m_ImageIO->GetMetaDataDictionary(),
588 std::stringstream stream;
594 std::string data = stream.str();
596 itk::EncapsulateMetaData<std::string>(
603 for (
const auto &property : *imagePropertyList->GetMap())
608 if (infoList.empty())
613 std::string value = infoList.front()->GetSerializationFunction()(
property.second);
620 std::string key = infoList.front()->GetKey();
622 itk::EncapsulateMetaData<std::string>(m_ImageIO->GetMetaDataDictionary(), key, value);
626 m_ImageIO->Write(imageAccess.
GetData());
628 catch (
const std::exception &e)
644 if (!m_ImageIO->SupportsDimension(image->
GetDimension()))
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");
static MimeTypeNameType ANY_MIMETYPE_NAME()
static const char * GetStaticNameOfClass()
itk::SmartPointer< Self > Pointer
void SetSpacing(const mitk::Vector3D &aSpacing, bool enforceSetSpacing=false)
Set the spacing (m_Spacing).
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.
const char *const PROPERTY_NAME_TIMEGEOMETRY_TIMEPOINTS
std::string GetFileName()
ItkImageIO(itk::ImageIOBase::Pointer imageIO)
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.
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,...)
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.
static std::string DEFAULT_BASE_NAME()
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())
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.
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.
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)
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...
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.
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.
static const char * GetStaticNameOfClass()
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.
Abstract class for implementing a reader and writer.
virtual TimeStepType CountTimeSteps() const
Returns the number of time steps.
Class for defining the data type of pixels.
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.