Skip to content

Commit

Permalink
Merge pull request #2767 from MRtrix3/allow_DICOM_header_read_with_un…
Browse files Browse the repository at this point in the history
…supported_transfer_syntax

DICOM: add null imageIO handler to allow parsing of DICOM data even with unsupported transfer syntax
  • Loading branch information
Lestropie authored Feb 10, 2025
2 parents 818a542 + 6b9957a commit 5c3d62d
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 38 deletions.
26 changes: 18 additions & 8 deletions core/file/dicom/mapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#include "header.h"
#include "phase_encoding.h"
#include "image_io/null.h"
#include "image_io/default.h"
#include "image_io/mosaic.h"
#include "image_io/variable_scaling.h"
Expand Down Expand Up @@ -68,6 +69,8 @@ namespace MR {
// build up sorted list of frames:
vector<Frame*> frames;

bool transfer_syntax_supported = true;

// loop over series list:
for (const auto& series_it : series) {
try {
Expand All @@ -82,13 +85,9 @@ namespace MR {

// loop over images in each series:
for (auto image_it : *series_it) {
if (!image_it->transfer_syntax_supported) {
Exception E ("unsupported transfer syntax found in DICOM data");
E.push_back ("consider using third-party tools to convert your data to standard uncompressed encoding");
E.push_back ("See the MRtrix3 documentation on DICOM handling for details:");
E.push_back (" http://mrtrix.readthedocs.io/en/latest/tips_and_tricks/dicom_handling.html#error-unsupported-transfer-syntax");
throw E;
}
if (!image_it->transfer_syntax_supported)
transfer_syntax_supported = false;

// if multi-frame, loop over frames in image:
if (image_it->frames.size()) {
std::sort (image_it->frames.begin(), image_it->frames.end(), compare_ptr_contents());
Expand Down Expand Up @@ -209,7 +208,7 @@ namespace MR {
}

size_t nchannels = image.samples_per_pixel;
if (nchannels == 1 && !image.frames.size()) {
if (nchannels == 1 && !image.frames.size() && transfer_syntax_supported) {
// only guess number of samples per pixel if not explicitly set in
// DICOM and not using multi-frame:
nchannels = image.data_size / (frame.dim[0] * frame.dim[1] * (frame.bits_alloc/8));
Expand Down Expand Up @@ -363,6 +362,17 @@ namespace MR {
}


if (!transfer_syntax_supported) {
WARN ("unsupported transfer syntax found in DICOM data");
WARN ("header information is accessible, but commands requiring access to image intensity data will fail");
WARN ("consider using third-party tools to convert your data to standard uncompressed encoding");
WARN ("See the MRtrix3 documentation on DICOM handling for details:");
WARN (" http://mrtrix.readthedocs.io/en/latest/tips_and_tricks/dicom_handling.html#error-unsupported-transfer-syntax");

io_handler.reset (new MR::ImageIO::Null (H));
return io_handler;
}

if (image.images_in_mosaic) {

INFO ("DICOM image \"" + H.name() + "\" is in mosaic format");
Expand Down
34 changes: 34 additions & 0 deletions core/image_io/null.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/* Copyright (c) 2008-2025 the MRtrix3 contributors.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Covered Software is provided under this License on an "as is"
* basis, without warranty of any kind, either expressed, implied, or
* statutory, including, without limitation, warranties that the
* Covered Software is free of defects, merchantable, fit for a
* particular purpose or non-infringing.
* See the Mozilla Public License v. 2.0 for more details.
*
* For more details, see http://www.mrtrix.org/.
*/

#include "image_io/null.h"
#include "header.h"

namespace MR {
namespace ImageIO {

void Null::load(const Header &header, size_t) {
throw Exception("No suitable handler to access data in \"" + header.name() +
"\"");
}

void Null::unload(const Header &header) {
throw Exception("No suitable handler to access data in \"" + header.name() +
"\"");
}

} // namespace ImageIO
} // namespace MR
38 changes: 38 additions & 0 deletions core/image_io/null.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/* Copyright (c) 2008-2025 the MRtrix3 contributors.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Covered Software is provided under this License on an "as is"
* basis, without warranty of any kind, either expressed, implied, or
* statutory, including, without limitation, warranties that the
* Covered Software is free of defects, merchantable, fit for a
* particular purpose or non-infringing.
* See the Mozilla Public License v. 2.0 for more details.
*
* For more details, see http://www.mrtrix.org/.
*/

#ifndef __image_io_null_h__
#define __image_io_null_h__

#include "image_io/base.h"

namespace MR {
namespace ImageIO {

class Null : public Base {
NOMEMALIGN
public:
Null(const Header &header) : Base(header) {}

protected:
virtual void load(const Header &, size_t);
virtual void unload(const Header &);
};

} // namespace ImageIO
} // namespace MR

#endif
87 changes: 57 additions & 30 deletions docs/tips_and_tricks/dicom_handling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -375,44 +375,71 @@ these are:

- Explicit VR Big Endian (``1.2.840.10008.1.2.2``)

Any other transfer syntax will be flagged as unsupported, and *MRtrix3* will be
unable to read the data, providing an error message similar to this:
Any other transfer syntax will be flagged as unsupported. When this occurs,
whether or not the *MRtrix3* command can proceed will depend on whether that
command requires access to the underlying image data:

- If *only header information* is required, then the command will be able to proceed,
albeit with a warning issued:

.. code-block:: console
$ mrinfo DICOM
mrinfo: [done] scanning DICOM folder "DICOM"
mrinfo: [ERROR] unable to read DICOM images in "DICOM":
mrinfo: [ERROR] unsupported transfer syntax found in DICOM data
mrinfo: [ERROR] consider using third-party tools to convert your data to standard uncompressed encoding
mrinfo: [ERROR] See the MRtrix3 documentation on DICOM handling for details:
mrinfo: [ERROR] http://mrtrix.readthedocs.io/en/latest/tips_and_tricks/dicom_handling.html#error-unsupported-transfer-syntax
mrinfo: [ERROR] error opening image "DICOM"
Thankfully, other tools exist that should be able to convert the data to a
format that *MRtrix3* (and other DICOM tools) will read. The `dcmtk
<http://dicom.offis.de/dcmtk.php.en>`__ DICOM toolkit in particular provides
the ``dcmdjpeg`` command to decompress data stored using JPEG transfer syntax.
On Linux, a directory of such files can be decompressed as follows (amend the
various ``PATH`` as required for your system):
$ mrinfo DICOM/
mrinfo: [done] scanning folder "DICOM/" for DICOM data
mrinfo: [100%] Reading DICOM series "SeriesDescription"
mrinfo: [WARNING] unable to read DICOM images in "DICOM/":
mrinfo: [WARNING] unsupported transfer syntax found in DICOM data
mrinfo: [WARNING] consider using third-party tools to convert your data to standard uncompressed encoding
mrinfo: [WARNING] See the MRtrix3 documentation on DICOM handling for details:
mrinfo: [WARNING] http://mrtrix.readthedocs.io/en/latest/tips_and_tricks/dicom_handling.html#error-unsupported-transfer-syntax
************************************************
Image name: "SURNAME^FIRSTNAME [MR] SeriesDescription"
************************************************
Dimensions: 96 x 96 x 60 x 7
Voxel size: 2.5 x 2.5 x 2.5 x ?
Data strides: [ -1 -2 3 4 ]
....
- If however a command requires *access to the underlying image intensities*,
then *MRtrix3* will be unable to read from such:


.. code-block:: console
$ mrconvert DICOM/ data.mif
mrconvert: [done] scanning folder "DICOM/" for DICOM data
mrconvert: [100%] Reading DICOM series "SeriesDescription"
mrconvert: [WARNING] unable to read DICOM images in "DICOM/":
mrconvert: [WARNING] unsupported transfer syntax found in DICOM data
mrconvert: [WARNING] consider using third-party tools to convert your data to standard uncompressed encoding
mrconvert: [WARNING] See the MRtrix3 documentation on DICOM handling for details:
mrconvert: [WARNING] http://mrtrix.readthedocs.io/en/latest/tips_and_tricks/dicom_handling.html#error-unsupported-transfer-syntax
mrconvert: [ERROR] No suitable handler to access data in "SURNAME^FIRSTNAME [MR] SeriesDescription"
Thankfully, other tools exist that should be able to convert the data to a
format that *MRtrix3* (and other DICOM tools) will read. The `dcmtk
<http://dicom.offis.de/dcmtk.php.en>`__ DICOM toolkit in particular provides
the ``dcmdjpeg`` command to decompress data stored using JPEG transfer syntax.
On Linux, a directory of such files can be decompressed as follows (amend the
various ``PATH`` as required for your system):
.. code-block:: console
$ export PATH=/opt/dcmtk/bin:$PATH
$ export DCMDICTPATH=/opt/dcmtk/share/dcmtk/dicom.dic
$ export PATH=/opt/dcmtk/bin:$PATH
$ export DCMDICTPATH=/opt/dcmtk/share/dcmtk/dicom.dic
$ for img in dcmdir/*
> do
> dcmdjpeg $img ${img}.tmp
> mv ${img}.tmp $img
> done
$ for img in dcmdir/*
> do
> dcmdjpeg $img ${img}.tmp
> mv ${img}.tmp $img
> done
*MRtrix3* commands should now be able to read the directory successfully:
*MRtrix3* commands should now be able to read the directory successfully:
.. code-block:: console
.. code-block:: console
$ mrinfo dcmdir
mrinfo: [done] scanning DICOM folder "data/driss/t1"
mrinfo: [100%] reading DICOM series "AX FSPGR 3D ASSET C+"
...
$ mrinfo dcmdir
mrinfo: [done] scanning DICOM folder "data/driss/t1"
mrinfo: [100%] reading DICOM series "AX FSPGR 3D ASSET C+"
...

0 comments on commit 5c3d62d

Please sign in to comment.