Skip to content
Commits on Source (6)
.DS_Store
build/
bin/
/build/
/bin/
/console/dcm2niix
......@@ -7,15 +7,25 @@ matrix:
include:
- os: linux
dist: trusty
env: TARGET=lnx
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-5 # support c++14
env:
- MATRIX_EVAL="CC=gcc-5 && CXX=g++-5"
- TARGET=lnx
- os: osx
osx_image: xcode8.3 # Tracvis default: OS X 10.12.6 and Xcode 8.3.3
env: TARGET=mac
before_install:
- eval "${MATRIX_EVAL}"
- git submodule update --init --depth=3 dcm_qa
script:
- mkdir build && cd build && cmake -DBATCH_VERSION=ON -DUSE_OPENJPEG=ON .. && make && cd -
- mkdir build && cd build && cmake -DBATCH_VERSION=ON -DUSE_OPENJPEG=ON -DUSE_JPEGLS=true -DZLIB_IMPLEMENTATION=Cloudflare .. && make && cd -
- export PATH=$PWD/build/bin:$PATH
- cd dcm_qa && ./batch.sh && cd -
......
......@@ -2,9 +2,11 @@
The README.md file describes the typical compilation of the software, using the `make` command to build the software. This document describes advanced methods for compiling and tuning the software.
Beyond the complexity of compiling the software, the only downside to adding optional modules is that the dcm2niix executable size will require a tiny bit more disk space. For example, on MacOS the stripped basic executable is 238kb, miniz (GZip support) adds 18kb, NanoJPEG (lossy JPEG support) adds 13kb, CharLS (JPEG-LS support) adds 271kb, and OpenJPEG (JPEG2000 support) adds 192kb. So with all these features installed the executable weighs in at 732kb.
## Choosing your compiler
The text below generally describes how to build dcm2niix using the [GCC](https://gcc.gnu.org) compiler using the `g++` command. However, the code is portable and you can use different compilers. For [clang/llvm](https://clang.llvm.org) compile using `clang++`. If you have the [Intel C compiler](https://software.intel.com/en-us/c-compilers), you can substitute the `icc` command. For [Microsoft's C compiler](http://landinghub.visualstudio.com/visual-cpp-build-tools) you would use the `cl` command. In theory, the code should support other compilers, but this has not been tested. Be aware that if you do not have gcc installed the `g++` command may use a default to a compiler (e.g. clang). To check what compiler was used, run the dcm2niix software: it always reports the version and the compiler used for the build.
The text below generally describes how to build dcm2niix using the [GCC](https://gcc.gnu.org) compiler using the `g++` command. However, the code is portable and you can use different compilers. For [clang/llvm](https://clang.llvm.org) compile using `clang++`. If you have the [Intel C compiler](https://software.intel.com/en-us/c-compilers), you can substitute the `icc` command. The code is compatible with Microsoft's VS 2015 or later. For [Microsoft's C compiler](http://landinghub.visualstudio.com/visual-cpp-build-tools) you would use the `cl` command. In theory, the code should support other compilers, but this has not been tested. Be aware that if you do not have gcc installed the `g++` command may use a default to a compiler (e.g. clang). To check what compiler was used, run the dcm2niix software: it always reports the version and the compiler used for the build.
## Building the command line version without cmake
......@@ -20,6 +22,11 @@ The following sub-sections list how you can modify this basic recipe for your ne
Some [Centos/Redhat](https://github.com/rordenlab/dcm2niix/issues/137) may report "/usr/bin/ld: cannot find -lstdc++". This can be resolved by installing static versions of libstdc++: `yum install libstdc++-static`.
To compile with debugging symbols, use
```
cmake -DUSE_OPENJPEG=ON -DCMAKE_CXX_FLAGS=-g .. && make
```
##### ZLIB BUILD
If we have zlib, we can use it (-lz) and disable [miniz](https://code.google.com/p/miniz/) (-myDisableMiniZ)
......@@ -51,17 +58,27 @@ By default, classic JPEG images will be decoded using the [compact NanoJPEG deco
g++ -dead_strip -O3 -I. main_console.cpp nii_dicom.cpp jpg_0XC3.cpp ujpeg.cpp nifti1_io_core.cpp nii_ortho.cpp nii_dicom_batch.cpp nii_foreign.cpp -o dcm2niix -DmyDisableOpenJPEG -DmyTurboJPEG -I/opt/libjpeg-turbo/include /opt/libjpeg-turbo/lib/libturbojpeg.a
```
##### JPEG-LS BUILD
You can compile dcm2niix to convert DICOM images compressed with the [JPEG-LS](https://en.wikipedia.org/wiki/JPEG_2000) [transfer syntaxes 1.2.840.10008.1.2.4.80 and 1.2.840.10008.1.2.4.81](https://www.nitrc.org/plugins/mwiki/index.php/dcm2nii:MainPage#Transfer_Syntaxes_and_Compressed_Images). Decoding this format is handled by the [CharLS library](https://github.com/team-charls/charls), which is included with dcm2niix in the `charls` folder. The included code was downloaded from the CharLS website on 6 June 2018. To enable support you will need to include the `myEnableJPEGLS` compiler flag as well as a few file sin the `charls` folder. Therefore, a minimal compile (with just JPEG-LS and without JPEG2000) should look like this:
`g++ -I. -DmyEnableJPEGLS charls/jpegls.cpp charls/jpegmarkersegment.cpp charls/interface.cpp charls/jpegstreamwriter.cpp charls/jpegstreamreader.cpp main_console.cpp nii_foreign.cpp nii_dicom.cpp jpg_0XC3.cpp ujpeg.cpp nifti1_io_core.cpp nii_ortho.cpp nii_dicom_batch.cpp -o dcm2niix -DmyDisableOpenJPEG`
Alternatively, you can decompress an image in JPEG-LS to an uncompressed DICOM using [gdcmconv](https://github.com/malaterre/GDCM)(e.g. `gdcmconv -w 3691459 3691459.dcm`). Or you can use gdcmconv compress a DICOM to JPEG-LS (e.g. `gdcmconv -L 3691459 3691459.dcm`). Alternatively, the DCMTK tool [dcmcjpls](https://support.dcmtk.org/docs/dcmcjpls.html) provides JPEG-LS support.
##### JPEG2000 BUILD
You can compile dcm2niix to convert DICOM images compressed with the JPEG2000 [transfer syntaxes 1.2.840.10008.1.2.4.90 and 1.2.840.10008.1.2.4.91](https://www.nitrc.org/plugins/mwiki/index.php/dcm2nii:MainPage#Transfer_Syntaxes_and_Compressed_Images). This is optional, as JPEG2000 is very rare in DICOMs (usually only created by the proprietary DCMJP2K or OsiriX). Due to the challenges discussed below this is a poor choice for archiving DICOM data. Rather than support conversion with dcm2niix, a better solution would be to use DCMJP2K to do a DICOM-to-DICOM conversion to a more widely supported transfer syntax. Unfortunately, JPEG2000 saw poor adoption as a general image format. This situation is unlikely to change, as JPEG2000 only offered incremental benefits over the simpler classic JPEG, and is outperformed by the more recent HEIF. This has implications for DICOM, as there is little active development on libraries to decode JPEG2000. Indeed, the two popular open-source libraries that decode JPEG2000 have serious limitations for processing these images. Some JPEG2000 DICOM images can not be decoded by the default compilation of OpenJPEG library after version [2.1.0](https://github.com/uclouvain/openjpeg/issues/962). On the other hand, the Jasper library does not handle lossy [16-bit](https://en.wikipedia.org/wiki/JPEG_2000) images with good precision.
You can compile dcm2niix to convert DICOM images compressed with the [JPEG2000](https://en.wikipedia.org/wiki/JPEG_2000) [transfer syntaxes 1.2.840.10008.1.2.4.90 and 1.2.840.10008.1.2.4.91](https://www.nitrc.org/plugins/mwiki/index.php/dcm2nii:MainPage#Transfer_Syntaxes_and_Compressed_Images). This is optional, as JPEG2000 is very rare in DICOMs (usually only created by the proprietary DCMJP2K or OsiriX). Due to the challenges discussed below this is a poor choice for archiving DICOM data. Rather than support conversion with dcm2niix, a better solution would be to use DCMJP2K to do a DICOM-to-DICOM conversion to a more widely supported transfer syntax. Unfortunately, JPEG2000 saw poor adoption as a general image format. This situation is unlikely to change, as JPEG2000 only offered incremental benefits over the simpler classic JPEG, and is outperformed by the more recent [HEIF](https://en.wikipedia.org/wiki/High_Efficiency_Image_File_Format). This has implications for DICOM, as there is little active development on libraries to decode JPEG2000. Indeed, the two popular open-source libraries that decode JPEG2000 have serious limitations for processing these images. Some JPEG2000 DICOM images can not be decoded by the default compilation of OpenJPEG library after version [2.1.0](https://github.com/uclouvain/openjpeg/issues/962). On the other hand, the Jasper library does not handle lossy [16-bit](https://en.wikipedia.org/wiki/JPEG_2000) images with good precision.
You can build dcm2niix with JPEG2000 decompression support using OpenJPEG 2.1.0. You will need to have the OpenJPEG library installed (use the package manager of your linux distribution, Homebrew for macOS, or see [here](https://github.com/uclouvain/openjpeg/blob/master/INSTALL.md) if you want to build it yourself). If you want to use a more recent version of OpenJPEG, it must be custom-compiled with `-DOPJ_DISABLE_TPSOT_FIX` compiler flag. I suggest building static libraries where you would [download the code](https://github.com/uclouvain/openjpeg) and run
You can build dcm2niix with JPEG2000 decompression support using OpenJPEG 2.1.0. You will need to have the OpenJPEG library installed (use the package manager of your Linux distribution, Homebrew for macOS, or see [here](https://github.com/uclouvain/openjpeg/blob/master/INSTALL.md) if you want to build it yourself). If you want to use a more recent version of OpenJPEG, it must be custom-compiled with `-DOPJ_DISABLE_TPSOT_FIX` compiler flag. I suggest building static libraries where you would [download the code](https://github.com/uclouvain/openjpeg) and run
```
cmake -DBUILD_SHARED_LIBS:bool=off -DOPJ_DISABLE_TPSOT_FIX:bool=on .
make
sudo make install
```
You should then be able to run then run:
You should then be able to run:
```
g++ -O3 -dead_strip -I. main_console.cpp nii_dicom.cpp nifti1_io_core.cpp nii_ortho.cpp nii_dicom_batch.cpp jpg_0XC3.cpp ujpeg.cpp nii_foreign.cpp -o dcm2niix -lopenjp2
......
## About
In general dcm2niix creates images with 3D dimensions, or 4 dimensions when the 4th dimension is time (fMRI) or gradient number (DWI). It will use the following extensions to disambiguate additional dimensions from the same series:
- _c1.._cN coil ID (only seen if saved independently for each coil)
- _e2..eN additional echoes (the first echo is implicit)
- _ph phase map
- _imaginary imaginary component of complex image
- _real real component of complex image
- _phMag rare case where phase and magnitude are saved as the 4th dimension
- _t If the trigger delay time (0020,9153) is non-zero, it will be recorded in the filename. For example, the files "T1_t178.nii" and "T1_t511" suggests that the T1 scan was acquired with two cardiac trigger delays (178 and 511ms after the last R-peak).
- _ADC Philips specific case DWI image where derived isotropic, ADC or trace volume was appended to the series. Since this image will disrupt subsequent processing, and because subsequent processing (dwidenoise, topup, eddy) will yield better derived images, dcm2niix will also create an additional image without this volume. Therefore, the _ADC file should typically be discarded. If you want dcm2niix to discard these useless derived images , use the ignore feature ('-i y').
- _Eq is specific to [CT scans](https://www.nitrc.org/plugins/mwiki/index.php/dcm2nii:MainPage#Computed_Tomography_.28CT.2C_CAT.29). These scans can be acquired with variable distance between the slices of a 3D volume. NIfTI asumes all 2D slices that form a 3D stack are equidistant. Therefore, dcm2niix reslices the input data to generate an equidistant volume.
- _Tilt is specific to [CT scans](https://www.nitrc.org/plugins/mwiki/index.php/dcm2nii:MainPage#Computed_Tomography_.28CT.2C_CAT.29). These scans can be acquired with a gantry tilt that causes a skew that can not be stored in a NIfTI qForm. Therefore, the slices are resampled to remove the effect of tilt.
......@@ -2,6 +2,10 @@
dcm2niix attempts to convert GE DICOM format images to NIfTI.
## Diffusion Tensor Notes
As noted by Jaemin Shin (GE), the GE convention for reported diffusion gradient direction has always been in “MR physics” logical coordinate, i.e Freq (X), Phase (Y), Slice (Z). Note that this is neither “with reference to the scanner bore” (like Siemens or Philips) nor “with reference to the imaging plane” (as expected by FSL tools). This is the main source of confusion. This explains why the dcm2niix function geCorrectBvecs() checks whether the DICOM tag In-plane Phase Encoding Direction (0018,1312) is 'ROW' or 'COL'. In addition, it will generate the warning 'reorienting for ROW phase-encoding untested' if you acquire DTI data with the phase encoding in the ROW direction. If you do test this feature, please report your findings as a Github issue.
## dcm2niix Notes
In addition to reading the
......
## About
dcm2niix attempts to convert Philips PAR/REC format images to NIfTI. While this format remains popular with users, it is slowly being superceded by Philips enhanced DICOM format as well as the direct NIfTI export that Philips provides for users.
dcm2niix attempts to convert Philips PAR/REC format images to NIfTI. While this format remains popular with users, it is slowly being superceded by Philips enhanced DICOM format, an XML/REC format as well as the direct NIfTI export. Note that dcm2niix does not support the XML/REC format.
According to [Matthew Clemence](https://www.nitrc.org/forum/forum.php?thread_id=9319&forum_id=4703) DICOM (classic and enhanced) and XML/REC are supported in the base product, NIFTI forms part of a Neuroscience commercial option from release 5 onwards. PAR/REC requires a research agreement to obtain. For the two formats XML/REC and PAR/REC, the "REC" part is identical but instead of a plain text file of the "par" format, the same information is now available as an XML file. This descision has been taken to allow the information to be more easily extended as the PAR file was getting increasingly limited.
## Detecting, Reporting and Fixing the V4 Image Offcente Bug
The PAR header contains a field 'image offcentre (ap,fh,rl in mm )' that we use to detect the spatial position of slices (e.g. for an axial scan is the first slice inferior or superior to the final slice). However, it appears that in some V4 images the values in these columns are actually stored in the order "rl,ap,fh". This has never been reported in V3, V4.1 and V4.2 images. A nice example of this is the ['philips_1_5T_intera' dataset provided with Rosetta Bit](https://www.nitrc.org/projects/rosetta/)(actually from a 3T MRI). This sample includes both DICOM and V4 PAR/REC data. Note the 'Off Centre midslice(ap,fh,rl) [mm]' field gives the volume center in the correct order. However, the subsequent 'image offcentre' fields are swizzled. The latest versions of dcm2niix will detect, report and correct this error. If you do see an error like the one below, please report it on Github as an issue, so we can have a better understanding of its prevalence.
```
Order of 'image offcentre (ap,fh,rl in mm )' appears incorrect (assuming rl,ap,fh)
err[ap,fh,rl]= 12.7279 (-7.05 -4.55 2.95)
err[rl,ap,fh]= 0.0223597 (-4.55 2.95 -7.05)
```
## File naming
You can specify the preferred name for your output file with dcm2niix. You do this by passing an argument string (default is '%f_%p_%t_%s'). For example, If you run "dcm2niix -f %p_%s ~/myParDir" the output name will be based on the protocol name and the series name. Here is a list of the possible argument you can use with Philips, and the tag from the header that is used for this value:
- %c: comment : "Examination name"
- %d: description : "Series Type"
- %e: echo number : "echo number" Column
- %f: folder name
- %i: ID : "Technique"
- %m: manufacturer : always 'Ph' for Philips
- %n: name : "Patient name"
- %p: protocol name : "Protocol name"
- %s: series number : "Acquisition nr"
- %t: time : "Examination date/time"
- %u: acquisition number : "Acquisition nr"
- %v: vendor : always 'Philips' for Philips
Note that for Philips (unlike DICOM) the For PAR/REC the acquisition (%u) and series (%s) numbers are the same. Also note that there are several arguments that might be useful with DICOM but will always be unused for PAR/REC:
- %a: antenna
- %j: seriesInstanceUID
- %k: studyInstanceUID
- %x: study ID
- %z: sequence name
## dcm2niix Limitations
None of the major contributors to the dcm2niix source code have access to Philips hardware. Therefore, one should be cautious when converting Philips PAR/REC data. Two situations will generate error reports from the current version of dcm2niix. If you encounter any of these situations you may want to consider filing a GitHub issue or trying an alternative such as [dicm2nii](https://www.mathworks.com/matlabcentral/fileexchange/42997-dicom-to-nifti-converter--nifti-tool-and-viewer) or [r2agui](http://r2agui.sourceforge.net/).
Be aware that dcm2niix assumes that the data is stored in complete 3D volumes. It will not convert datasets where the scan is interrupted mid-volume (e.g. where the number of 2D slices is not divisible by the number of slices in a volume). This can occur if the user aborts a sequence part way through acquisition. If dcm2niix detects this situation it will suggest you use [dicm2nii](https://www.mathworks.com/matlabcentral/fileexchange/42997-dicom-to-nifti-converter--nifti-tool-and-viewer) which can handle these files.
- dcm2niix assumes that the data is stored in complete 3D volumes. It will not convert datasets where the scan is interrupted mid-volume (e.g. where the number of 2D slices is not divisible by the number of slices in a volume).
- dcm2niix is aware of phase maps and magnitude maps. In theory (though we have never seen any examples), the format can also store real, imaginary and subsequent calculations such as B1. These may or may not be converted correctly.
......@@ -2,11 +2,11 @@
dcm2niix attempts to convert all DICOM images to NIfTI. The Philips enhanced DICOM images are elegantly able to save all images from a series as a single file. However, this format is necessarily complex. The usage of this format has evolved over time, and can become further complicated when DICOM are handled by DICOM tools (for example, anonymization, transfer which converts explicit VRs to implicit VRs, etc.).
This web page describes some of the strategies handle these images. However, users should be vigilant when handling these datasets. If you encounter problems using dcm2niix you can explore [https://github.com/rordenlab/dcm2niix competing DICOM to NIfTI converters] or [ [https://github.com/rordenlab/dcm2niix report an issue].
This web page describes some of the strategies handle these images. However, users should be vigilant when handling these datasets. If you encounter problems using dcm2niix you can explore [alternative DICOM to NIfTI converters](https://www.nitrc.org/plugins/mwiki/index.php/dcm2nii:MainPage#Alternatives) or [report an issue](https://github.com/rordenlab/dcm2niix).
## Image Patient Position
The Image Patient Position (0020,0032) tag is required to determine the position of the slices with respect to each other (and with respect to the scanner bore). Philips scans often report two conflicting IPPs for each single slice: with one stored in the private sequence (SQ) 2005,140F while the other is in the public sequence. This is unusual, but is [ftp://medical.nema.org/medical/dicom/final/cp758_ft.pdf legal].
The Image Patient Position (0020,0032) tag is required to determine the position of the slices with respect to each other (and with respect to the scanner bore). Philips scans often report two conflicting IPPs for each single slice: with one stored in the private sequence (SQ) 2005,140F while the other is in the public sequence. This is unusual, but is [legal](ftp://medical.nema.org/medical/dicom/final/cp758_ft.pdf).
In practice, this complication has several major implications. First, not all software translate private SQs well. One potential problem is when the implicit VRs are saved as implicit VRs. This can obscure the fact that 2005,140F is an SQ. Indeed, some tools will convert the private SQ type as a "UN" unknown type and add another public sequence. This can confuse reading software.
......@@ -43,4 +43,4 @@ The current version of dcm2niix uses Dimension Index Values (0020,9157) to deter
## General variations
Prior versions of dcm2niix used different methods to sort images. However, these have proved unreliable The undocumented tags SliceNumberMrPhilips (2001,100A), NumberOfSlicesMrPhilips (2001,1018) are not always present. In theory, InStackPositionNumber (0020,9057) should be present in all enhanced files, but has not proved reliable (perhaps not in older Philips images or DICOM images that were modified after leaving the scanner). MRImageGradientOrientationNumber (2005,1413) is complicated by the inclusion of derived images.Therefore, current versions of dcm2niix do not depend on any of these.
Prior versions of dcm2niix used different methods to sort images. However, these have proved unreliable The undocumented tags SliceNumberMrPhilips (2001,100A). In theory, InStackPositionNumber (0020,9057) should be present in all enhanced files, but has not proved reliable (perhaps not in older Philips images or DICOM images that were modified after leaving the scanner). MRImageGradientOrientationNumber (2005,1413) is complicated by the inclusion of derived images. Therefore, current versions of dcm2niix do not generally depend on any of these.
......@@ -13,6 +13,17 @@ This software is open source. The bulk of the code is covered by the BSD license
This software should run on macOS, Linux and Windows typically without requiring any other software. However, if you use dcm2niix to create gz-compressed images it will be faster if you have [pigz](https://github.com/madler/pigz) installed. You can get a version of both dcm2niix and pigz compiled for your operating system by downloading [MRIcroGL](https://www.nitrc.org/projects/mricrogl/).
## Image Conversion and Compression
DICOM provides many ways to store/compress image data, known as [transfer syntaxes](https://www.nitrc.org/plugins/mwiki/index.php/dcm2nii:MainPage#DICOM_Transfer_Syntaxes_and_Compressed_Images). The [COMPILE.md file describes details](./COMPILE.md) on how to enable different options to provide support for more formats.
- The base code includes support for raw, run-length encoded, and classic JPEG lossless decoding.
- Lossy JPEG is handled by the included [NanoJPEG](https://keyj.emphy.de/nanojpeg/). This support is modular: you can compile for [libjpeg-turbo](https://github.com/chris-allan/libjpeg-turbo) or disable it altogether.
- JPEG-LS lossless support is optional, and can be provided by using [CharLS](https://github.com/team-charls/charls).
- JPEG2000 lossy and lossless support is optional, and can be provided using [OpenJPEG](https://github.com/uclouvain/openjpeg) or [Jasper](https://www.ece.uvic.ca/~frodo/jasper/).
- GZ compression (e.g. creating .nii.gz images) is optional, and can be provided using either the included [miniz](https://github.com/richgel999/miniz) or the popular zlib. Of particular note, the [Cloudflare zlib](https://github.com/cloudflare/zlib) exploits modern hardware (available since 2008) for very rapid compression. Alternatively, you can compile dcm2niix without a gzip compressor. Regardless of how you compile dcm2niix, it can use the external program [pigz](https://github.com/madler/pigz) for parallel compression.
## Versions
[See the VERSIONS.md file for details on releases](./VERSIONS.md).
......@@ -33,7 +44,7 @@ Ubuntu: `sudo apt-get install cmake pkg-config`
MacOS: `brew install cmake pkg-config`
**To build:**
**Basic build:**
```bash
mkdir build && cd build
cmake ..
......@@ -41,13 +52,15 @@ make
```
`dcm2niix` will be created in the `bin` subfolder. To install on the system run `make install` instead of `make` - this will copy the executable to your path so you do not have to provide the full path to the executable.
**optional building with OpenJPEG:**
In rare case if cmake fails with the message like `"Generator: execution of make failed"`, it could be fixed by ``sudo ln -s `which make` /usr/bin/gmake``.
**Advanced build:**
Support for JPEG2000 using OpenJPEG is optional. To build with OpenJPEG change the cmake command to `cmake -DUSE_OPENJPEG=ON ..`:
As noted in the `Image Conversion and Compression Support` section, the software provides many optional modules with enhanced features. A common choice might be to include support for JPEG2000, [JPEG-LS](https://github.com/team-charls/charls) (this option requires a c++14 compiler), as well as using the high performance Cloudflare zlib library (this option requires a CPU built after 2008). To build with these options simply request them when configuring cmake:
```bash
mkdir build && cd build
cmake -DUSE_OPENJPEG=ON ..
cmake -DZLIB_IMPLEMENTATION=Cloudflare -DUSE_JPEGLS=ON -DUSE_OPENJPEG=ON ..
make
```
......@@ -61,8 +74,9 @@ If you have any problems with the cmake build script described above or want to
## Alternatives
- [Valerio Luccio's dinifti](http://cbi.nyu.edu/software/dinifti.php) is focused on conversion of Siemens data
- [Valerio Luccio's dinifti](http://cbi.nyu.edu/software/dinifti.php) is focused on conversion of Siemens data.
- [dcm2nii](http://www.mccauslandcenter.sc.edu/mricro/mricron/dcm2nii.htm) is the predecessor of dcm2niix. It is deprecated for modern images, but does handle image formats that predate DICOM (proprietary Elscint, GE and Siemens formats).
- [DWIConvert](https://github.com/BRAINSia/BRAINSTools/tree/master/DWIConvert) converts DICOM images to NRRD and NIfTI formats.
- [Xiangrui Li's dicm2nii](http://www.mathworks.com/matlabcentral/fileexchange/42997-dicom-to-nifti-converter) is written in Matlab. The Matlab language makes this very scriptable.
- [dicom2nifti](https://github.com/icometrix/dicom2nifti) uses the scriptable Python wrapper utilizes the [high performance GDCMCONV](http://gdcm.sourceforge.net/wiki/index.php/Gdcmconv) executables.
- [MRtrix mrconvert](http://mrtrix.readthedocs.io/en/latest/reference/commands/mrconvert.html) is a useful general purpose image converter and handles DTI data well. It is an outstanding tool for modern Philips enhanced images.
......@@ -80,7 +94,10 @@ If you have any problems with the cmake build script described above or want to
- [Dcm2Bids](https://github.com/cbedetti/Dcm2Bids) uses dcm2niix to create [BIDS](http://bids.neuroimaging.io/) datasets.
- [dcm2niir](https://github.com/muschellij2/dcm2niir) R wrapper for dcm2niix/dcm2nii.
- [dcm2niix_afni](https://afni.nimh.nih.gov/pub/dist/doc/program_help/dcm2niix_afni.html) is a version of dcm2niix included with the [AFNI](https://afni.nimh.nih.gov/) distribution.
- [dcm2niiXL](https://github.com/neurolabusc/dcm2niiXL) is a shell script and tuned compilation of dcm2niix designed for accelerated conversion of extra large datasets.
- [dicom2nifti_batch](https://github.com/scanUCLA/dicom2nifti_batch) is a Matlab script for automating dcm2niix.
- [divest](https://github.com/jonclayden/divest) R interface to dcm2niix.
- [fsleyes](https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/FSLeyes) is a powerful Python-based image viewer. It uses dcm2niix to handle DICOM files through its [fslpy libraries](https://users.fmrib.ox.ac.uk/~paulmc/fsleyes/fslpy/latest/fsl.data.dicom.html).
- [heudiconv](https://github.com/nipy/heudiconv) can use dcm2niix to create [BIDS](http://bids.neuroimaging.io/) datasets.
- [MRIcroGL](https://github.com/neurolabusc/MRIcroGL) is available for MacOS, Linux and Windows and provides a graphical interface for dcm2niix. You can get compiled copies from the [MRIcroGL NITRC web site](https://www.nitrc.org/projects/mricrogl/).
- [neuro_docker](https://github.com/Neurita/neuro_docker) includes dcm2niix as part of a single, static Dockerfile.
......
set(CLOUDFLARE_BRANCH gcc.amd64) # Cloudflare zlib branch
ExternalProject_Add(zlib
GIT_REPOSITORY "${git_protocol}://github.com/ningfei/zlib.git"
GIT_TAG "${CLOUDFLARE_BRANCH}"
SOURCE_DIR cloudflare-zlib
BINARY_DIR cloudflare-zlib-build
CMAKE_ARGS
-Wno-dev
-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
-DCMAKE_INSTALL_PREFIX:PATH=${DEP_INSTALL_DIR}
)
set(ZLIB_ROOT ${DEP_INSTALL_DIR})
......@@ -9,7 +9,7 @@ ExternalProject_Add(openjpeg
-Wno-dev
--no-warn-unused-cli
-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
-DCMAKE_INSTALL_PREFIX=${DEP_INSTALL_DIR}
-DCMAKE_INSTALL_PREFIX:PATH=${DEP_INSTALL_DIR}
)
set(OpenJPEG_DIR ${DEP_INSTALL_DIR}/lib/openjpeg-2.1)
......@@ -9,7 +9,7 @@ ExternalProject_Add(yaml-cpp
-Wno-dev
--no-warn-unused-cli
-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
-DCMAKE_INSTALL_PREFIX=${DEP_INSTALL_DIR}
-DCMAKE_INSTALL_PREFIX:PATH=${DEP_INSTALL_DIR}
)
set(YAML-CPP_DIR ${DEP_INSTALL_DIR}/lib/cmake/yaml-cpp)
......@@ -13,19 +13,22 @@ else()
endif()
# Basic CMake build settings
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING
"Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug;Release;RelWithDebInfo;MinSizeRel")
endif()
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
option(USE_STATIC_RUNTIME "Use static runtime" ON)
if(USE_STATIC_RUNTIME)
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
if(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
find_file(STATIC_LIBCXX "libstdc++.a" ${CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES})
mark_as_advanced(STATIC_LIBCXX)
if(NOT STATIC_LIBCXX)
unset(STATIC_LIBCXX CACHE)
# only on some Centos/Redhat systems
# Only on some Centos/Redhat systems
message(FATAL_ERROR
"\"USE_STATIC_RUNTIME\" set to ON but \"libstdcxx.a\" not found! \
\"yum install libstdc++-static\" to resolve the error.")
......@@ -33,11 +36,11 @@ if(USE_STATIC_RUNTIME)
endif()
endif()
option(USE_SYSTEM_ZLIB "Use the system zlib" OFF)
option(USE_TURBOJPEG "Use TurboJPEG to decode classic JPEG" OFF)
option(USE_JASPER "Build with JPEG2000 support using Jasper" OFF)
option(USE_OPENJPEG "Build with JPEG2000 support using OpenJPEG" OFF)
option(USE_JPEGLS "Build with JPEG-LS support using CharLS" OFF)
option(BATCH_VERSION "Build dcm2niibatch for multiple conversions" OFF)
include(ExternalProject)
......@@ -55,8 +58,8 @@ endif()
if(USE_OPENJPEG)
message("-- Build with OpenJPEG: ${USE_OPENJPEG}")
if(OpenJPEG_DIR OR OPENJPEG_DIR)
set(OpenJPEG_DIR "${OpenJPEG_DIR}${OPENJPEG_DIR}" CACHE PATH "Path to OpenJPEG configuration file" FORCE)
if(OpenJPEG_DIR)
set(OpenJPEG_DIR "${OpenJPEG_DIR}" CACHE PATH "Path to OpenJPEG configuration file" FORCE)
message("-- Using OpenJPEG library from ${OpenJPEG_DIR}")
else()
find_package(PkgConfig)
......@@ -88,7 +91,8 @@ if(BATCH_VERSION)
pkg_check_modules(YAML-CPP yaml-cpp)
endif()
if(YAML-CPP_FOUND)
# Build from github if not found or version < 0.5.3
if(YAML-CPP_FOUND AND NOT (YAML-CPP_VERSION VERSION_LESS "0.5.3"))
set(YAML-CPP_DIR ${YAML-CPP_LIBDIR}/cmake/yaml-cpp CACHE PATH "Path to yaml-cpp configuration file" FORCE)
message("-- Using yaml-cpp library from ${YAML-CPP_DIR}")
else()
......@@ -100,6 +104,21 @@ if(BATCH_VERSION)
endif()
endif()
set(ZLIB_IMPLEMENTATION "Miniz" CACHE STRING "Choose zlib implementation.")
set_property(CACHE ZLIB_IMPLEMENTATION PROPERTY STRINGS "Miniz;System;Cloudflare;Custom")
if(${ZLIB_IMPLEMENTATION} STREQUAL "Cloudflare")
message("-- Build with Cloudflare zlib: ON")
include(${CMAKE_SOURCE_DIR}/SuperBuild/External-CLOUDFLARE-ZLIB.cmake)
list(APPEND DEPENDENCIES zlib)
set(BUILD_CLOUDFLARE-ZLIB TRUE)
message("-- Will build Cloudflare zlib from github")
elseif(${ZLIB_IMPLEMENTATION} STREQUAL "Custom")
set(ZLIB_ROOT ${ZLIB_ROOT} CACHE PATH "Specify custom zlib root directory.")
if(NOT ZLIB_ROOT)
message(FATAL_ERROR "ZLIB_ROOT needs to be set to locate custom zlib!")
endif()
endif()
ExternalProject_Add(console
DEPENDS ${DEPENDENCIES}
DOWNLOAD_COMMAND ""
......@@ -109,11 +128,16 @@ ExternalProject_Add(console
-Wno-dev
--no-warn-unused-cli
-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
-DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}
-DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_BINARY_DIR}
-DCMAKE_C_FLAGS:STRING=${CMAKE_C_FLAGS}
-DCMAKE_CXX_FLAGS:STRING=${CMAKE_CXX_FLAGS}
-DCMAKE_VERBOSE_MAKEFILE:BOOL=${CMAKE_VERBOSE_MAKEFILE}
-DUSE_STATIC_RUNTIME:BOOL=${USE_STATIC_RUNTIME}
-DUSE_SYSTEM_ZLIB:BOOL=${USE_SYSTEM_ZLIB}
-DUSE_TURBOJPEG:BOOL=${USE_TURBOJPEG}
-DUSE_JASPER:BOOL=${USE_JASPER}
-DUSE_JPEGLS:BOOL=${USE_JPEGLS}
-DZLIB_IMPLEMENTATION:STRING=${ZLIB_IMPLEMENTATION}
-DZLIB_ROOT:PATH=${ZLIB_ROOT}
# OpenJPEG
-DUSE_OPENJPEG:BOOL=${USE_OPENJPEG}
-DOpenJPEG_DIR:PATH=${OpenJPEG_DIR}
......
## Versions
22-June-2018
- [fix issues where 6-June-2018 release could save Enhanced DICOM Philips bvec/bval with different order than .nii images](https://github.com/rordenlab/dcm2niix/issues/201).
6-June-2018
- [Improved Philips PAR/REC support](https://github.com/rordenlab/dcm2niix/issues/171)
- [Improved Philips Enhanced
DICOM support](https://github.com/rordenlab/dcm2niix/issues/170) including saving different [real, imaginary, magnitude and phase images in a single DICOM file](https://github.com/rordenlab/dcm2niix/issues/189).
- GE and Philips data now report [PhaseEncodingAxis](https://github.com/rordenlab/dcm2niix/issues/163) instead of PhaseEncodingDirection (these DICOMs store the dimension, but not the polarity).
- Experimental detection of [phase encoding direction for GE](https://github.com/rordenlab/dcm2niix/issues/163). To enable compile with "MY_DEBUG_GE" flag.
- Support for Philips Private RLE (1.3.46.670589.33.1.4.1) transfer syntax.
- Optional support for JPEG-LS (1.2.840.10008.1.2.4.80/1.2.840.10008.1.2.4.81) transfer syntaxes (using [CharLS](https://github.com/team-charls/charls)). Requires c++14.
- [Improved GE support](https://github.com/rordenlab/dcm2niix/issues/163)
- Optional [lossless integer scaling](https://github.com/rordenlab/dcm2niix/issues/198) for INT16 and UINT16 DICOM images that only use a fraction of the possible range.
15-Dec-2017
- Support [Siemens XA10 images](https://github.com/rordenlab/dcm2niix/pull/145).
- [Ability to select specific series to convert](https://github.com/rordenlab/dcm2niix/pull/146).
......
version: build-{build}
image: Visual Studio 2015
branches:
only:
- master
......@@ -32,7 +34,7 @@ before_build:
cd c:\projects\dcm2niix\build
cmake -G "Visual Studio 14 2015 Win64" -DBATCH_VERSION=ON -DUSE_OPENJPEG=ON ..\
cmake -Wno-dev -G "Visual Studio 14 2015 Win64" -DBATCH_VERSION=ON -DUSE_OPENJPEG=ON -DUSE_JPEGLS=true ..\
build:
project: c:\projects\dcm2niix\build\dcm2niix.sln
......
......@@ -12,17 +12,17 @@ else()
endif()
# Basic CMake build settings
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING
"Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug;Release;RelWithDebInfo;MinSizeRel")
endif()
set(PROGRAMS dcm2niix)
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
# using Clang
add_definitions(-fno-caret-diagnostics)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-dead_strip")
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
# using GCC
if(NOT (${CMAKE_CXX_COMPILER_VERSION} VERSION_LESS 4.5.0))
add_definitions(-Wno-unused-result) # available since GCC 4.5.0
......@@ -30,9 +30,7 @@ elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
if(NOT (${CMAKE_CXX_COMPILER_VERSION} VERSION_LESS 4.8.0))
add_definitions(-fno-diagnostics-show-caret) # available since GCC 4.8.0
endif()
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
# using Intel C++
elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
elseif(MSVC)
# using Visual Studio C++
add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4018") # '<': signed/unsigned mismatch
......@@ -49,7 +47,18 @@ elseif("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:8388608") # set "Stack Reserve Size" to 8MB (default value is 1MB)
endif()
add_executable(dcm2niix
# Compiler dependent flags
include (CheckCXXCompilerFlag)
if(UNIX)
check_cxx_compiler_flag(-msse2 HAS_SSE2)
if(HAS_SSE2)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse2 -mfpmath=sse")
endif()
endif()
set(PROGRAMS dcm2niix)
set(DCM2NIIX_SRCS
main_console.cpp
nii_dicom.cpp
jpg_0XC3.cpp
......@@ -59,8 +68,34 @@ add_executable(dcm2niix
nii_ortho.cpp
nii_dicom_batch.cpp)
option(USE_SYSTEM_ZLIB "Use the system zlib" OFF)
if(USE_SYSTEM_ZLIB)
option(USE_JPEGLS "Build with JPEG-LS support using CharLS" OFF)
if(USE_JPEGLS)
add_definitions(-DmyEnableJPEGLS)
if(MSVC)
add_definitions(-DCHARLS_STATIC)
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
set(CHARLS_SRCS
charls/jpegls.cpp
charls/jpegmarkersegment.cpp
charls/interface.cpp
charls/jpegstreamwriter.cpp
charls/jpegstreamreader.cpp)
add_executable(dcm2niix ${DCM2NIIX_SRCS} ${CHARLS_SRCS})
else()
add_executable(dcm2niix ${DCM2NIIX_SRCS})
endif()
set(ZLIB_IMPLEMENTATION "Miniz" CACHE STRING "Choose zlib implementation.")
set_property(CACHE ZLIB_IMPLEMENTATION PROPERTY STRINGS "Miniz;System;Custom")
if(NOT ${ZLIB_IMPLEMENTATION} STREQUAL "Miniz")
if(NOT ${ZLIB_IMPLEMENTATION} STREQUAL "System")
set(ZLIB_ROOT ${ZLIB_ROOT} CACHE PATH "Specify custom zlib root directory.")
if(NOT ZLIB_ROOT)
message(FATAL_ERROR "ZLIB_ROOT needs to be set to locate custom zlib!")
endif()
endif()
find_package(ZLIB REQUIRED)
add_definitions(-DmyDisableMiniZ)
target_include_directories(dcm2niix PRIVATE ${ZLIB_INCLUDE_DIRS})
......@@ -86,7 +121,7 @@ endif()
option(USE_OPENJPEG "Build with JPEG2000 support using OpenJPEG" OFF)
if(USE_OPENJPEG)
set(OpenJPEG_DIR "${OpenJPEG_DIR}${OPENJPEG_DIR}" CACHE PATH "Path to yaml-cpp configuration file" FORCE)
set(OpenJPEG_DIR "${OpenJPEG_DIR}" CACHE PATH "Path to OpenJPEG configuration file" FORCE)
find_package(OpenJPEG REQUIRED)
......@@ -106,9 +141,7 @@ endif()
option(BATCH_VERSION "Build dcm2niibatch for multiple conversions" OFF)
if(BATCH_VERSION)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
add_executable(dcm2niibatch
set(DCM2NIIBATCH_SRCS
main_console_batch.cpp
nii_dicom.cpp
jpg_0XC3.cpp
......@@ -118,6 +151,13 @@ if(BATCH_VERSION)
nii_ortho.cpp
nii_dicom_batch.cpp)
if(USE_JPEGLS)
add_executable(dcm2niibatch ${DCM2NIIBATCH_SRCS} ${CHARLS_SRCS})
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
add_executable(dcm2niibatch ${DCM2NIIBATCH_SRCS})
endif()
set(YAML-CPP_DIR ${YAML-CPP_DIR} CACHE PATH "Path to yaml-cpp configuration file" FORCE)
find_package(YAML-CPP REQUIRED)
......@@ -125,19 +165,16 @@ if(BATCH_VERSION)
target_link_libraries(dcm2niibatch ${YAML_CPP_LIBRARIES})
if(ZLIB_FOUND)
add_definitions(-DmyDisableMiniZ)
target_include_directories(dcm2niibatch PRIVATE ${ZLIB_INCLUDE_DIRS})
target_link_libraries(dcm2niibatch z)
target_link_libraries(dcm2niibatch ${ZLIB_LIBRARIES})
endif()
if(TURBOJPEG_FOUND)
add_definitions(-DmyTurboJPEG)
target_include_directories(dcm2niibatch PRIVATE ${TURBOJPEG_INCLUDEDIR})
target_link_libraries(dcm2niibatch ${TURBOJPEG_LIBRARIES})
endif()
if(JASPER_FOUND)
add_definitions(-DmyEnableJasper)
target_include_directories(dcm2niibatch PRIVATE ${JASPER_INCLUDE_DIR})
target_link_libraries(dcm2niibatch ${JASPER_LIBRARIES})
endif()
......@@ -145,8 +182,6 @@ if(BATCH_VERSION)
if(OPENJPEG_FOUND)
target_include_directories(dcm2niibatch PRIVATE ${OPENJPEG_INCLUDE_DIRS})
target_link_libraries(dcm2niibatch ${OPENJPEG_LIBRARIES})
else()
add_definitions(-DmyDisableOpenJPEG)
endif()
list(APPEND PROGRAMS dcm2niibatch)
......
https://github.com/team-charls/charls
Copyright (c) 2007-2010, Jan de Vaan
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of my employer, nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
[![Build status](https://ci.appveyor.com/api/projects/status/yq0naf3v2m8nfa8r/branch/master?svg=true)](https://ci.appveyor.com/project/vbaderks/charls/branch/master)
[![Build Status](https://travis-ci.org/team-charls/charls.svg?branch=master)](https://travis-ci.org/team-charls/charls)
# CharLS
CharLS is a C++ implementation of the JPEG-LS standard for lossless and near-lossless image compression and decompression.
JPEG-LS is a low-complexity image compression standard that matches JPEG 2000 compression ratios.
# CharLS and dcm2niix
[CharLS](https://github.com/team-charls/charls) is an optional module for dcm2niix. If included, it allows dcm2niix to handle the [JPEG-LS transfer syntaxes](https://www.nitrc.org/plugins/mwiki/index.php/dcm2nii:MainPage#DICOM_Transfer_Syntaxes_and_Compressed_Images). The included code was downloaded from the CharLS website on 6 June 2018.
It is worth noting that DICOM can specify three different [lossless forms of the JPEG](http://www.mccauslandcenter.sc.edu/crnl/tools/jpeg-formats) image standard. CharLS is used only for the JPEG-LS form (transfer syntaxes 1.2.840.10008.1.2.4.80/81; ISO/IEC 14495-1:1999 ITU-T.87). In contrast, dcm2niix uses bespoke code to handle the older JPEG-Lossless (1.2.840.10008.1.2.4.57/70; ISO/IEC 10918-1:1994 ITU-T.81). Finally, dcm2niix handles the very complex JPEG-2000 lossless (1.2.840.10008.1.2.4.90/91; ISO/IEC 15444-1:2004 ITU-T.800) using the [OpenJPEG](https://github.com/uclouvain/openjpeg) library.
To enable support you will need to include the `myEnableJPEGLS` compiler flag as well as a few file sin the `charls` folder. You will also need to specify `-std=c++14` and use a compiler that supports c++14 or later. Therefore, a minimal compile should look like this:
`g++ -I. -std=c++14 -DmyEnableJPEGLS charls/jpegls.cpp charls/jpegmarkersegment.cpp charls/interface.cpp charls/jpegstreamwriter.cpp charls/jpegstreamreader.cpp main_console.cpp nii_foreign.cpp nii_dicom.cpp jpg_0XC3.cpp ujpeg.cpp nifti1_io_core.cpp nii_ortho.cpp nii_dicom_batch.cpp -o dcm2niix -DmyDisableOpenJPEG`
The option `myEnableJPEGLS` specifies the latest version of CharLS (currently version 2). Alternatively, you can specify `myEnableJPEGLS1` to compile for CharLS version 1. This older code is not included with dcm2niix, but you can [download it from Github](https://github.com/team-charls/charls/tree/1.x-master). Note that CharLS version 1 is designed for c++03:
`g++ -I. -std=c++03 -DmyEnableJPEGLS1 charls1/header.cpp charls1/jpegls.cpp charls1/jpegmarkersegment.cpp charls1/interface.cpp charls1/jpegstreamwriter.cpp main_console.cpp nii_foreign.cpp nii_dicom.cpp jpg_0XC3.cpp ujpeg.cpp nifti1_io_core.cpp nii_ortho.cpp nii_dicom_batch.cpp -o dcm2niix -DmyDisableOpenJPEG`
Note that in these examples we have disabled OpenJPEG's JPEG2000 support. In reality, you will probably want to support both JPEG2000 and JPEG-LS, this will allow you to convert a broader range of images, and JPEG2000 includes lossy variations that do not have analogues for JPEG-LS. For details on adding the JPEG2000 module see this [compile page](https://github.com/rordenlab/dcm2niix/blob/master/COMPILE.md).
# JPEG-LS versus other lossless JPEG codecs
You can use gdcmconv to compare the performance of the ancient JPEG-lossless (gdcmconv -J; default mode for dcmcjpeg), JPEG-LS (gdcmconv -L) and JPEG2000-lossess (gdcmconv -K). Below is a sample test looking at 800 DICOM CT scans - with a raw size of 425mb which dcm2niix can convert in 1.6 seconds. The table shows that JPEG-LS reduces the file sizes to 137mb (0.39 original size), but that decompression takes 7.2 times longer. In contrast, the complicated JPEG2000 achieves only slightly better compression but is much slower to decompress.
| CT | Size | Speed |
| ----------------------------------------- | -----:| -----:|
| Raw 1.2.840.10008.1.2.1 | 1.00 | 1.0 |
| JPEG-lossless 1.2.840.10008.1.2.4.70 | 0.37 | 6.4 |
| JPEG-LS 1.2.840.10008.1.2.4.80 | 0.32 | 7.2 |
| JPEG2000 lossless 1.2.840.10008.1.2.4.90 | 0.31 | 60.1 |
Below is a sample test looking at 1092 DICOM MRI scans with a Siemens Prisma with 16-bit output (many older systems use 12-bit output which would presumably provide more compression potential) - with a raw size of 425mb which dcm2niix can convert in 4.7 seconds. Note that the MRI scans show poorer compression for all techniques.
| MRI | Size | Speed |
| ----------------------------------------- | -----:| -----:|
| Raw 1.2.840.10008.1.2.1 | 1.00 | 1.0 |
| JPEG-lossless 1.2.840.10008.1.2.4.70 | 0.65 | 5.0 |
| JPEG-LS 1.2.840.10008.1.2.4.80 | 0.60 | 7.7 |
| JPEG2000 lossless 1.2.840.10008.1.2.4.90 | 0.61 | 71.6 |
The tables above describe illustrate the speed for decompression. With respect to compression, the MRI images take 54 seconds to compress as JPEG-lossless, 72 seconds to compress as JPEG-LS and 212 seconds for JPEG2000 lossless. These tests support the notion that JPEG-LS provides similar compression to JPEG2000 lossless with much faster compression and decompression. In fairness, it should be noted that all these tests use open source OpenJPEG library for JPEG2000 compression and decompression. This library is known to be robust but [slow compared to proprietary libraries](https://blog.hexagongeospatial.com/jpeg2000-quirks/).
## Features
* C++14 library implementation with a binary C interface for maximum interoperability.</br>Note: a C++03 compatible implementation is maintained in the 1.x-master branch.
* Supports Windows, Linux and Solaris in 32 bit and 64 bit.
* Includes an adapter assembly for .NET based languages.
* Excellent compression and decompression performance.
## About JPEG-LS
JPEG-LS (ISO/IEC 14495-1:1999 / ITU-T.87) is an image compression standard derived from the Hewlett Packard LOCO algorithm. JPEG-LS has low complexity (meaning fast compression) and high compression ratios, similar to the JPEG 2000 lossless ratios. JPEG-LS is more similar to the old Lossless JPEG than to JPEG 2000, but interestingly the two different techniques result in vastly different performance characteristics.
Wikipedia on lossless JPEG and JPEG-LS: <http://en.wikipedia.org/wiki/Lossless_JPEG>
Tip: the ITU makes their version of the JPEG-LS standard (ITU-T.87) freely available for download, the text is identical with the ISO version.
## About this software
This project's goal is to provide a full implementation of the ISO/IEC 14495-1:1999, "Lossless and near-lossless compression of continuous-tone still images: Baseline" standard. This library is written from scratch in portable C++. The master branch uses modern C++14. The 1.x branch is maintained in C++03. All mainstream JPEG-LS features are implemented by this library.
According to preliminary test results published on http://imagecompression.info/gralic, CharLS is about *twice as fast* as the original HP code, and beats both JPEG-XR and JPEG 2000 by a factor 3.
### Limitations
* No support for (optional) JPEG restart markers (RST). These markers are rarely used in practice.
* No support for the SPIFF file header.
* No support for oversize image dimension. Maximum supported image dimensions are [1, 65535] by [1, 65535].
* After releasing the original baseline standrd 14495-1:1999, ISO released an extension to the JPEG-LS standard called ISO/IEC 14495-2:2003: "Lossless and near-lossless compression of continuous-tone still images: Extensions". CharLS doesn't support these extensions.
## Supported platforms
The code is regularly compiled/tested on Windows and 64 bit Linux. Additionally, the code has been successfully tested on Linux Intel/AMD 32/64 bit (slackware, debian, gentoo), Solaris SPARC systems, Intel based Macs and Windows CE (ARM CPU, emulated), where the less common compilers may require minor code edits. It leverages C++ language features (templates, traits) to create optimized code, which generally perform best with recent compilers. If you compile with GCC, 64 bit code performs substantially better.
## Users & Acknowledgements
CharLS is being used by [GDCM DICOM toolkit](http://sourceforge.net/projects/gdcm/), thanks for [Mathieu Malaterre](http://sourceforge.net/users/malat) for getting CharLS started on Linux. [Kato Kanryu](http://knivez.homelinux.org/) wrote an initial version of the color transfroms and the DIB output format code, for an [irfanview](http://www.irfanview.com) plugin using CharLS. Thanks to Uli Schlachter, CharLS now finally runs correctly on big-endian architectures like Sun SPARC.
## Legal
The code in this project is available through a BSD style license, allowing use of the code in commercial closed source applications if you wish. **All** the code in this project is written from scratch, and not based on other JPEG-LS implementations. Be aware that Hewlett Packard claims to own patents that apply to JPEG-LS implementations, but they license it for free for conformant JPEG-LS implementations. Read more at <http://www.hpl.hp.com/loco/> before you use this if you use this code for commercial purposes.
/*
(C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
*/
#ifndef CHARLS_CHARLS
#define CHARLS_CHARLS
#include "publictypes.h"
// Windows and building CharLS DLL itself.
#if defined(WIN32) && defined(CHARLS_DLL_BUILD)
#define CHARLS_IMEXPORT(returntype) __declspec(dllexport) returntype __stdcall // NOLINT
#endif
// Non-windows (static linking)
#if !defined(CHARLS_IMEXPORT) && !defined(_WIN32)
#define CHARLS_IMEXPORT(returntype) returntype
#endif
// Windows static linking
#if !defined(CHARLS_IMEXPORT) && defined(CHARLS_STATIC)
#define CHARLS_IMEXPORT(returntype) returntype
#endif
// Windows DLL
#if !defined(CHARLS_IMEXPORT) && defined(CHARLS_DLL)
#define CHARLS_IMEXPORT(returntype) __declspec(dllimport) returntype __stdcall
#endif
#if !defined(CHARLS_IMEXPORT)
#error Please #define CHARLS_STATIC or CHARLS_DLL before including "charls.h" to indicate if CharLS is built as a static library or as a dll.
#endif
#ifdef __cplusplus
extern "C"
{
#else
#include <stddef.h>
#endif
/// <summary>
/// Encodes a byte array with pixel data to a JPEG-LS encoded (compressed) byte array.
/// </summary>
/// <param name="destination">Byte array that holds the encoded bytes when the function returns.</param>
/// <param name="destinationLength">Length of the array in bytes. If the array is too small the function will return an error.</param>
/// <param name="bytesWritten">This parameter will hold the number of bytes written to the destination byte array. Cannot be NULL.</param>
/// <param name="source">Byte array that holds the pixels that should be encoded.</param>
/// <param name="sourceLength">Length of the array in bytes.</param>
/// <param name="params">Parameter object that describes the pixel data and how to encode it.</param>
/// <param name="errorMessage">Character array of at least 256 characters or NULL. Hold the error message when a failure occurs, empty otherwise.</param>
CHARLS_IMEXPORT(CharlsApiResultType) JpegLsEncode(void* destination, size_t destinationLength, size_t* bytesWritten,
const void* source, size_t sourceLength, const struct JlsParameters* params, char* errorMessage);
/// <summary>
/// Retrieves the JPEG-LS header. This info can be used to pre-allocate the uncompressed output buffer.
/// </summary>
/// <param name="compressedData">Byte array that holds the JPEG-LS encoded data of which the header should be extracted.</param>
/// <param name="compressedLength">Length of the array in bytes.</param>
/// <param name="params">Parameter object that describes how the pixel data is encoded.</param>
/// <param name="errorMessage">Character array of at least 256 characters or NULL. Hold the error message when a failure occurs, empty otherwise.</param>
CHARLS_IMEXPORT(CharlsApiResultType) JpegLsReadHeader(const void* compressedData, size_t compressedLength,
struct JlsParameters* params, char* errorMessage);
/// <summary>
/// Encodes a JPEG-LS encoded byte array to uncompressed pixel data byte array.
/// </summary>
/// <param name="destination">Byte array that holds the uncompressed pixel data bytes when the function returns.</param>
/// <param name="destinationLength">Length of the array in bytes. If the array is too small the function will return an error.</param>
/// <param name="source">Byte array that holds the JPEG-LS encoded data that should be decoded.</param>
/// <param name="sourceLength">Length of the array in bytes.</param>
/// <param name="params">Parameter object that describes the pixel data and how to decode it.</param>
/// <param name="errorMessage">Character array of at least 256 characters or NULL. Hold the error message when a failure occurs, empty otherwise.</param>
CHARLS_IMEXPORT(CharlsApiResultType) JpegLsDecode(void* destination, size_t destinationLength,
const void* source, size_t sourceLength, const struct JlsParameters* params, char* errorMessage);
CHARLS_IMEXPORT(CharlsApiResultType) JpegLsDecodeRect(void* uncompressedData, size_t uncompressedLength,
const void* compressedData, size_t compressedLength,
struct JlsRect roi, const struct JlsParameters* info, char* errorMessage);
#ifdef __cplusplus
}
CHARLS_IMEXPORT(CharlsApiResultType) JpegLsEncodeStream(ByteStreamInfo compressedStreamInfo, size_t& pcbyteWritten, ByteStreamInfo rawStreamInfo, const JlsParameters& params, char* errorMessage);
CHARLS_IMEXPORT(CharlsApiResultType) JpegLsDecodeStream(ByteStreamInfo rawStream, ByteStreamInfo compressedStream, const JlsParameters* info, char* errorMessage);
CHARLS_IMEXPORT(CharlsApiResultType) JpegLsReadHeaderStream(ByteStreamInfo rawStreamInfo, JlsParameters* params, char* errorMessage);
#endif
#endif
//
// (C) Jan de Vaan 2007-2010, all rights reserved. See the accompanying "License.txt" for licensed use.
//
#ifndef CHARLS_COLORTRANSFORM
#define CHARLS_COLORTRANSFORM
#include "util.h"
// This file defines simple classes that define (lossless) color transforms.
// They are invoked in processline.h to convert between decoded values and the internal line buffers.
// Color transforms work best for computer generated images, but are outside the official JPEG-LS specifications.
template<typename T>
struct TransformNoneImpl
{
static_assert(std::is_integral<T>::value, "Integral required.");
using size_type = T;
FORCE_INLINE Triplet<T> operator()(int v1, int v2, int v3) const noexcept
{
return Triplet<T>(v1, v2, v3);
}
};
template<typename T>
struct TransformNone : TransformNoneImpl<T>
{
static_assert(std::is_integral<T>::value, "Integral required.");
using Inverse = TransformNoneImpl<T>;
};
template<typename T>
struct TransformHp1
{
static_assert(std::is_integral<T>::value, "Integral required.");
using size_type = T;
struct Inverse
{
explicit Inverse(const TransformHp1&) noexcept
{
}
FORCE_INLINE Triplet<T> operator()(int v1, int v2, int v3) const noexcept
{
return Triplet<T>(v1 + v2 - Range / 2, v2, v3 + v2 - Range / 2);
}
};
FORCE_INLINE Triplet<T> operator()(int red, int green, int blue) const noexcept
{
Triplet<T> hp1;
hp1.v2 = static_cast<T>(green);
hp1.v1 = static_cast<T>(red - green + Range / 2);
hp1.v3 = static_cast<T>(blue - green + Range / 2);
return hp1;
}
private:
static constexpr size_t Range = 1 << (sizeof(T) * 8);
};
template<typename T>
struct TransformHp2
{
static_assert(std::is_integral<T>::value, "Integral required.");
using size_type = T;
struct Inverse
{
explicit Inverse(const TransformHp2&) noexcept
{
}
FORCE_INLINE Triplet<T> operator()(int v1, int v2, int v3) const noexcept
{
Triplet<T> rgb;
rgb.R = static_cast<T>(v1 + v2 - Range / 2); // new R
rgb.G = static_cast<T>(v2); // new G
rgb.B = static_cast<T>(v3 + ((rgb.R + rgb.G) >> 1) - Range / 2); // new B
return rgb;
}
};
FORCE_INLINE Triplet<T> operator()(int red, int green, int blue) const noexcept
{
return Triplet<T>(red - green + Range / 2, green, blue - ((red + green) >> 1) - Range / 2);
}
private:
static constexpr size_t Range = 1 << (sizeof(T) * 8);
};
template<typename T>
struct TransformHp3
{
static_assert(std::is_integral<T>::value, "Integral required.");
using size_type = T;
struct Inverse
{
explicit Inverse(const TransformHp3&) noexcept
{
}
FORCE_INLINE Triplet<T> operator()(int v1, int v2, int v3) const noexcept
{
const int G = v1 - ((v3 + v2) >> 2) + Range / 4;
Triplet<T> rgb;
rgb.R = static_cast<T>(v3 + G - Range / 2); // new R
rgb.G = static_cast<T>(G); // new G
rgb.B = static_cast<T>(v2 + G - Range / 2); // new B
return rgb;
}
};
FORCE_INLINE Triplet<T> operator()(int red, int green, int blue) const noexcept
{
Triplet<T> hp3;
hp3.v2 = static_cast<T>(blue - green + Range / 2);
hp3.v3 = static_cast<T>(red - green + Range / 2);
hp3.v1 = static_cast<T>(green + ((hp3.v2 + hp3.v3) >> 2)) - Range / 4;
return hp3;
}
private:
static constexpr size_t Range = 1 << (sizeof(T) * 8);
};
// Transform class that shifts bits towards the high bit when bit count is not 8 or 16
// needed to make the HP color transformations work correctly.
template<typename Transform>
struct TransformShifted
{
using size_type = typename Transform::size_type;
struct Inverse
{
explicit Inverse(const TransformShifted& transform) noexcept
: _shift(transform._shift),
_inverseTransform(transform._colortransform)
{
}
FORCE_INLINE Triplet<size_type> operator()(int v1, int v2, int v3) noexcept
{
const Triplet<size_type> result = _inverseTransform(v1 << _shift, v2 << _shift, v3 << _shift);
return Triplet<size_type>(result.R >> _shift, result.G >> _shift, result.B >> _shift);
}
FORCE_INLINE Quad<size_type> operator()(int v1, int v2, int v3, int v4)
{
Triplet<size_type> result = _inverseTransform(v1 << _shift, v2 << _shift, v3 << _shift);
return Quad<size_type>(result.R >> _shift, result.G >> _shift, result.B >> _shift, v4);
}
private:
int _shift;
typename Transform::Inverse _inverseTransform;
};
explicit TransformShifted(int shift) noexcept
: _shift(shift)
{
}
FORCE_INLINE Triplet<size_type> operator()(int red, int green, int blue) noexcept
{
const Triplet<size_type> result = _colortransform(red << _shift, green << _shift, blue << _shift);
return Triplet<size_type>(result.R >> _shift, result.G >> _shift, result.B >> _shift);
}
FORCE_INLINE Quad<size_type> operator()(int red, int green, int blue, int alpha)
{
Triplet<size_type> result = _colortransform(red << _shift, green << _shift, blue << _shift);
return Quad<size_type>(result.R >> _shift, result.G >> _shift, result.B >> _shift, alpha);
}
private:
int _shift;
Transform _colortransform;
};
#endif
//
// Copyright CharLS Team, all rights reserved. See the accompanying "License.txt" for licensed use.
//
#ifndef CHARLS_CONSTANTS
#define CHARLS_CONSTANTS
// Default threshold values for JPEG-LS statistical modeling as defined in ISO/IEC 14495-1, Table C.3
// for the case MAXVAL = 255 and NEAR = 0.
// Can be overridden at compression time, however this is rarely done.
const int DefaultThreshold1 = 3; // BASIC_T1
const int DefaultThreshold2 = 7; // BASIC_T2
const int DefaultThreshold3 = 21; // BASIC_T3
const int DefaultResetValue = 64; // Default RESET value as defined in ISO/IEC 14495-1, table C.2
#endif