25 #include <itkImageFileReader.h> 26 #include <itkImageIOFactory.h> 27 #include <itkImageIORegion.h> 28 #include <itkMetaDataObject.h> 40 :
AbstractFileIO(other), m_ImageIO(dynamic_cast<
itk::ImageIOBase *>(other.m_ImageIO->
Clone().GetPointer()))
42 this->InitializeDefaultMetaDataKeys();
47 std::vector<std::string> extensions;
49 if (imageIOName ==
"GiplImageIO")
51 extensions.push_back(
"gipl");
52 extensions.push_back(
"gipl.gz");
54 else if (imageIOName ==
"GDCMImageIO")
56 extensions.push_back(
"gdcm");
57 extensions.push_back(
"dcm");
58 extensions.push_back(
"DCM");
59 extensions.push_back(
"dc3");
60 extensions.push_back(
"DC3");
61 extensions.push_back(
"ima");
62 extensions.push_back(
"img");
64 else if (imageIOName ==
"PNGImageIO")
66 extensions.push_back(
"png");
67 extensions.push_back(
"PNG");
69 else if (imageIOName ==
"StimulateImageIO")
71 extensions.push_back(
"spr");
73 else if (imageIOName ==
"HDF5ImageIO")
75 extensions.push_back(
"hdf");
76 extensions.push_back(
"h4");
77 extensions.push_back(
"hdf4");
78 extensions.push_back(
"h5");
79 extensions.push_back(
"hdf5");
80 extensions.push_back(
"he4");
81 extensions.push_back(
"he5");
82 extensions.push_back(
"hd5");
84 else if (
"GE4ImageIO" == imageIOName ||
"GE5ImageIO" == imageIOName ||
"Bruker2dseqImageIO" == imageIOName)
86 extensions.push_back(
"");
89 if (!extensions.empty())
91 MITK_DEBUG <<
"Fixing up known extensions for " << imageIOName;
99 if (
"GE4ImageIO" == imageIOName)
103 else if (
"GE5ImageIO" == imageIOName)
107 else if (
"Bruker2dseqImageIO" == imageIOName)
116 if (m_ImageIO.IsNull())
118 mitkThrow() <<
"ITK ImageIOBase argument must not be nullptr";
124 std::vector<std::string> readExtensions = m_ImageIO->GetSupportedReadExtensions();
126 if (readExtensions.empty())
128 std::string imageIOName = m_ImageIO->GetNameOfClass();
129 MITK_DEBUG <<
"ITK ImageIOBase " << imageIOName <<
" does not provide read extensions";
135 for (std::vector<std::string>::const_iterator iter = readExtensions.begin(), endIter = readExtensions.end();
139 std::string extension = *iter;
140 if (!extension.empty() && extension[0] ==
'.')
142 extension.assign(iter->begin() + 1, iter->end());
148 if (extensions.empty() || (extensions.size() == 1 && extensions[0].empty()))
150 std::string imageIOName = m_ImageIO->GetNameOfClass();
156 std::vector<std::string> writeExtensions = imageIO->GetSupportedWriteExtensions();
157 if (writeExtensions.empty())
159 std::string imageIOName = imageIO->GetNameOfClass();
160 MITK_DEBUG <<
"ITK ImageIOBase " << imageIOName <<
" does not provide write extensions";
164 if (writeExtensions != readExtensions)
168 for (std::vector<std::string>::const_iterator iter = writeExtensions.begin(), endIter = writeExtensions.end();
172 std::string extension = *iter;
173 if (!extension.empty() && extension[0] ==
'.')
175 extension.assign(iter->begin() + 1, iter->end());
181 if (extensions.empty() || (extensions.size() == 1 && extensions[0].empty()))
183 std::string imageIOName = m_ImageIO->GetNameOfClass();
190 std::string description = std::string(
"ITK ") + imageIO->GetNameOfClass();
198 :
AbstractFileIO(
Image::GetStaticNameOfClass(), mimeType,
std::string(
"ITK ") + imageIO->GetNameOfClass()),
201 if (m_ImageIO.IsNull())
203 mitkThrow() <<
"ITK ImageIOBase argument must not be nullptr";
222 const auto *timeGeometryTimeData =
223 dynamic_cast<const itk::MetaDataObject<std::string> *
>(data);
224 std::vector<TimePointType> result;
226 if (timeGeometryTimeData)
228 std::string dataStr = timeGeometryTimeData->GetMetaDataObjectValue();
229 std::stringstream stream(dataStr);
233 result.push_back(tp);
242 std::vector<BaseData::Pointer> result;
247 const unsigned int MINDIM = 2;
248 const unsigned int MAXDIM = 4;
252 MITK_INFO <<
"loading " << path <<
" via itk::ImageIOFactory... " << std::endl;
257 mitkThrow() <<
"Empty filename in mitk::ItkImageIO ";
262 m_ImageIO->SetFileName(path);
263 m_ImageIO->ReadImageInformation();
265 unsigned int ndim = m_ImageIO->GetNumberOfDimensions();
266 if (ndim < MINDIM || ndim > MAXDIM)
268 MITK_WARN <<
"Sorry, only dimensions 2, 3 and 4 are supported. The given file has " << ndim
269 <<
" dimensions! Reading as 4D.";
273 itk::ImageIORegion ioRegion(ndim);
274 itk::ImageIORegion::SizeType ioSize = ioRegion.GetSize();
275 itk::ImageIORegion::IndexType ioStart = ioRegion.GetIndex();
277 unsigned int dimensions[MAXDIM];
293 for (i = 0; i < ndim; ++i)
296 ioSize[i] = m_ImageIO->GetDimensions(i);
299 dimensions[i] = m_ImageIO->GetDimensions(i);
300 spacing[i] = m_ImageIO->GetSpacing(i);
306 origin[i] = m_ImageIO->GetOrigin(i);
310 ioRegion.SetSize(ioSize);
311 ioRegion.SetIndex(ioStart);
313 MITK_INFO <<
"ioRegion: " << ioRegion << std::endl;
314 m_ImageIO->SetIORegion(ioRegion);
315 void *buffer =
new unsigned char[m_ImageIO->GetImageSizeInBytes()];
316 m_ImageIO->Read(buffer);
318 image->Initialize(
MakePixelType(m_ImageIO), ndim, dimensions);
321 const itk::MetaDataDictionary &dictionary = m_ImageIO->GetMetaDataDictionary();
325 matrix.SetIdentity();
326 unsigned int j, itkDimMax3 = (ndim >= 3 ? 3 : ndim);
327 for (i = 0; i < itkDimMax3; ++i)
328 for (j = 0; j < itkDimMax3; ++j)
329 matrix[i][j] = m_ImageIO->GetDirection(j)[i];
332 PlaneGeometry *planeGeometry = image->GetSlicedGeometry(0)->GetPlaneGeometry(0);
347 if (dictionary.HasKey(PROPERTY_NAME_TIMEGEOMETRY_TYPE) || dictionary.HasKey(PROPERTY_KEY_TIMEGEOMETRY_TYPE))
350 itk::MetaDataObject<std::string>::ConstPointer timeGeometryTypeData =
nullptr;
351 if (dictionary.HasKey(PROPERTY_NAME_TIMEGEOMETRY_TYPE))
353 timeGeometryTypeData =
354 dynamic_cast<const itk::MetaDataObject<std::string> *
>(dictionary.Get(PROPERTY_NAME_TIMEGEOMETRY_TYPE));
358 timeGeometryTypeData =
359 dynamic_cast<const itk::MetaDataObject<std::string> *
>(dictionary.Get(PROPERTY_KEY_TIMEGEOMETRY_TYPE));
365 typedef std::vector<TimePointType> TimePointVector;
366 TimePointVector timePoints;
368 if (dictionary.HasKey(PROPERTY_NAME_TIMEGEOMETRY_TIMEPOINTS))
372 else if (dictionary.HasKey(PROPERTY_KEY_TIMEGEOMETRY_TIMEPOINTS))
377 if (timePoints.size() - 1 != image->GetDimension(3))
379 MITK_ERROR <<
"Stored timepoints (" << timePoints.size() - 1 <<
") and size of image time dimension (" 380 << image->GetDimension(3) <<
") do not match. Switch to ProportionalTimeGeometry fallback" 386 TimePointVector::const_iterator pos = timePoints.begin();
389 for (; pos != timePoints.end(); ++prePos, ++pos)
391 arbitraryTimeGeometry->AppendNewTimeStepClone(slicedGeometry, *prePos, *pos);
394 timeGeometry = arbitraryTimeGeometry;
399 if (timeGeometry.IsNull())
403 propTimeGeometry->Initialize(slicedGeometry, image->GetDimension(3));
404 timeGeometry = propTimeGeometry;
407 image->SetTimeGeometry(timeGeometry);
410 MITK_INFO <<
"number of image components: " << image->GetPixelType().GetNumberOfComponents() << std::endl;
412 for (
auto iter = dictionary.Begin(), iterEnd = dictionary.End(); iter != iterEnd;
415 if (iter->second->GetMetaDataObjectTypeInfo() ==
typeid(std::string))
417 const std::string &key = iter->first;
418 std::string assumedPropertyName = key;
419 std::replace(assumedPropertyName.begin(), assumedPropertyName.end(),
'_',
'.');
427 return x.IsNotNull() && x->GetMimeTypeName() == mimeTypeName;
429 auto finding = std::find_if(infoList.begin(), infoList.end(), predicate);
431 if (finding == infoList.end())
436 finding = std::find_if(infoList.begin(), infoList.end(), predicateWild);
441 if (finding != infoList.end())
443 assumedPropertyName = (*finding)->GetName();
449 newInfo->SetNameAndKey(assumedPropertyName, key);
455 dynamic_cast<itk::MetaDataObject<std::string> *
>(iter->second.GetPointer())->GetMetaDataObjectValue();
459 image->SetProperty(assumedPropertyName.c_str(), loadedProp);
463 bool isDefaultKey(
false);
465 for (
const auto &defaultKey : m_DefaultMetaDataKeys)
467 if (defaultKey.length() <= assumedPropertyName.length())
470 if (assumedPropertyName.substr(0, defaultKey.length()).find(defaultKey) != std::string::npos)
485 MITK_INFO <<
"...finished!" << std::endl;
487 result.push_back(image.GetPointer());
500 if (
image ==
nullptr)
502 mitkThrow() <<
"Cannot write non-image data";
513 if (
image->GetDimension() == 2 && !geometry->Is2DConvertable())
515 MITK_WARN <<
"Saving a 2D image with 3D geometry information. Geometry information will be lost! You might " 516 "consider using Convert2Dto3DImageFilter before saving.";
519 mitk::AffineTransform3D::Pointer affTrans = mitk::AffineTransform3D::New();
520 affTrans->SetIdentity();
523 geometry->SetIndexToWorldTransform(affTrans);
524 geometry->SetSpacing(spacing);
525 geometry->SetOrigin(origin);
531 MITK_INFO <<
"Writing image: " << path << std::endl;
538 const unsigned int dimension =
image->GetDimension();
539 const unsigned int *
const dimensions =
image->GetDimensions();
546 itk::Vector<double, 4u> spacing4D;
547 spacing4D[0] = mitkSpacing[0];
548 spacing4D[1] = mitkSpacing[1];
549 spacing4D[2] = mitkSpacing[2];
552 itk::Vector<double, 4u> origin4D;
553 origin4D[0] = mitkOrigin[0];
554 origin4D[1] = mitkOrigin[1];
555 origin4D[2] = mitkOrigin[2];
559 m_ImageIO->SetNumberOfDimensions(dimension);
562 static_cast<itk::ImageIOBase::IOComponentType
>(pixelType.
GetComponentType()) :
563 itk::ImageIOBase::UNKNOWNCOMPONENTTYPE);
566 itk::ImageIORegion ioRegion(dimension);
568 for (
unsigned int i = 0; i < dimension; i++)
570 m_ImageIO->SetDimensions(i, dimensions[i]);
571 m_ImageIO->SetSpacing(i, spacing4D[i]);
572 m_ImageIO->SetOrigin(i, origin4D[i]);
575 mitkDirection.SetVnlVector(geometry->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(i));
576 itk::Vector<double, 4u> direction4D;
577 direction4D[0] = mitkDirection[0];
578 direction4D[1] = mitkDirection[1];
579 direction4D[2] = mitkDirection[2];
591 vnl_vector<double> axisDirection(dimension);
592 for (
unsigned int j = 0; j < dimension; j++)
594 axisDirection[j] = direction4D[j] / spacing4D[i];
596 m_ImageIO->SetDirection(i, axisDirection);
598 ioRegion.SetSize(i,
image->GetLargestPossibleRegion().GetSize(i));
599 ioRegion.SetIndex(i,
image->GetLargestPossibleRegion().GetIndex(i));
603 m_ImageIO->UseCompressionOn();
605 m_ImageIO->SetIORegion(ioRegion);
606 m_ImageIO->SetFileName(path);
612 itk::EncapsulateMetaData<std::string>(m_ImageIO->GetMetaDataDictionary(),
616 std::stringstream stream;
618 for (
TimeStepType pos = 0; pos < arbitraryTG->CountTimeSteps(); ++pos)
620 stream <<
" " << arbitraryTG->GetTimeBounds(pos)[1];
622 std::string data = stream.str();
624 itk::EncapsulateMetaData<std::string>(
631 for (
const auto &property : *imagePropertyList->GetMap())
636 if (infoList.empty())
641 std::string value = infoList.front()->GetSerializationFunction()(
property.second);
648 std::string key = infoList.front()->GetKey();
650 itk::EncapsulateMetaData<std::string>(m_ImageIO->GetMetaDataDictionary(), key, value);
654 m_ImageIO->Write(imageAccess.GetData());
656 catch (
const std::exception &e)
666 if (
image ==
nullptr)
672 if (!m_ImageIO->SupportsDimension(
image->GetDimension()))
676 if ((
image->GetDimension() == 3) && (
image->GetSlicedGeometry()->GetSlices() == 1))
683 if (
image->GetDimension() == 2 && !
image->GetGeometry()->Is2DConvertable())
693 this->m_DefaultMetaDataKeys.push_back(
"NRRD.space");
694 this->m_DefaultMetaDataKeys.push_back(
"NRRD.kinds");
695 this->m_DefaultMetaDataKeys.push_back(PROPERTY_NAME_TIMEGEOMETRY_TYPE);
696 this->m_DefaultMetaDataKeys.push_back(PROPERTY_NAME_TIMEGEOMETRY_TIMEPOINTS);
697 this->m_DefaultMetaDataKeys.push_back(
"ITK.InputFilterName");
static MimeTypeNameType ANY_MIMETYPE_NAME()
static const char * GetStaticNameOfClass()
void SetSpacing(const mitk::Vector3D &aSpacing, bool enforceSetSpacing=false)
Set the spacing (m_Spacing).
virtual InfoResultType GetInfoByKey(const std::string &persistenceKey, bool allowKeyRegEx=true) const =0
Get the persistence info that will use the specified key.
vcl_size_t GetNumberOfComponents() const
Get the number of components of which each element consists.
const char *const PROPERTY_NAME_TIMEGEOMETRY_TIMEPOINTS
std::string GetFileName()
std::string GetName() const
Returns the unique name for the MimeType.
ItkImageIO(itk::ImageIOBase::Pointer imageIO)
std::vector< TimePointType > ConvertMetaDataObjectToTimePointList(const itk::MetaDataObjectBase *data)
DataCollection - Class to facilitate loading/accessing structured data.
Point3D GetCornerPoint(int id) const
Get the position of the corner number id (in world coordinates)
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,...)
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...
int GetComponentType() const
Get the component type (the scalar (!) type). Each element may contain m_NumberOfComponents (more tha...
std::vector< std::string > GetExtensions() const
Returns all extensions that this MimeType can handle.
void SetRanking(int ranking)
Set the service ranking for this file writer.
std::string GetLocalFileName() const
Get a local file name for reading.
void SetMimeTypePrefix(const std::string &prefix)
ConfidenceLevel GetWriterConfidenceLevel() const override
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
virtual void FixUpCustomMimeTypeName(const std::string &imageIOName, CustomMimeType &customMimeType)
static std::string DEFAULT_BASE_NAME()
ConfidenceLevel
A confidence level describing the confidence of the reader or writer in handling the given data...
Convenience class to temporarily change the current locale.
static IPropertyPersistence * GetPropertyPersistence(us::ModuleContext *context=us::GetModuleContext())
Get an IPropertyPersistence instance.
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)
const BaseData * GetInput() const override
Get the input data set via SetInput().
Image class for storing images.
const char *const PROPERTY_NAME_TIMEGEOMETRY_TYPE
void SetReaderDescription(const std::string &description)
mitk::ScalarType TimePointType
A local file representation for streams.
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.
itk::ImageIOBase::IOPixelType GetPixelType() const
mitk::Image::Pointer image
virtual void InitializeDefaultMetaDataKeys()
void AddExtension(const std::string &extension)
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)
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
TimeBounds GetTimeBounds() const override
Get the time bounds (in ms) it returns GetMinimumTimePoint() and GetMaximumTimePoint() results as bou...
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)
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
static const char * GetStaticNameOfClass()
ImageReadAccessor class to get locked read access for a particular image part.
Abstract class for implementing a reader and writer.
std::string GetMimeTypePrefix() const
const CustomMimeType * GetMimeType() const
Class for defining the data type of pixels.
mitk::AffineTransform3D * GetIndexToWorldTransform()
Get the transformation used to convert from index to world coordinates.
void SetName(const std::string &name)