Skip to content

Commit e94bb37

Browse files
jhlegarretahjmjohnson
authored andcommitted
ENH: Use strongly typed enums for itk::NiftiImageIO readable formats
Use strongly typed enums to define the file formats readable by the `itk::NiftiImageIO` class, Take advantage of the commit to gather the strongly typed enums in `itk::NiftiImageIO` into a common `itk::NiftiImageIOEnums` class so that it can be wrapped.
1 parent 63150f0 commit e94bb37

File tree

8 files changed

+200
-92
lines changed

8 files changed

+200
-92
lines changed

Modules/IO/NIFTI/include/itkNiftiImageIO.h

Lines changed: 59 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -28,28 +28,58 @@
2828
namespace itk
2929
{
3030

31-
32-
/** \class Analyze75Flavor
31+
/**\class NiftiImageIOEnums
32+
* \brief
3333
* \ingroup ITKIONIFTI
34-
* Enum used to define way to treat legacy Analyze75 files
3534
*/
36-
enum class Analyze75Flavor : uint8_t
35+
class NiftiImageIOEnums
3736
{
38-
/** Behavior introduced in ITK4.0 by NIFTI reader interpreting Analyze files */
39-
AnalyzeITK4 = 4,
40-
/** Will ignore orientation code and negative pixel dimensions */
41-
AnalyzeFSL = 3,
42-
/** Will ignore orientation code and respect negative pixel dimensions */
43-
AnalyzeSPM = 2,
44-
/** Same as AnalyzeITK4 but will show warning about deprecated file format (Default)*/
45-
AnalyzeITK4Warning = 1,
46-
/** Reject Analyze files as potentially wrong */
47-
AnalyzeReject = 0
37+
public:
38+
/** \class Analyze75Flavor
39+
* \ingroup ITKIONIFTI
40+
* Enum used to define the way to treat legacy Analyze75 files.
41+
*/
42+
enum class Analyze75Flavor : uint8_t
43+
{
44+
/** Behavior introduced in ITK4.0 by NIFTI reader interpreting Analyze files */
45+
AnalyzeITK4 = 4,
46+
/** Will ignore orientation code and negative pixel dimensions */
47+
AnalyzeFSL = 3,
48+
/** Will ignore orientation code and respect negative pixel dimensions */
49+
AnalyzeSPM = 2,
50+
/** Same as AnalyzeITK4 but will show warning about deprecated file format (Default)*/
51+
AnalyzeITK4Warning = 1,
52+
/** Reject Analyze files as potentially wrong */
53+
AnalyzeReject = 0
54+
};
55+
56+
/** \class NiftiFileEnum
57+
* \ingroup ITKIONIFTI
58+
* Enum used to define the possible file formats readable by this ImageIO implementation.
59+
*/
60+
enum class NiftiFileEnum : int8_t
61+
{
62+
/** 2-file Nifti (consisting of .hdr and .img file). */
63+
TwoFileNifti = 2,
64+
/** 1-file Nifti (consisting of .nii file). */
65+
OneFileNifti = 1,
66+
/** Legacy Analyze 7.5 format (consisting of .hdr and .img file). */
67+
Analyze75 = 0,
68+
/** Some other file format, or file system error. */
69+
OtherOrError = -1,
70+
};
4871
};
4972

73+
/** Backwards compatibility for enum values */
74+
#if !defined(ITK_LEGACY_REMOVE)
75+
using Analyze75Flavor = NiftiImageIOEnums::Analyze75Flavor;
76+
#endif
77+
5078
/** Define how to print enumerations */
5179
extern ITKIONIFTI_EXPORT std::ostream &
52-
operator<<(std::ostream & out, const Analyze75Flavor value);
80+
operator<<(std::ostream & out, const NiftiImageIOEnums::Analyze75Flavor value);
81+
extern ITKIONIFTI_EXPORT std::ostream &
82+
operator<<(std::ostream & out, const NiftiImageIOEnums::NiftiFileEnum value);
5383

5484
/**
5585
*\class NiftiImageIO
@@ -82,28 +112,24 @@ class ITKIONIFTI_EXPORT NiftiImageIO : public ImageIOBase
82112

83113
//-------- This part of the interfaces deals with reading data. -----
84114

85-
/** Possible file formats readable by this ImageIO implementation.
86-
* Used by DetermineFileType(). */
87-
enum FileType
88-
{
89-
/** 2-file Nifti (consisting of .hdr and .img file). */
90-
TwoFileNifti = 2,
91-
/** 1-file Nifti (consisting of .nii file). */
92-
OneFileNifti = 1,
93-
/** Legacy Analyze 7.5 format (consisting of .hdr and .img file). */
94-
Analyze75 = 0,
95-
/** Some other file format, or file system error. */
96-
OtherOrError = -1,
97-
};
98-
115+
#if !defined(ITK_LEGACY_REMOVE)
116+
/** Backwards compatibility for enum values */
117+
using FileType = NiftiImageIOEnums::NiftiFileEnum;
118+
// We need to expose the enum values at the class level
119+
// for backwards compatibility
120+
static constexpr FileType TwoFileNifti = NiftiImageIOEnums::NiftiFileEnum::TwoFileNifti;
121+
static constexpr FileType OneFileNifti = NiftiImageIOEnums::NiftiFileEnum::OneFileNifti;
122+
static constexpr FileType Analyze75 = NiftiImageIOEnums::NiftiFileEnum::Analyze75;
123+
static constexpr FileType OtherOrError = NiftiImageIOEnums::NiftiFileEnum::OtherOrError;
124+
#endif
99125

100126
/** Reads the file to determine if it can be read with this ImageIO implementation,
101127
* and to determine what kind of file it is (Analyze vs NIfTI). Note that the value
102128
* of LegacyAnalyze75Mode is ignored by this method.
103129
* \param FileNameToRead The name of the file to test for reading.
104130
* \return Returns one of the IOFileEnum enumerations.
105131
*/
106-
FileType
132+
NiftiImageIOEnums::NiftiFileEnum
107133
DetermineFileType(const char * FileNameToRead);
108134

109135
/** Reads the file to determine if it can be read with this ImageIO implementation.
@@ -159,8 +185,8 @@ class ITKIONIFTI_EXPORT NiftiImageIO : public ImageIOBase
159185
* the nifti library maintainers. This format does not properly respect the file orientation fields.
160186
* By default this is set by configuration option ITK_NIFTI_IO_ANALYZE_FLAVOR
161187
*/
162-
itkSetMacro(LegacyAnalyze75Mode, Analyze75Flavor);
163-
itkGetConstMacro(LegacyAnalyze75Mode, Analyze75Flavor);
188+
itkSetMacro(LegacyAnalyze75Mode, NiftiImageIOEnums::Analyze75Flavor);
189+
itkGetConstMacro(LegacyAnalyze75Mode, NiftiImageIOEnums::Analyze75Flavor);
164190

165191
protected:
166192
NiftiImageIO();
@@ -214,7 +240,7 @@ class ITKIONIFTI_EXPORT NiftiImageIO : public ImageIOBase
214240

215241
IOComponentEnum m_OnDiskComponentType{ IOComponentEnum::UNKNOWNCOMPONENTTYPE };
216242

217-
Analyze75Flavor m_LegacyAnalyze75Mode;
243+
NiftiImageIOEnums::Analyze75Flavor m_LegacyAnalyze75Mode;
218244
};
219245

220246

Modules/IO/NIFTI/src/itkNiftiImageIO.cxx

Lines changed: 42 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -787,7 +787,7 @@ NiftiImageIO::Read(void * buffer)
787787
}
788788
}
789789

790-
NiftiImageIO::FileType
790+
NiftiImageIOEnums::NiftiFileEnum
791791
NiftiImageIO::DetermineFileType(const char * FileNameToRead)
792792
{
793793
// is_nifti_file returns
@@ -797,7 +797,7 @@ NiftiImageIO::DetermineFileType(const char * FileNameToRead)
797797
// == -1 for an error,
798798
const int imageFTYPE = is_nifti_file(FileNameToRead);
799799

800-
return static_cast<NiftiImageIO::FileType>(imageFTYPE);
800+
return static_cast<NiftiImageIOEnums::NiftiFileEnum>(imageFTYPE);
801801
}
802802

803803
// This method will only test if the header looks like an
@@ -816,7 +816,7 @@ NiftiImageIO ::CanReadFile(const char * FileNameToRead)
816816
{
817817
return true;
818818
}
819-
else if (imageFTYPE == 0 && (this->GetLegacyAnalyze75Mode() != Analyze75Flavor::AnalyzeReject))
819+
else if (imageFTYPE == 0 && (this->GetLegacyAnalyze75Mode() != NiftiImageIOEnums::Analyze75Flavor::AnalyzeReject))
820820
{
821821
return true;
822822
}
@@ -997,15 +997,15 @@ NiftiImageIO ::ReadImageInformation()
997997
const int image_FTYPE = is_nifti_file(this->GetFileName());
998998
if (image_FTYPE == 0)
999999
{
1000-
if (this->GetLegacyAnalyze75Mode() == Analyze75Flavor::AnalyzeReject)
1000+
if (this->GetLegacyAnalyze75Mode() == NiftiImageIOEnums::Analyze75Flavor::AnalyzeReject)
10011001
{
10021002
itkExceptionMacro(<< this->GetFileName()
10031003
<< " is Analyze file and reader is instructed to reject it, specify preferred Analyze flavor "
10041004
"using SetLegacyAnalyze75Mode ");
10051005
}
10061006
else
10071007
{
1008-
if (this->GetLegacyAnalyze75Mode() == Analyze75Flavor::AnalyzeITK4Warning)
1008+
if (this->GetLegacyAnalyze75Mode() == NiftiImageIOEnums::Analyze75Flavor::AnalyzeITK4Warning)
10091009
itkWarningMacro(<< this->GetFileName() << " is Analyze file and it's deprecated ");
10101010
// to disable this message, specify preferred Analyze flavor using SetLegacyAnalyze75Mode
10111011
}
@@ -1283,8 +1283,8 @@ NiftiImageIO ::ReadImageInformation()
12831283
break;
12841284
}
12851285
// see http://www.grahamwideman.com/gw/brain/analyze/formatdoc.htm
1286-
bool ignore_negative_pixdim =
1287-
this->m_NiftiImage->nifti_type == 0 && this->GetLegacyAnalyze75Mode() == Analyze75Flavor::AnalyzeFSL;
1286+
bool ignore_negative_pixdim = this->m_NiftiImage->nifti_type == 0 &&
1287+
this->GetLegacyAnalyze75Mode() == NiftiImageIOEnums::Analyze75Flavor::AnalyzeFSL;
12881288

12891289
const int dims = this->GetNumberOfDimensions();
12901290
switch (dims)
@@ -1797,8 +1797,9 @@ NiftiImageIO::SetImageIOOrientationFromNIfTI(unsigned short int dims)
17971797
m_Origin[2] = 0.0;
17981798
}
17991799

1800-
if (this->m_NiftiImage->nifti_type == 0 && this->GetLegacyAnalyze75Mode() != Analyze75Flavor::AnalyzeITK4 &&
1801-
this->GetLegacyAnalyze75Mode() != Analyze75Flavor::AnalyzeITK4Warning)
1800+
if (this->m_NiftiImage->nifti_type == 0 &&
1801+
this->GetLegacyAnalyze75Mode() != NiftiImageIOEnums::Analyze75Flavor::AnalyzeITK4 &&
1802+
this->GetLegacyAnalyze75Mode() != NiftiImageIOEnums::Analyze75Flavor::AnalyzeITK4Warning)
18021803
{ // only do this for Analyze file format
18031804
SpatialOrientationAdapter::OrientationType orient;
18041805
switch (this->m_NiftiImage->analyze75_orient)
@@ -2267,25 +2268,44 @@ NiftiImageIO ::Write(const void * buffer)
22672268
}
22682269
}
22692270

2270-
/** Define how to print enumerations */
22712271
std::ostream &
2272-
operator<<(std::ostream & out, const Analyze75Flavor value)
2272+
operator<<(std::ostream & out, const NiftiImageIOEnums::Analyze75Flavor value)
22732273
{
22742274
return out << [value] {
22752275
switch (value)
22762276
{
2277-
case Analyze75Flavor::AnalyzeReject:
2278-
return "Analyze75Flavor::AnalyzeReject";
2279-
case Analyze75Flavor::AnalyzeITK4:
2280-
return "Analyze75Flavor::AnalyzeITK4";
2281-
case Analyze75Flavor::AnalyzeITK4Warning:
2282-
return "Analyze75Flavor::AnalyzeITK4Warning";
2283-
case Analyze75Flavor::AnalyzeSPM:
2284-
return "Analyze75Flavor::AnalyzeSPM";
2285-
case Analyze75Flavor::AnalyzeFSL:
2286-
return "Analyze75Flavor::AnalyzeFSL";
2277+
case NiftiImageIOEnums::Analyze75Flavor::AnalyzeReject:
2278+
return "itk::NiftiImageIOEnums::Analyze75Flavor::AnalyzeReject";
2279+
case NiftiImageIOEnums::Analyze75Flavor::AnalyzeITK4:
2280+
return "itk::NiftiImageIOEnums::Analyze75Flavor::AnalyzeITK4";
2281+
case NiftiImageIOEnums::Analyze75Flavor::AnalyzeITK4Warning:
2282+
return "itk::NiftiImageIOEnums::Analyze75Flavor::AnalyzeITK4Warning";
2283+
case NiftiImageIOEnums::Analyze75Flavor::AnalyzeSPM:
2284+
return "itk::NiftiImageIOEnums::Analyze75Flavor::AnalyzeSPM";
2285+
case NiftiImageIOEnums::Analyze75Flavor::AnalyzeFSL:
2286+
return "itk::NiftiImageIOEnums::Analyze75Flavor::AnalyzeFSL";
22872287
default:
2288-
return "INVALID VALUE FOR Analyze75Flavor";
2288+
return "INVALID VALUE FOR itk::NiftiImageIOEnums::Analyze75Flavor";
2289+
}
2290+
}();
2291+
}
2292+
2293+
std::ostream &
2294+
operator<<(std::ostream & out, const NiftiImageIOEnums::NiftiFileEnum value)
2295+
{
2296+
return out << [value] {
2297+
switch (value)
2298+
{
2299+
case NiftiImageIOEnums::NiftiFileEnum::TwoFileNifti:
2300+
return "itk::NiftiImageIOEnums::TwoFileNifti";
2301+
case NiftiImageIOEnums::NiftiFileEnum::OneFileNifti:
2302+
return "itk::NiftiImageIOEnums::NiftiFileEnum::OneFileNifti";
2303+
case NiftiImageIOEnums::NiftiFileEnum::Analyze75:
2304+
return "itk::NiftiImageIOEnums::NiftiFileEnum::Analyze75";
2305+
case NiftiImageIOEnums::NiftiFileEnum::OtherOrError:
2306+
return "itk::NiftiImageIOEnums::NiftiFileEnum::OtherOrError";
2307+
default:
2308+
return "INVALID VALUE FOR itk::NiftiImageIOEnums::NiftiFileEnum";
22892309
}
22902310
}();
22912311
}

Modules/IO/NIFTI/src/itkNiftiImageIOConfigurePrivate.h.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@
2222
// IO/NIFTI module and should not be installed.
2323

2424
// Analyze default flavour
25-
#define ITK_NIFTI_IO_ANALYZE_FLAVOR_DEFAULT Analyze75Flavor::Analyze@ITK_NIFTI_IO_ANALYZE_FLAVOR@
25+
#define ITK_NIFTI_IO_ANALYZE_FLAVOR_DEFAULT NiftiImageIOEnums::Analyze75Flavor::Analyze@ITK_NIFTI_IO_ANALYZE_FLAVOR@
2626

2727
#endif //itkNiftiImageIOConfigurePrivate_h

Modules/IO/NIFTI/test/itkNiftiImageIOTest.cxx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ itkNiftiImageIOTest(int ac, char * av[])
128128
ImageType::Pointer input;
129129
itk::NiftiImageIO::Pointer imageIO = itk::NiftiImageIO::New();
130130
// enable old behavior of NIFTI reader
131-
imageIO->SetLegacyAnalyze75Mode(itk::Analyze75Flavor::AnalyzeITK4);
131+
imageIO->SetLegacyAnalyze75Mode(itk::NiftiImageIOEnums::Analyze75Flavor::AnalyzeITK4);
132132
for (int imagenameindex = 1; imagenameindex < ac; imagenameindex++)
133133
{
134134
try
@@ -230,5 +230,8 @@ itkNiftiImageIOTest(int ac, char * av[])
230230
}
231231
// This was made a protected function. MyFactoryTest->PrintSelf(std::cout,0);
232232
}
233+
234+
TestEnumStreaming();
235+
233236
return rval;
234237
}

Modules/IO/NIFTI/test/itkNiftiImageIOTest.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -572,5 +572,6 @@ int
572572
TestNiftiByteSwap(const std::string & prefix);
573573
void
574574
RemoveNiftiByteSwapTestFiles(const std::string & prefix);
575-
575+
void
576+
TestEnumStreaming();
576577
#endif

Modules/IO/NIFTI/test/itkNiftiImageIOTestHelper.cxx

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
*
1717
*=========================================================================*/
1818

19+
#include <set>
1920
#include "itkNiftiImageIOTest.h"
2021

2122
// The WriteNiftiTestFiles function writes binary data to disk to ensure that both big and little endian files are
@@ -124,3 +125,32 @@ RemoveNiftiByteSwapTestFiles(const std::string & prefix)
124125
itk::IOTestHelper::Remove((prefix + "NiftiBigEndian.hdr").c_str());
125126
itk::IOTestHelper::Remove((prefix + "NiftiBigEndian.img").c_str());
126127
}
128+
129+
void
130+
TestEnumStreaming()
131+
{
132+
// Test streaming enumeration for Analyze75Flavor elements
133+
const std::set<itk::NiftiImageIOEnums::Analyze75Flavor> allAnalyze75Flavor{
134+
itk::NiftiImageIOEnums::Analyze75Flavor::AnalyzeReject,
135+
itk::NiftiImageIOEnums::Analyze75Flavor::AnalyzeITK4,
136+
itk::NiftiImageIOEnums::Analyze75Flavor::AnalyzeITK4Warning,
137+
itk::NiftiImageIOEnums::Analyze75Flavor::AnalyzeSPM,
138+
itk::NiftiImageIOEnums::Analyze75Flavor::AnalyzeFSL
139+
};
140+
for (const auto & ee : allAnalyze75Flavor)
141+
{
142+
std::cout << "STREAMED ENUM VALUE itk::NiftiImageIOEnums::Analyze75Flavor: " << ee << std::endl;
143+
}
144+
145+
// Test streaming enumeration for NiftiFileEnum elements
146+
const std::set<itk::NiftiImageIOEnums::NiftiFileEnum> allNiftiFileEnum{
147+
itk::NiftiImageIOEnums::NiftiFileEnum::TwoFileNifti,
148+
itk::NiftiImageIOEnums::NiftiFileEnum::OneFileNifti,
149+
itk::NiftiImageIOEnums::NiftiFileEnum::Analyze75,
150+
itk::NiftiImageIOEnums::NiftiFileEnum::OtherOrError
151+
};
152+
for (const auto & ee : allNiftiFileEnum)
153+
{
154+
std::cout << "STREAMED ENUM VALUE itk::NiftiImageIOEnums::NiftiFileEnum: " << ee << std::endl;
155+
}
156+
}

0 commit comments

Comments
 (0)