InsightSoftwareConsortium / InsightSoftwareConsortium/ITK

ENH: Support reading MATLAB Level-5 (`.mat` v5) transform files in `itkMatlabTransformIO`

Open
#6,725 1 comment 0 reactions 0 assignees View on GitHub
type:Enhancement
Dominant language
C++
Stars
1.7k
Forks
748
Avg merge
1d 1h
Merged PRs (30d)
64

Description

`itkMatlabTransformIO` reads and writes only **MATLAB Level 4** — the 1980s fixed 20-byte header (`type/rows/cols/imag/namlen`) — via the vendored vnl `vnl_matlab_read*`/`vnl_matlab_write*` helpers. MATLAB has defaulted to the tagged Level 5 format since 1996 and to v7.3/HDF5 since R2006b, so ITK silently cannot open `.mat` files produced by any modern MATLAB.

This issue is to decide **whether** to widen to Level-5 *read* while keeping Level-4 read+write forever (the deployed corpus is non-negotiable), and if so, whether to hand-roll it in ITK or vendor matio.

Evidence that the current format really is Level 4

Dumping ITK's own test fixtures:

```
Transforms_double.mat type=0 rows=20 cols=1 name=AffineTransform_double_4_4
Transforms_float.mat type=10 rows=20 cols=1 name=AffineTransform_float_4_4
EmptyCompositeTransform_float.mat type=10 rows=0 name=CompositeTransform_float_3_3
IllegalMat.mat 9 bytes (deliberate bad-file test)
```

Every ITK `.mat` transform ever written by ANTs, Slicer, BRAINSTools, or any registration pipeline is Level 4. Real MATLAB (R2006+) can still *read* v4, but nothing modern *writes* it.

Consumer surface — it is genuinely tiny

- `Modules/IO/TransformMatlab/src/itkMatlabTransformIO.cxx` — the **only** real consumer. It uses roughly eight calls: `vnl_matlab_readhdr(istream)`, `operator!`, `.rows()`, `.cols()`, `.name()`, `.is_single()`, `.read_data(float*)`/`.read_data(double*)`, and `vnl_matlab_write(ostream, double*, n, name)`.
- `Modules/IO/TransformInsightLegacy/src/itkTxtTransformIO.cxx` — `#include`s `vnl/vnl_matlab_read.h` and `vnl/vnl_matlab_write.h` but uses **zero symbols** from either. Stale includes; deleting them is a trivial cleanup that is independent of everything else in this issue and can be done immediately.

The vendored code being relied on is **993 lines** total across `Modules/ThirdParty/VNL/src/vxl/core/vnl/vnl_matlab_{read,write,header,filewrite}.{h,cxx}`.

Third-party library survey (done 2026-07-21 — please don't redo it)

| Library | License | v4 read+write | v5 | Deps | Verdict |
|---|---|---|---|---|---|
| **matio** (tbeu/matio) | BSD-2 | **yes** | yes | none for v4-only; zlib for v5 compression, HDF5 for v7.3 | Only viable third-party candidate |
| matio-cpp (ami-iit) | BSD-2 | via matio | yes | **requires matio** | Additive, not substitutive |
| mat-v4 (bolderflight) | MIT | **write only** | no | none | Cannot read the corpus |
| TinyMAT (jkriege2) | **LGPL-2.1+** | no | write only | zlib | **License-blocked for ITK** |
| cvmatio | — | no | read | **OpenCV** | Non-starter |

matio 1.5.30 (Jan 2026) is actively maintained and its `mat4.c` backend is first-class, not deprecated (`Mat_VarRead4`, `Mat_VarWrite4`, `Mat_CreateVer(..., MAT_FT_MAT4)`). As of mid-2026 there is no permissive header-only single-file MAT *reader* covering Level 4.

**Argument against adopting matio:** it would become ITK's 27th ThirdParty module — 10-25 kLOC of C, `UpdateFromUpstream.sh` machinery, mangled headers, a `USE_SYSTEM_MATIO` path, and Slicer/BRAINSTools coordination — to replace 993 lines used by one file. It also carries a live CVE history (CVE-2025-50343 → `Mat_VarCreateStruct` deprecated in 1.5.30), so adopting it is a tracking obligation, not a vendor-and-forget.

Suggested approach

1. **Establish the actual user need first.** Is anyone filing issues about v5 `.mat` transforms, or is this speculative? Check Discourse (`https://discourse.itk.org/search.json?q=matlab+transform+mat+file`) and `gh issue list -S "matlab transform"` before investing.
2. **If the need is real, prefer read-only v5.** ITK should keep *writing* v4 forever for backward compatibility with the deployed corpus; only *reading* needs to widen. That halves the scope and sidesteps round-trip format questions.
3. **Evaluate ITK-owned code before vendoring.** Level 5's tagged format is more involved than v4 but still modest for the rank-2 numeric-array subset ITK needs (`miMATRIX` / `mxDOUBLE_CLASS` / `mxSINGLE_CLASS`, optionally `miCOMPRESSED` via the already-vendored zlib). An ITK-owned `itkMatlabTransformIOHelper` could be `SizeValueType`-clean, exception-based rather than `std::cerr`-based, and fuzz-tested — none of which the vendored vnl code is. It would also advance the broader VNL-decoupling direction already in flight.
4. **Only reach for matio if v7.3/HDF5 turns out to be required.** That is where hand-rolling stops being sensible, and since ITK already vendors HDF5 the marginal dependency cost there is lower than it first appears.
5. **Independently of all the above, delete the dead `vnl_matlab_*` includes from `itkTxtTransformIO.cxx`.**

Explicitly NOT covered by the already-merged #6682

#6575 item **B91** was a distinct, narrower defect: `vnl_matlab_readhdr::read_hdr()` omitted native type code `1010` (big-endian, column-wise, single-precision) from its no-swap `switch`, so big-endian hosts byte-swapped their own native headers as though foreign. Fixed in **PR #6682** (merged 2026-07-23), vendored-only by maintainer decision, no upstream vxl submission.

That is a **Level-4 endianness bug inside the existing reader**. It adds no Level-5 capability and does not resolve this issue. (B91 was reachable precisely because ITK writes `type=10` for float transforms on little-endian, hence `1010` on big-endian.)

Downstream constraint on any VNL API removal

If this work ends up removing or narrowing the vendored `vnl_matlab_*` API rather than merely layering on top of it, note that ITK-SNAP's vendored `greedy` submodule calls `vnl_matlab_read_or_die` directly (`Submodules/greedy/src/lmshoot/TestGeodesicShooting.cxx`). Any removal must account for it.

`Documentation/Maintenance/ThirdPartyForkConventions.md` documents the process cost that a matio adoption would incur.

Contributor guide

Open the contributing guide

Research direction

First check the linked Discourse search and `gh issue list -S "matlab transform"` to establish whether Level-5 support is needed. Then read `Modules/IO/TransformMatlab/src/itkMatlabTransformIO.cxx` and the vendored `vnl_matlab_*` helpers, preserving existing Level-4 behavior while deciding the read-only Level-5 scope. Independently inspect `Modules/IO/TransformInsightLegacy/src/itkTxtTransformIO.cxx` for the stale includes; done means an agreed implementation path and coverage for the supported formats.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
backend, data
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.