Skip to content

Commit 2e61183

Browse files
authored
Merge pull request #6137 from hjmjohnson/ingest-MGHIO
ENH: Ingest ITKMGHIO into Modules/IO
2 parents 3343437 + 0b37537 commit 2e61183

19 files changed

Lines changed: 1788 additions & 66 deletions

Modules/IO/MGHIO/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
project(MGHIO)
2+
set(MGHIO_LIBRARIES MGHIO)
3+
itk_module_impl()

Modules/IO/MGHIO/README.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# MGHIO
2+
3+
In-tree ITK module providing an `itk::MGHImageIO` plugin for the
4+
`.mgh` / `.mgz` (MGH) volume format used by the FreeSurfer
5+
neuroimaging toolchain. The factory `itk::MGHImageIOFactory`
6+
auto-registers with `itk::ImageIOFactory` so any
7+
`itk::ImageFileReader` / `itk::ImageFileWriter` transparently picks
8+
up `.mgh` / `.mgz` files when the module is enabled.
9+
10+
## Origin
11+
12+
Ingested from the standalone remote module
13+
[**InsightSoftwareConsortium/itkMGHImageIO**](https://github.com/InsightSoftwareConsortium/itkMGHImageIO)
14+
on 2026-04-27, at upstream commit
15+
[`af74507c`](https://github.com/InsightSoftwareConsortium/itkMGHImageIO/commit/af74507c1ddc82722637c37d1f5d169e3000553a).
16+
The upstream repository will be archived read-only after this PR
17+
merges; it remains reachable at the URL above.
18+
19+
## What lives here
20+
21+
Per the v3 ingestion strategy (see
22+
`Utilities/Maintenance/RemoteModuleIngest/INGESTION_STRATEGY.md`), only
23+
paths matching the narrow whitelist (code, headers, tests, wrapping,
24+
module CMake) crossed the merge boundary:
25+
26+
- `include/` — public C++ headers (`itkMGHImageIO.h`, `itkMGHImageIOFactory.h`).
27+
- `src/` — non-template implementation.
28+
- `test/` — CTest drivers and content-link stubs.
29+
- `wrapping/` — Python wrapping descriptors.
30+
- `CMakeLists.txt`, `itk-module.cmake` — build + module descriptors.
31+
32+
Every surviving commit preserves original authorship; `git blame`
33+
walks across the merge boundary to upstream authors going back to the
34+
module's earliest history.
35+
36+
## What was intentionally left upstream
37+
38+
Everything outside the whitelist stays in the archived upstream repo.
39+
If you need any of it, clone
40+
<https://github.com/InsightSoftwareConsortium/itkMGHImageIO>.
41+
42+
| Content in upstream | Why it did not ingest |
43+
|---|---|
44+
| `.github/`, `azure-pipelines.yml`, `Dockerfile` | Standalone-build CI scaffolding; not useful in-tree. |
45+
| `CTestConfig.cmake`, `pyproject.toml`, `LICENSE`, `.clang-format` | Packaging / CI / style scaffolding superseded by ITK root. |
46+
| Historical `Old/`, `paper/`, `docs/`, demo asset trees | Stripped by the whitelist to protect ITK's git pack from bloat. |
47+
48+
## Long-form documentation
49+
50+
- **Format reference** — see the FreeSurfer documentation:
51+
<https://surfer.nmr.mgh.harvard.edu/fswiki/FsTutorial/MghFormat>.
52+
- **Standalone build + history** — see the archived upstream at
53+
<https://github.com/InsightSoftwareConsortium/itkMGHImageIO>.
54+
55+
## Compliance level
56+
57+
Compliance Level 2 (Alpha — niche execution environment dependence:
58+
FreeSurfer-format I/O). Carried forward from the
59+
`MODULE_COMPLIANCE_LEVEL 2` declaration in the previous
60+
`Modules/Remote/MGHIO.remote.cmake`.
61+
62+
## Content-link status
63+
64+
The 3 input content-links under `test/MD5/` are already in `.cid`
65+
(IPFS Content Identifier) form; no `.md5``.cid` normalization is
66+
required for this module.
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
/*=========================================================================
2+
*
3+
* Copyright NumFOCUS
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* https://www.apache.org/licenses/LICENSE-2.0.txt
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*=========================================================================*/
18+
19+
#ifndef itkMGHImageIO_h
20+
#define itkMGHImageIO_h
21+
22+
#include "itkMatrix.h"
23+
#include "itkImageIOBase.h"
24+
#include <fstream>
25+
#include "itk_zlib.h"
26+
27+
#include "MGHIOExport.h"
28+
29+
namespace itk
30+
{
31+
/** \class MGHImageIO
32+
*
33+
* \author Hans J. Johnson
34+
* \brief Class that defines how to read MGH file format.
35+
* Originally developed as part of the Slicer software
36+
* package under grants XXXX
37+
*
38+
* \ingroup IOFilters
39+
* \ingroup MGHIO
40+
*/
41+
class MGHIO_EXPORT MGHImageIO : public ImageIOBase
42+
{
43+
public:
44+
/** Standard class type alias. */
45+
using Self = MGHImageIO;
46+
using Superclass = ImageIOBase;
47+
using Pointer = SmartPointer<Self>;
48+
49+
/** Method for creation through the object factory. */
50+
itkNewMacro(Self);
51+
52+
/** Run-time type information (and related methods). */
53+
itkOverrideGetNameOfClassMacro(MGHImageIO);
54+
55+
/*-------- This part of the interfaces deals with reading data. ----- */
56+
57+
/** Determine if the file can be read with this ImageIO implementation.
58+
* \param FileNameToRead The name of the file to test for reading.
59+
* \post Sets classes ImageIOBase::m_FileName variable to be FileNameToWrite
60+
* \return Returns true if this ImageIO can read the file specified.
61+
*/
62+
bool
63+
CanReadFile(const char * FileNameToRead) override;
64+
65+
/** Set the spacing and dimension information for the set filename. */
66+
void
67+
ReadImageInformation() override;
68+
69+
/** Reads the data from disk into the memory buffer provided. */
70+
void
71+
Read(void * pData) override;
72+
73+
/*-------- This part of the interfaces deals with writing data. ----- */
74+
75+
/** Determine if the file can be written with this ImageIO implementation.
76+
* \param FileNameToWrite The name of the file to test for writing.
77+
* \post Sets classes ImageIOBase::m_FileName variable to be FileNameToWrite
78+
* \return Returns true if this ImageIO can write the file specified.
79+
*/
80+
bool
81+
CanWriteFile(const char * name) override;
82+
83+
/** Set the spacing and dimension information for the set filename. */
84+
void
85+
WriteImageInformation() override;
86+
87+
/** Writes the data to disk from the memory buffer provided. Make sure
88+
* that the IORegions has been set properly. */
89+
void
90+
Write(const void * buffer) override;
91+
92+
protected:
93+
MGHImageIO();
94+
~MGHImageIO() override;
95+
void
96+
PrintSelf(std::ostream & os, Indent indent) const override;
97+
98+
void
99+
ReadVolumeHeader();
100+
101+
private:
102+
static const int MRI_UCHAR = 0;
103+
static const int MRI_INT = 1;
104+
static const int MRI_FLOAT = 3;
105+
static const int MRI_SHORT = 4;
106+
static const int MRI_TENSOR = 6;
107+
static const unsigned int FS_DIMENSION_HEADER_SIZE = sizeof(int) * 7;
108+
static const unsigned int FS_RAS_HEADER_SIZE = (sizeof(float) * 15) + sizeof(short);
109+
static const unsigned int FS_UNUSED_HEADER_SIZE = 256 - FS_RAS_HEADER_SIZE;
110+
static const unsigned int FS_WHOLE_HEADER_SIZE =
111+
FS_RAS_HEADER_SIZE + FS_DIMENSION_HEADER_SIZE + FS_UNUSED_HEADER_SIZE;
112+
113+
/** check if a filename is for a compressed file */
114+
bool
115+
IsCompressedFilename(const std::string fname);
116+
/// processes the actual data buffer
117+
void
118+
SwapBytesIfNecessary(void * const buffer, const unsigned long numberOfPixels);
119+
120+
/// examines the direction cosines and creates encapsulation data
121+
// void MriDirCos();
122+
123+
void
124+
WriteHeader();
125+
126+
void
127+
WriteData(const void * buffer);
128+
129+
void
130+
PermuteFrameValues(const void * buffer, char * tempmemory);
131+
132+
unsigned int
133+
GetComponentSize() const override;
134+
135+
std::string
136+
GetOrientation(itk::Matrix<double> directions);
137+
138+
bool m_IsCompressed;
139+
gzFile m_GZFile;
140+
std::ofstream m_Output;
141+
142+
// Utility function to assist with writing to disk in the
143+
// proper format. TInType is static_cast<TDiskType> type.
144+
template <typename TInType, typename TDiskType>
145+
int
146+
TWrite(const TInType inValue);
147+
template <typename TDiskType, typename TOutType>
148+
int
149+
TRead(TOutType & outValue);
150+
151+
int
152+
TWrite(const char * buf, const unsigned long count);
153+
void
154+
OpenFile();
155+
void
156+
CloseFile();
157+
};
158+
} // end namespace itk
159+
160+
#endif // itkMGHImageIO_h
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*=========================================================================
2+
*
3+
* Copyright NumFOCUS
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* https://www.apache.org/licenses/LICENSE-2.0.txt
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*=========================================================================*/
18+
19+
#ifndef itkMGHImageIOFactory_h
20+
#define itkMGHImageIOFactory_h
21+
22+
#include "itkObjectFactoryBase.h"
23+
#include "itkImageIOBase.h"
24+
25+
#include "MGHIOExport.h"
26+
27+
namespace itk
28+
{
29+
/** \class MGHImageIOFactory
30+
* \brief Create instances of MGHImageIO objects using an object factory.
31+
* \ingroup MGHIO
32+
*/
33+
class MGHIO_EXPORT MGHImageIOFactory : public ObjectFactoryBase
34+
{
35+
public:
36+
ITK_DISALLOW_COPY_AND_MOVE(MGHImageIOFactory);
37+
38+
/** Standard class type alias */
39+
using Self = MGHImageIOFactory;
40+
using Superclass = ObjectFactoryBase;
41+
using Pointer = SmartPointer<Self>;
42+
using ConstPointer = SmartPointer<const Self>;
43+
44+
/** Class methods used to interface with the registered factories **/
45+
const char *
46+
GetITKSourceVersion() const override;
47+
48+
const char *
49+
GetDescription() const override;
50+
51+
/** Method for class instantiation **/
52+
itkFactorylessNewMacro(Self);
53+
54+
/** Run-time type information (and related methods). */
55+
itkOverrideGetNameOfClassMacro(MGHImageIOFactory);
56+
57+
/** Register one factory of this type */
58+
static void
59+
RegisterOneFactory()
60+
{
61+
MGHImageIOFactory::Pointer MGHFactory = MGHImageIOFactory::New();
62+
63+
ObjectFactoryBase::RegisterFactoryInternal(MGHFactory);
64+
}
65+
66+
protected:
67+
MGHImageIOFactory();
68+
~MGHImageIOFactory() override;
69+
void
70+
PrintSelf(std::ostream & os, Indent indent) const override;
71+
};
72+
} // end namespace itk
73+
74+
#endif /// itkMGHImageIOFactory_h

Modules/IO/MGHIO/itk-module.cmake

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
set(
2+
DOCUMENTATION
3+
"This modules contains an ImageIO class to read or write the
4+
MGH file format that is an integral part of FreeSurfer based tools."
5+
)
6+
7+
itk_module(
8+
MGHIO
9+
ENABLE_SHARED
10+
DEPENDS
11+
ITKIOImageBase
12+
ITKZLIB
13+
TEST_DEPENDS
14+
ITKTestKernel
15+
ITKTransform
16+
EXCLUDE_FROM_DEFAULT
17+
FACTORY_NAMES
18+
ImageIO::MGH
19+
DESCRIPTION "${DOCUMENTATION}"
20+
)
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
set(
2+
MGHIO_SRC
3+
itkMGHImageIOFactory.cxx
4+
itkMGHImageIO.cxx
5+
)
6+
7+
itk_module_add_library(MGHIO ${MGHIO_SRC})

0 commit comments

Comments
 (0)