[med-svn] [Git][med-team/dcm2niix][upstream/latest] New upstream version 1.0.20200331

Nilesh Patra gitlab at salsa.debian.org
Tue Sep 29 13:39:21 BST 2020



Nilesh Patra pushed to branch upstream/latest at Debian Med / dcm2niix


Commits:
af44ba06 by Nilesh Patra at 2020-09-29T18:05:16+05:30
New upstream version 1.0.20200331
- - - - -


29 changed files:

- .travis.yml
- FILENAMING.md
- GE/README.md
- PARREC/README.md
- Philips/README.md
- README.md
- RENAMING.md
- Siemens/README.md
- SuperBuild/SuperBuild.cmake
- + Toshiba/README.md
- + Troubleshooting/README.md
- appveyor.yml
- console/CMakeLists.txt
- + console/Info.plist
- console/jpg_0XC3.cpp
- console/main_console.cpp
- console/makefile
- console/nifti1.h
- console/nifti1_io_core.cpp
- console/nifti1_io_core.h
- console/nii_dicom.cpp
- console/nii_dicom.h
- console/nii_dicom_batch.cpp
- console/nii_dicom_batch.h
- console/nii_foreign.cpp
- console/print.h
- console/ujpeg.h
- license.txt
- + notarize.command


Changes:

=====================================
.travis.yml
=====================================
@@ -27,15 +27,15 @@ before_install:
   - git submodule update --init --depth=3 dcm_qa_uih
 
 script:
-  - mkdir build && cd build && cmake -DBATCH_VERSION=ON -DUSE_OPENJPEG=ON -DUSE_JPEGLS=true -DZLIB_IMPLEMENTATION=Cloudflare .. && make && cd -
+  # - mkdir build && cd build && cmake -DBATCH_VERSION=ON -DUSE_OPENJPEG=ON -DUSE_JPEGLS=true -DZLIB_IMPLEMENTATION=Cloudflare .. && make && cd -
+  - mkdir build && cd build && cmake -DBATCH_VERSION=OFF -DUSE_OPENJPEG=ON -DUSE_JPEGLS=true -DZLIB_IMPLEMENTATION=Cloudflare .. && make && cd -
   - export PATH=$PWD/build/bin:$PATH
   - cd dcm_qa && ./batch.sh && cd -
   - cd dcm_qa_nih && ./batch.sh && cd -
   - cd dcm_qa_uih && ./batch.sh && cd -
 
 before_deploy:
-  - export DATE=`date +%-d-%b-%Y`
-  - zip -j dcm2niix_${DATE}_${TARGET}.zip build/bin/*
+  - zip -j dcm2niix_${TARGET}.zip build/bin/*
   - sleep 300 # make sure appveyor deployment is done, thus proper release name is set
 
 deploy:


=====================================
FILENAMING.md
=====================================
@@ -4,47 +4,66 @@ DICOM files tend to have bizarre file names, for example based on the instance U
 
 ## Basics
 
-You request the output filename with the `-f` argument. For example, consider you convert files with `dcm2niix -f %s_%p`: in this case an image from series 3 with the protocol name `T1` will be saved as `3_T1.nii`. Here are the available parameters for file names:
+You request the output file name with the `-f` argument. For example, consider you convert files with `dcm2niix -f %s_%p`: in this case an image from series 3 with the protocol name `T1` will be saved as `3_T1.nii`. Here are the available parameters for file names:
 
  - %a=antenna (coil) name (from Siemens 0051,100F)
- - %b=basename (filename of first DICOM)
+ - %b=basename (file name of first DICOM)
  - %c=comments (from 0020,4000)
  - %d=description (from 0008,103E)
  - %e=echo number (from 0018,0086)
  - %f=folder name (name of folder containing first DICOM)
  - %i=ID of patient (from 0010,0020)
- - %j=seriesInstanceUID (from 0020,000E)
- - %k=studyInstanceUID (from 0020,000D)
+ - %j=series instance UID (from 0020,000E)
+ - %k=study instance UID (from 0020,000D)
+ - %l=local procedure step description (from 0040,0254)
  - %m=manufacturer short name (from 0008,0070: GE, Ph, Si, To, UI, NA)
  - %n=name of patient (from 0010,0010)
+ - %o=mediaObjectInstanceUID (0002,0003)*
  - %p=protocol name (from 0018,1030)
- - %r=instance number (from 0020,0013)
+ - %r=instance number (from 0020,0013)*
  - %s=series number (from 0020,0011)
  - %t=time of study (from 0008,0020 and 0008,0030)
  - %u=acquisition number (from 0020,0012)
  - %v=vendor long name (from 0008,0070: GE, Philips, Siemens, Toshiba, UIH, NA)
  - %x=study ID (from 0020,0010)
+ - %y=youth in series: GE RawDataRunNumber ([0019,10A2](https://github.com/rordenlab/dcm2niix/issues/359)) else TemporalPosition ([0020,0100](https://github.com/rordenlab/dcm2niix/issues/357))*
  - %z=sequence name (from 0018,0024)
+ 
+* Attributes listed above with an asterisk (*) are likely to vary within a series, and are typically not useful for DICOM to NIfTI conversion (where all images from a series are stacked together). These attributes can be useful for [renaming](RENAMING.md) DICOM images
 
-## Filename Post-fixes: Image Disambiguation
+## File Name Post-fixes: Image Disambiguation
 
-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:
+In general dcm2niix creates images with 3D dimensions, or 4 dimensions when the 4th dimension is time (fMRI) or gradient number (DWI). However, DICOM images can include additional dimensions, e.g. a multiple-echo sequence would generate separate images for each echo. By default dcm2niix will use the following extensions to the file names in order to disambiguate additional dimensions from the same series:
 
  - _cNx.._cNz  where C* refers to the coil name (typically only seen for uncombined data, where a separate image is generated for each antenna)
  - _e1..eN echo number for multi-echo sequences
+ - _Eq is commonly seen in [CT scans](https://github.com/neurolabusc/dcm_qa_ct). For example, CT scans of the brain often have many slices closely packed near the brain stem and only a few slices spread far apart near the top of the head. Variable between-slice spacing is rarer in MRI, and if you see this from a MRI sequence you should ensure that [all of the acquired slices have been provided to dcm2niix](https://neurostars.org/t/field-mapping-siemens-scanners-dcm2niix-output-2-bids/2075/7). NIfTI asumes all 2D slices that form a 3D stack are equidistant. Therefore, dcm2niix reslices the input data to generate an equidistant volume.
  - _ph phase map
+ - _iN appended image number for non-parallel slices
  - _imaginary imaginary component of complex image
+ - _MoCo is appended to the ProtocolName if Image Type (0008,0008) includes the term 'MOCO'. This helps disambiguate Siemens fMRI runs where both motion corrected and raw data is stored for a single session.
  - _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. A 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.
+ - _t  If the trigger delay time (0020,9153) or trigger time (0018,1060) is non-zero, it will be recorded in the file name. 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).
  - _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.
- - _MoCo is appended to the ProtocolName if Image Type (0008,0008) includes the term 'MOCO'. This helps disambiguate Siemens fMRI runs where both motion corrected and raw data is stored for a single session.
+
+Some post-fixes are specific to Philips DICOMs
+ - _ADC Philips specific case. A 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').
+ - _Raw Philips XX_* DICOMs (Raw Data Storage).
+ - _PS Philips PS_* DICOMs (Grayscale Softcopy Presentation State).
+
+If you do not want post-fixes, run dcm2niix in the terse mode (`--terse`). In this mode, most post-fixes will be omitted. Beware that this mode can have name clashes, and images from a series may over write each other.  
+
+## File Name Conflicts
+
+dcm2niix will attempt to write your image using the naming scheme you specify with the '-f' parameter. However, if an image already exists with the specified output name, dcm2niix will append a letter (e.g. 'a') to the end of a file name to avoid overwriting existing images. Consider a situation where dcm2niix is run with '-f %t'. This will name images based on the study time. If a single study has multiple series (for example, a T1 sequence and a fMRI scan, the reulting file names will conflict with each other. In order to avoid overwriting images, dcm2niix will resort to adding the post fix 'a', 'b', etc. There are a few solutions to avoiding these situations. You may want to consider using both of these:
+ - Make sure you specify a naming scheme that can discriminate between your images. For example '-f %t' will not disambiguate different series acquired in the same session. However, '-f %t_%s' will discriminate between series.
+ - Localizer (scout) images are the first scans acquired for any scanning session, and are used to plan the location for subsequent images. Localizers are not used in subsequent analyses (due to resolution, artefacts, etc). Localizers are often acquired with three orthogonal image planes (sagittal, coronal and axial). The NIfTI format requires that all slices in a volume are co-planar, so these localizers will generate naming conflicts. The solution is to use '-i y' which will ignore (not convert) localizers (it will also ignore derived images and 2D slices). This command helps exclude images that are not required for subsequent analyses.
+ - Be aware that if you run dcm2niix twice with the same parameters on the same data, you will encounter file naming conflicts.
 
 ## Special Characters
 
-[Some characters are not permitted](https://stackoverflow.com/questions/1976007/what-characters-are-forbidden-in-windows-and-linux-directory-names) in filenames. The following characters will be replaced with underscorces (`_`). Note that the forbidden characters vary between operating systems (Linux only forbids the forward slash, MacOS forbids forward slash and colon, while Windows forbids any of the characters listed below). To ensure that files can be easily copied between file systems, [dcm2niix restricts filenames to characters allowed by Windows](https://github.com/rordenlab/dcm2niix/issues/237).
+[Some characters are not permitted](https://stackoverflow.com/questions/1976007/what-characters-are-forbidden-in-windows-and-linux-directory-names) in file names. The following characters will be replaced with underscorces (`_`). Note that the forbidden characters vary between operating systems (Linux only forbids the forward slash, MacOS forbids forward slash and colon, while Windows forbids any of the characters listed below). To ensure that files can be easily copied between file systems, [dcm2niix restricts file names to characters allowed by Windows](https://github.com/rordenlab/dcm2niix/issues/237).
 
 ### List of Forbidden Characters (based on Windows)
 ```
@@ -57,4 +76,6 @@ In general dcm2niix creates images with 3D dimensions, or 4 dimensions when the
 | (vertical bar or pipe)
 ? (question mark)
 * (asterisk)
-```
\ No newline at end of file
+```
+
+Be warned that dcm2niix will copy all allowed characters verbatim, which can cause problems for some other tools. Consider this [sample dataset](https://github.com/neurolabusc/dcm_qa_nih/tree/master/In/20180918GE/mr_0004) where the DICOM Protocol Name (0018,1030) is 'Axial_EPI-FMRI_(Interleaved_I_to_S)'. The parentheses ("round brackets") may cause other tools issues. Consider converting this series with the command 'dcm2niix -f %s_%p ~/DICOM' to create the file '4_Axial_EPI-FMRI_(Interleaved_I_to_S).nii'.If you now run the command 'fslhd 4_Axial_EPI-FMRI_(Interleaved_I_to_S).nii' you will get the error '-bash: syntax error near unexpected token `(''. Therefore, it is often a good idea to use double quotes to specify the names of files. In this example 'fslhd "4_Axial_EPI-FMRI_(Interleaved_I_to_S).nii"' will work correctly.
\ No newline at end of file


=====================================
GE/README.md
=====================================
@@ -1,6 +1,6 @@
 ## About
 
-dcm2niix attempts to convert GE DICOM format images to NIfTI. The current generation DICOM files generated be GE equipment is quite impoverished relative to other vendors. Therefore, the amount of information dcm2niix is able to extract is relatively limited. Hopefully, in the future GE will provide more details that are critical for brain scientists.
+dcm2niix attempts to convert GE DICOM format images to NIfTI. The current generation DICOM files generated by GE equipment is quite impoverished relative to other vendors. Therefore, the amount of information dcm2niix is able to extract is relatively limited. Hopefully, in the future GE will provide more details that are critical for brain scientists.
 
 ## Diffusion Tensor Notes
 
@@ -10,17 +10,28 @@ The [NA-MIC Wiki](https://www.na-mic.org/wiki/NAMIC_Wiki:DTI:DICOM_for_DWI_and_D
 
 Knowing the relative timing of the acquisition for each 2D slice in a 3D volume is useful for [slice time correction](https://www.mccauslandcenter.sc.edu/crnl/tools/stc) of both fMRI and DTI data. Unfortunately, current GE software does not provide a consistent way to record this.
 
-[Some sequences](https://afni.nimh.nih.gov/afni/community/board/read.php?1,154006) encode the RTIA Timer (0021,105E) element. For example, [this dataset DV24](https://github.com/nikadon/cc-dcm2bids-wrapper/tree/master/dicom-qa-examples/ge-mr750-slice-timing) includes timing data, while [this DV26 dataset does not](https://github.com/neurolabusc/dcm_qa_nih). Even with the sequences that do encode the RTIA Timer, there is some debate regarding the accuracy of this element. In the example listed, the slice times are clearly wrong in the first volume. Therefore, dcm2niix always estimates slice times based on the 2nd volume in a time series.
+[Some sequences](https://afni.nimh.nih.gov/afni/community/board/read.php?1,154006) encode the RTIA Timer (0021,105E) element. For example, [this DV24 dataset](https://github.com/nikadon/cc-dcm2bids-wrapper/tree/master/dicom-qa-examples/ge-mr750-slice-timing) includes timing data, while [this DV26 dataset does not](https://github.com/neurolabusc/dcm_qa_nih). Be aware that different versions of GE software appear to use different units for 0021,105E. The DV24 example is reported in seconds, while [14.0 uses 1/10000 seconds](https://github.com/rordenlab/dcm2niix/issues/286). An example of the latter format can be found [here](https://www.nitrc.org/plugins/mwiki/index.php/dcm2nii:MainPage#Archival_MRI). Even with the sequences that do encode the RTIA Timer, there is some debate regarding the accuracy of this element. In the example listed, the slice times are clearly wrong in the first volume. Therefore, dcm2niix always estimates slice times based on the 2nd volume in a time series.
 
-In general, fMRI acquired using GE product sequence (PSD) “epi” with the multiphase option will store slice timing in the Trigger Time (DICOM 0018,1060) element. The current version of dcm2niix ignores this field, as no examples are available. In contrast, the popular PSD “epiRT” (BrainWave RT, fMRI/DTI package provided by Medical Numerics) does not save this tag (though in some cases it saves the RTIA Timer). Examples are [available](https://www.nitrc.org/plugins/mwiki/index.php/dcm2nii:MainPage#Slice_timing_correction) for both the “epiRT” and “epi” sequences.
+In general, fMRI acquired using GE product sequence (PSD) “epi” with the multiphase option will store slice timing in the Trigger Time (DICOM 0018,1060) element. In contrast, the popular PSD “epiRT” (BrainWave RT, fMRI/DTI package provided by Medical Numerics) does not save this tag (though in some cases it saves the RTIA Timer). Examples are [available](https://www.nitrc.org/plugins/mwiki/index.php/dcm2nii:MainPage#Slice_timing_correction) for both the “epiRT” and “epi” sequences.
 
-## User Define Data GE  (0043,102A)
+If neither Trigger Time (DICOM 0018,1060) or RTIA Timer (0021,105E) store slice timing information, a final option is to decode the GE Protocol Data Block as described below. At best, this block only reports whether the acquisition was interleaved or sequential. As long as one assumes the acquisition was continuous (with no temporal gap between volumes, e.g. sparse images) on can use this value, the number of slices in the volume and the repetition time to infer slice times.
+
+## User Define Data GE (0043,102A)
 
 This private element of the DICOM header is used to determine the phase encoding polarity. Specifically, we need to know the "Ky traversal direction" (top-down, or bottom up) and the phase encoding polarity. Unfortunately, this data is stored in a complicated, proprietary structure, that has changed with different releases of GE software. [Click here to see the definition for this structure](https://github.com/ScottHaileRobertson/GE-MRI-Tools/blob/master/GePackage/%2BGE/%2BPfile/%2BHeader/%2BRDB15/rdbm.h)..
 
+## Multi-Echo EPI Sequences
+
+Current GE software (DV26.0_R03_1831.b) running research multi-echo sequences create invalid DICOM images. The required public [EchoTime (0018,0081)](https://dicom.innolitics.com/ciods/mr-image/mr-image/00180081) attribute lists the shortest echo time for the series, rather than the actual echo time for the given DICOM image. The public tag [EchoNumber (0018,0086)](https://dicom.innolitics.com/ciods/mr-image/mr-image/00180086) reports `1` for all echoes. These limitations in GE's DICOM images disrupt dcm2niix's image conversion. Hopefully future product sequences will generate valid DICOM data. In the meantime, [issue 359](https://github.com/rordenlab/dcm2niix/issues/359) provides a kludge for image conversion.
+
+
+## Imkage Interpolation
+
+Some sequences allow the user to interpolate images in plane (e.g. saving a 2D 64x64 EPI image as 128x128) or between slices (e.g. saving a 126 slice T1-weighted image as 252 images). The resulting files require much more disk space, add no new information, are slower to process and can [disrupt some tools](https://mrtrix.readthedocs.io/en/latest/reference/commands/mrdegibbs.html). Users are strongly discouraged from interpolating raw data. However, dcm2niix should correctly detect this interpolation, resolving apparent discrepancies between tags (0020,1002; 0021,104F; 0054,0081). [Issue 355](https://github.com/rordenlab/dcm2niix/issues/355) provides details.
+
 ## Total Readout Time
 
-One often wants to determine [echo spacing, bandwidth, ](https://support.brainvoyager.com/brainvoyager/functional-analysis-preparation/29-pre-processing/78-epi-distortion-correction-echo-spacing-and-bandwidth) and total read-out time for EPI data so they can be undistorted. Total readout time is influence by parallel acceleration factor, bandwidth, number of EPI lines, and partial Fourier. Not all of these parameters are available from the GE DICOM images, so a user needs to check the scanner console.
+One often wants to determine [echo spacing, bandwidth](https://support.brainvoyager.com/brainvoyager/functional-analysis-preparation/29-pre-processing/78-epi-distortion-correction-echo-spacing-and-bandwidth) and total read-out time for EPI data so they can be undistorted. Total readout time is influence by parallel acceleration factor, bandwidth, number of EPI lines, and partial Fourier. Not all of these parameters are available from the GE DICOM images, so a user needs to check the scanner console.
 
 ## GE Protocol Data Block
 
@@ -33,5 +44,6 @@ In addition to the public DICOM tags, previous versions of dcm2niix attempted to
 ## Sample Datasets
 
  - [A validation dataset for dcm2niix commits](https://github.com/neurolabusc/dcm_qa_nih).
+ - [Slice timing validation](https://github.com/neurolabusc/dcm_qa_stc) for different varieties of GE EPI sequences.
  - [Examples of phase encoding polarity, slice timing and diffusion gradients](https://github.com/nikadon/cc-dcm2bids-wrapper/tree/master/dicom-qa-examples/).
- - The dcm2niix (wiki)[https://www.nitrc.org/plugins/mwiki/index.php/dcm2nii:MainPage] includes examples of diffusion data, slice timing, and other variations.
\ No newline at end of file
+ - The dcm2niix [wiki](https://www.nitrc.org/plugins/mwiki/index.php/dcm2nii:MainPage) includes examples of diffusion data, slice timing, and other variations.
\ No newline at end of file


=====================================
PARREC/README.md
=====================================
@@ -5,7 +5,7 @@ dcm2niix attempts to convert Philips PAR/REC format images to NIfTI. While this
 
 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
+## Detecting, Reporting and Fixing the V4 Image offcentre 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.
 


=====================================
Philips/README.md
=====================================
@@ -16,9 +16,26 @@ In general it is recommended that you archive and convert DICOM images as they a
 
 Therefore, dcm2niix will ignore the IPP enclosed in 2005,140F unless no alternative exists.
 
+## Image Scaling
+
+dcm2niix losslessy copies the raw data from DICOM to NIfTI format. These values are typically stored as 16-bit integers in the range -32768..32767. Both the DICOM and NIfTI formats describe how scaling intercept and slope values can be used to convert these raw values into calibrated values. For example, with an intercept of 0 and slope of 0.01 the raw value of 50 would be converted to 0.5. 
+
+Unlike other vendors, Philips can store different scaling factors in their DICOM header. For most MRI modalities where the intensity brightness is relative, this has no impact. However, for modalities like ASL it can have an impact. The NIfTI format requires a single intensity intercept and slope is chosen. Therefore, dcm2niix will choose the "Real World" values if provided. If these are not available, dcm2niix will choose either the "precise" (default) or "display" (if the user choose "-p n") value. dcm2niix will also populate the folllowing tags in the BIDS header that allow the user to select between different intensity scaling formats: "PhilipsRescaleSlope", "PhilipsRescaleIntercept", "PhilipsScaleSlope", "UsePhilipsFloatNotDisplayScaling" (where "1" indicates NIfTI uses precise value, and "0" indicates display values)., "PhilipsRWVSlope" and "PhilipsRWVIntercept".
+
+The relevant DICOM tags are
+RS = rescale slope ([0028,1053](http://dicomlookup.com/lookup.asp?sw=Tnumber&q=(0028,1053)))
+RI = rescale intercept ([0028,1052](http://dicomlookup.com/lookup.asp?sw=Tnumber&q=(0028,1052)))
+SS = scale slope (2005,100E)
+RealWorldIntercept = (0040,9224) 
+Real World Slope = (0040,9225)
+The transformation formulas are:
+R = raw value, P = precise value, D = displayed value
+D = R * RS + RI
+P = D/(RS * SS)
+
 ## Derived parametric maps stored with raw diffusion data
 
-Some Philips diffusion DICOM images include derived image(s) along with the images. Other manufacturers save these derived images as a separate series number, and the DICOM standard seems ambiguous on whether it is allowable to mix raw and derived data in the same series (see PS 3.3-2008, C.7.6.1.1.2-3). In practice, many Philips diffusion images append [derived parametric maps](http://www.revisemri.com/blog/2008/diffusion-tensor-imaging/) with the original data. For example, ADC, Trace and Isotropic images can all be derived from the raw scans. As scientists, we want to discard these derived images, as they will disrupt data processing and we can generate better parametric maps after we have applied undistortion methods such as [Eddy and Topup](https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/eddy/UsersGuide). The current version of dcm2niix uses the Diffusion Directionality (0018,9075) tag to detect B=0 unweighted ("NONE"), B-weighted ("DIRECTIONAL"), and derived ("ISOTROPIC") images. Note that the Dimension Index Values (0020,9157) tag provides an alternative approach to discriminate these images. Here are sample tags from a Philips enhanced image that includes and derived map (3rd dimension is "1" while the other images set this to "2").
+Some Philips diffusion DICOM images include derived image(s) along with the images. Other manufacturers save these derived images as a separate series number, and the DICOM standard seems ambiguous on whether it is allowable to mix raw and derived data in the same series (see PS 3.3-2008, C.7.6.1.1.2-3). In practice, many Philips diffusion images append [derived parametric maps](http://www.revisemri.com/blog/2008/diffusion-tensor-imaging/) with the original data. With Philips, appending the derived isotropic image is optional  - it is only created for the 'clinical' DTI schemes for radiography analysis and is triggered if the first three vectors in the gradient table are the unit X,Y and Z vectors. For conventional DWI, the result is the conventional mean of the ADC  X,Y,Z for DTI it the conventional mean of the 3 principle Eigen vectors. As scientists, we want to discard these derived images, as they will disrupt data processing and we can generate better parametric maps after we have applied undistortion methods such as [Eddy and Topup](https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/eddy/UsersGuide). The current version of dcm2niix uses the Diffusion Directionality (0018,9075) tag to detect B=0 unweighted ("NONE"), B-weighted ("DIRECTIONAL"), and derived ("ISOTROPIC") images. Note that the Dimension Index Values (0020,9157) tag provides an alternative approach to discriminate these images. Here are sample tags from a Philips enhanced image that includes and derived map (3rd dimension is "1" while the other images set this to "2").
 
 ```
 (0018,9075) CS [DIRECTIONAL]
@@ -39,7 +56,67 @@ Some Philips diffusion DICOM images include derived image(s) along with the imag
 
 Proper Philips enhanced scans use tag 0018,9089 to report the 3 gradient directions. However, in the wild, other files from Philips (presumably using older versions of Philips software) use the tags 2005,10b0, 2005,10b1, 2005,10b2. In general, dcm2niix will use the values that most closely precede the Dimension Index Values (0020,9157).
 
-The current version of dcm2niix uses Dimension Index Values (0020,9157) to determine gradient number, which can also be found in (2005,1413). However, while 2005,1413 is always indexed from one, this is not necessarily the case for 0020,9157. For example, the ADNI DWI dataset for participant 018_S_4868 has values of 2005,1413 that range from 1..36 for the 36 directions, while 0020,9157 ranges from 2..37. The current version of dcm2niix compensates for this by re-indexing the values of 0020,9157 after all the volumes have been read.
+Public Tags
+```
+(0018,9089) FD 1\0\0
+(0018,9087) FD 1000
+```
+
+Private Tags
+```
+(2001,1003) FL 1000
+(2005,10b0) FL 1.0
+(2005,10b1) FL 1.0
+(2005,10b2) FL 0.0
+```
+
+For modern Philips DICOMs, the current version of dcm2niix uses Dimension Index Values (0020,9157) to determine gradient number, which can also be found in (2005,1413). However, while 2005,1413 is always indexed from one, this is not necessarily the case for 0020,9157. For example, the ADNI DWI dataset for participant 018_S_4868 has values of 2005,1413 that range from 1..36 for the 36 directions, while 0020,9157 ranges from 2..37. The current version of dcm2niix compensates for this by re-indexing the values of 0020,9157 after all the volumes have been read.
+
+For acquiring DWI data, you can adjust your setup with from the Philips console. Specifically, in Contrast one selects Diffusion mode to DTI and adjusts the directional resolution. Options for directional resolution are `Low` which acquires 6 directions (P,M,S, plus 3 oblique), `Medium` (15 directions), `High` (32 directions) and `Opt x` where x is a number from 6 - 128 directions. DTI Elite users can also select `From File`. This will import the text file named E:\Export\dti_vectors_input.txt. This text file has a simple format. The first line is optional and is the name of the scheme - this line should not begin with a number. If the file contains a b=0 vector, it must be the first line of the file. The following lines specify the direction and bvalues. If you want to acquire more than one b=0 volume, each must specify a unique direction. One can only process these custom files with Philips FiberTrak if the same directions have been obtained for all b-values. Here is an example file that obeys these rules:
+
+```
+MyCustomDirections
+0.000	0.000	1.000	0
+0.049	-0.919	-0.391	1000
+0.726	0.301	-0.618	1000
+-0.683	0.255	-0.684	1000
+0.845	-0.502	-0.186	1000
+-0.73	-0.619	-0.288	1000
+-0.051	0.039	0.998	1000
+-0.018	0.871	-0.491	1000
+-0.444	0.494	0.747	1000
+-0.989	-0.086	-0.116	1000
+1.000	0.000	0.000	0
+
+```
+
+## Missing Information.
+
+Philips DICOMs do not contain all the information desired by many neuroscientists. Due to this, the [BIDS](http://bids.neuroimaging.io/) files created by dcm2niix are impoverished relative to data from other vendors. This reflects a limitation in the Philips DICOMs, not dcm2niix.
+
+[Slice timing correction](https://www.mccauslandcenter.sc.edu/crnl/tools/stc) can account for some variability in fMRI datasets. Unfortunately, Philips DICOM data [does not encode slice timing information](https://neurostars.org/t/heudiconv-no-extraction-of-slice-timing-data-based-on-philips-dicoms/2201/4). Therefore, dcm2niix is unable to populate the "SliceTiming" BIDS field. However, one can typically infer slice timing by recording the [mode and number of packages](https://en.wikibooks.org/w/index.php?title=SPM/Slice_Timing&stable=0#Philips_scanners) reported for the sequence on the scanner console or the [sequence PDF](http://adni.loni.usc.edu/wp-content/uploads/2017/09/ADNI-3-Basic-Philips-R5.pdf). For precise timing, it is also worth knowing if equidistant "temporal slice spacing" is set and whether "prospect. motion corr." is on or off (if on, a short delay occurs between volumes).
+
+Likewise, the BIDS tag "PhaseEncodingDirection" allows tools like [eddy](https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/eddy) and [TOPUP](https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/topup) to undistort images. While the Philips DICOM header distinguishes the phase encoding axis (e.g. anterior-posterior vs left-right) it does not encode the polarity (A->P vs P->A).
+
+Another value desirable for TOPUP is the "TotalReadoutTime". Again, one can not confidently calculate this from Philips DICOMs (though on can [appoximate it if you make a few assumptions](https://github.com/nipreps/sdcflows/issues/5)). If you do decide to calculate this using values from the MRI console, be aware that the [FSL definition](https://github.com/rordenlab/dcm2niix/issues/130) is not intuitive for scans with interpolation, partial Fourier, parallel imaging, etc. However, it should be pointed out that the "TotalReadoutTime" only influences TOPUP's calibrated validation images that are typically ignored. The data used in subsequent steps will not be influenced by this value.
+
+## Partial Volumes
+
+NIfTI expects all 3D volumes of a  4D series to have the same number of series (e.g. a time series of 3D fMRI volumes, or a diffusion set with 3D volumes with different gradients applied). If a fMRI sequence is aborted part way through, it is possible that a Philips scanner will only save part of the final volume. An example would be where the total slices (9970) does not equal Dynamics (290) x slices (35) = 10150. Current versions of dcm2niix expect complete volumes. You can repair your data using the console or a Python script, as discussed in [issue 357](https://github.com/rordenlab/dcm2niix/issues/357). To resolve this situation by hand you could also [rename](RENAMING.md) your DICOM files with a call like `./dcm2niix -r y -f %t/%s_%p_%4y_%2r.dcm ~/out 0020,0100`. In this example, the [`%4y`](FILENAMING.md) parameter adds the volume (Temporal Position, 0020,0100) to the filename, allowing you to identify volumes with missing slices.
+
+## Non-Image DICOMs
+
+NIfTI is an image format, while DICOM is a multi-purpose format that can store videos (MPEG) or other data. Specifically, some Philips systems save Exam Cards and other non-image data as DICOM files. In these case, dcm2niix should skip these files, as they can not be represented in NIfTI. You can discriminate these files by reading the [MediaStorageSOPClassUID (0002,0002)](https://github.com/rordenlab/dcm2niix/issues/328).
+
+- MR Image Storage = 1.2.840.10008.5.1.4.1.1.4
+- Enhanced MR Image Storage = 1.2.840.10008.5.1.4.1.1.4.1
+- MR Spectroscopy Storage = 1.2.840.10008.5.1.4.1.1.4.2
+- Secondary Capture Image Storage = 1.2.840.10008.5.1.4.1.1.7
+- Grayscale Softcopy Presentation State = 1.2.840.10008.5.1.4.1.1.11.1
+- Raw Data Storage = 1.2.840.10008.5.1.4.1.1.66
+- (Old) Private MR Spectrum Storage = 1.3.46.670589.11.0.0.12.1
+- (Old) Private MR Series Data Storage = 1.3.46.670589.11.0.0.12.2
+- (Old) Private MR Examcard Storage = 1.3.46.670589.11.0.0.12.4 
 
 ## General variations
 


=====================================
README.md
=====================================
@@ -13,7 +13,6 @@ 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.
@@ -38,11 +37,16 @@ Command line usage is described in the [NITRC wiki](https://www.nitrc.org/plugin
 
 There are a couple ways to install dcm2niix
  - [Github Releases](https://github.com/rordenlab/dcm2niix/releases) provides the latest compiled executables. This is an excellent option for MacOS and Windows users. However, the provided Linux executable requires a recent version of Linux, so the provided Unix executable is not suitable for all distributions.
- - [MRIcroGL](https://github.com/neurolabusc/MRIcroGL/releases) includes dcm2niix that can be run from the command line or from the graphical user interface (select the Import menu item). The Linux version of dcm2niix is compiled on a holy build box, so it should run on any Linux distribution.
+ - Run the following command to get the latest version for Linux, Macintosh or Windows: 
+   * `curl -fLO https://github.com/rordenlab/dcm2niix/releases/latest/download/dcm2niix_lnx.zip`
+   * `curl -fLO https://github.com/rordenlab/dcm2niix/releases/latest/download/dcm2niix_mac.zip`
+   * `curl -fLO https://github.com/rordenlab/dcm2niix/releases/latest/download/dcm2niix_win.zip`
+ - [MRIcroGL (NITRC)](https://www.nitrc.org/projects/mricrogl) or [MRIcroGL (GitHub)](https://github.com/rordenlab/MRIcroGL12/releases) includes dcm2niix that can be run from the command line or from the graphical user interface (select the Import menu item). The Linux version of dcm2niix is compiled on a holy build box, so it should run on any Linux distribution.
  - If you have a MacOS computer with Homebrew you can run `brew install dcm2niix`.
  - If you have Conda, [`conda install -c conda-forge dcm2niix`](https://anaconda.org/conda-forge/dcm2niix) on Linux, MacOS or Windows.
  - On Debian Linux computers you can run `sudo apt-get install dcm2niix`..
 
+
 ## Build from source
 
 It is often easier to download and install a precompiled version. However, you can also build from source.
@@ -72,7 +76,11 @@ In rare case if cmake fails with the message like `"Generator: execution of make
 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
+git clone https://github.com/rordenlab/dcm2niix.git
+cd dcm2niix
+mkdir build && cd build
 cmake -DZLIB_IMPLEMENTATION=Cloudflare -DUSE_JPEGLS=ON -DUSE_OPENJPEG=ON ..
+make
 ```
 
 **optional batch processing version:**
@@ -83,36 +91,72 @@ The batch processing binary `dcm2niibatch` is optional. To build `dcm2niibatch`
 
 If you have any problems with the cmake build script described above or want to customize the software see the [COMPILE.md file for details on manual compilation](./COMPILE.md).
 
+## Referencing
+
+ - Li X, Morgan PS, Ashburner J, Smith J, Rorden C (2016) The first step for neuroimaging data analysis: DICOM to NIfTI conversion. J Neurosci Methods. 264:47-56. doi: 10.1016/j.jneumeth.2016.03.001. [PMID: 26945974](https://www.ncbi.nlm.nih.gov/pubmed/26945974) 
+
 ## Alternatives
 
- - [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.
+ - [dcm2nii](https://people.cas.sc.edu/rorden/mricron/dcm2nii.html) 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).
  - [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.
+ - [dicomtonifti](https://github.com/dgobbi/vtk-dicom/wiki/dicomtonifti) leverages [VTK](https://www.vtk.org/).
+ - [dinifti](http://as.nyu.edu/cbi/resources/Software/DINIfTI.html) is focused on conversion of Siemens data.
+ - [DWIConvert](https://github.com/BRAINSia/BRAINSTools/tree/master/DWIConvert) converts DICOM images to NRRD and NIfTI formats.
  - [mcverter](http://lcni.uoregon.edu/%7Ejolinda/MRIConvert/) has great support for various vendors.
  - [mri_convert](https://surfer.nmr.mgh.harvard.edu/pub/docs/html/mri_convert.help.xml.html) is part of the popular FreeSurfer package. In my limited experience this tool works well for GE and Siemens data, but fails with Philips 4D datasets.
+ - [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.
+ - [Plastimatch](https://www.plastimatch.org/) is a Swiss Army knife - it computes registration, image processing, statistics and it has a basic image format converter that can convert some DICOM images to NIfTI or NRRD.
  - [SPM12](http://www.fil.ion.ucl.ac.uk/spm/software/spm12/) is one of the most popular tools in the field. It includes DICOM to NIfTI conversion. Being based on Matlab it is easy to script.
+ - dcm2niix is largely used for converting MRI and CT DICOMs. While it should in theory support ultra sound (US) images stored as DICOMs, vendors tend to use private tags. The [SlicerHeart extension](https://github.com/SlicerHeart/SlicerHeart) is specifically designed to help 3D Slicer support this modality.
 
 ## Links
 
+The following tools exploit dcm2niix
+
+  - [abcd-dicom2bids](https://github.com/DCAN-Labs/abcd-dicom2bids) selectively downloads high quality ABCD datasets. 
+  - [autobids](https://github.com/khanlab/autobids) automates dcm2bids which uses dcm2niix.
+  - [BiDirect_BIDS_Converter](https://github.com/wulms/BiDirect_BIDS_Converter) for conversion from DICOM to the BIDS standard.
+  - [BIDS Toolbox](https://github.com/cardiff-brain-research-imaging-centre/bids-toolbox) is a web service for the creation and manipulation of BIDS datasets, using dcm2niix for importing DICOM data.
+  - [brainnetome DiffusionKit](http://diffusion.brainnetome.org/en/latest/) uses dcm2niix to convert images.
+  - [Brain imAgiNg Analysis iN Arcana (Banana)](https://pypi.org/project/banana/) is a collection of brain imaging analysis workflows, it uses dcm2niix for format conversions.
+  - [BOLD5000_autoencoder](https://github.com/nmningmei/BOLD5000_autoencoder) uses dcm2niix to pipe imaging data into an unsupervised machine learning algorithm.
+  - [clinica](https://github.com/aramis-lab/clinica) is a software platform for clinical neuroimaging studies that uses dcm2niix to convert DICOM images.
+  - [dcm2niix can help convert data from the Adolescent Brain Cognitive Development (ABCD) DICOM to BIDS](https://github.com/ABCD-STUDY/abcd-dicom2bids)
   - [bidsify](https://github.com/spinoza-rec/bidsify) is a Python project that uses dcm2niix to convert DICOM and Philips PAR/REC images to the BIDS standard.
   - [bidskit](https://github.com/jmtyszka/bidskit) uses dcm2niix to create [BIDS](http://bids.neuroimaging.io/) datasets.
+  - [BioImage Suite Web Project](https://github.com/bioimagesuiteweb/bisweb) is a JavaScript project that uses dcm2niix for its DICOM conversion module.
   - [boutiques-dcm2niix](https://github.com/lalet/boutiques-dcm2niix) is a dockerfile for installing and validating dcm2niix.
   - [DAC2BIDS](https://github.com/dangom/dac2bids) uses dcm2niibatch to create [BIDS](http://bids.neuroimaging.io/) datasets.
   - [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.
+  - [DICOM2BIDS](https://github.com/klsea/DICOM2BIDS) is a Python 2 script for creating BIDS files.
+  - [dcmwrangle](https://github.com/jbteves/dcmwrangle) a Python interactive and static tool for organizing dicoms.
   - [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).
+  - [fmrif tools](https://github.com/nih-fmrif/fmrif_tools) uses dcm2niix for its [oxy2bids](https://fmrif-tools.readthedocs.io/en/latest/#) tool..
+  - [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.
+  - [Functional Real-Time Interactive Endogenous Neuromodulation and Decoding (FRIEND) Engine](https://github.com/InstitutoDOr/FriendENGINE) uses dcm2niix.
   - [heudiconv](https://github.com/nipy/heudiconv) can use dcm2niix to create [BIDS](http://bids.neuroimaging.io/) datasets.
+  - [kipettools](https://github.com/mathesong/kipettools) uses dcm2niix to load PET data.
+  - [LEAD-DBS](http://www.lead-dbs.org/) uses dcm2niix for [DICOM import](https://github.com/leaddbs/leaddbs/blob/master/ea_dicom_import.m).
   - [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/).
+  - [neurodocker](https://github.com/kaczmarj/neurodocker) includes dcm2niix as a lean, minimal install Dockerfile.
   - [neuro_docker](https://github.com/Neurita/neuro_docker) includes dcm2niix as part of a single, static Dockerfile.
   - [NeuroDebian](http://neuro.debian.net/pkgs/dcm2niix.html) provides up-to-date version of dcm2niix for Debian-based systems.
   - [neurodocker](https://github.com/kaczmarj/neurodocker) generates [custom](https://github.com/rordenlab/dcm2niix/issues/138) Dockerfiles given specific versions of neuroimaging software.
+  - [NeuroElf](http://neuroelf.net) can use dcm2niix to convert DICOM images.
+  - [Neuroinformatics Database (NiDB)](https://github.com/gbook/nidb) is designed to store, retrieve, analyze, and share neuroimaging data. It uses dcm2niix for image QA and handling some formats. 
+  - [NiftyPET](https://niftypet.readthedocs.io/en/latest/install.html) provides PET image reconstruction and analysis, and uses dcm2niix to handle DICOM images. 
   - [nipype](https://github.com/nipy/nipype) can use dcm2niix to convert images.
+  - [PNL-nipype](https://github.com/pnlbwh/Dummy-PNL-nipype) is a Python script that can convert dcm2niix created NIfTI files to the popular NRRD format (including DWI gradient tables). Note, recent versions of dcm2niix can directly convert DICOM images to NRRD.
   - [pydcm2niix is a Python module for working with dcm2niix](https://github.com/jstutters/pydcm2niix).
+  - [pyBIDSconv provides a graphical format for converting DICOM images to the BIDS format](https://github.com/DrMichaelLindner/pyBIDSconv). It includes clever default heuristics for identifying Siemens scans.
+  - [qsm](https://github.com/CAIsr/qsm) Quantitative Susceptibility Mapping software.
+  - [reproin](https://github.com/ReproNim/reproin) is a setup for automatic generation of shareable, version-controlled BIDS datasets from MR scanners.
   - [sci-tran dcm2niix](https://github.com/scitran-apps/dcm2niix) Flywheel Gear (docker).
+  - The [SlicerDcm2nii extension](https://github.com/Slicer/ExtensionsIndex/blob/master/SlicerDcm2nii.s4ext) is one method to import DICOM data into Slicer.
+  - [TORTOISE](https://tortoise.nibib.nih.gov) is used for processing diffusion MRI data, and uses dcm2niix to import DICOM images.
+  - [TractoR (Tracto­graphy with R) uses dcm2niix for image conversion](http://www.tractor-mri.org.uk/TractoR-and-DICOM).


=====================================
RENAMING.md
=====================================
@@ -19,11 +19,12 @@ Therefore, the 9th DICOM image from series 3 acquired on 4 February 2012 would b
 It is very important that your file naming disambiguates all your images. For example, consider a naming scheme that only used the image number (`-f %r.dcm`) and was applied to multiple series (each which had an image number 1,2,...). When there are naming conflicts, dcm2niix will terminate with an error message, e.g. `Error: File naming conflict. Existing file /home/c/dcm/1.dcm`.
 
 A special situation is the fieldmaps generated by Siemens scanners. Users often acquire gradient-echo fieldmaps so they can undistort EPI images. These fieldmaps acquire two (or more) echoes. Unfortunately, Siemens will give each of these echoes an identical series and image number. DICOM tools that are unaware of this often [overwrite](https://neurostars.org/t/field-mapping-siemens-scanners-dcm2niix-output-2-bids/2075/7) some of the images from each echo. To combat this situation, dcm2niix will add the post-fix `_e2` to the second echo. Therefore, if you converted a series with `-f %s_%4r` your fieldmap might generate files named `5_0001.dcm` and `5_0001_e2.dcm`. Note you could also explicitly number each echo (`-f %s_%4r_%e`), though in this case all your series (not just the fieldmaps) will have the echo appended.
+
 ## Alternatives
 
 An advantage of using dcm2niix is simplicity: it is a free, single file executable that you can [download](https://github.com/rordenlab/dcm2niix/releases) that is available for MacOS, Linux and Windows that you can run from the command line. On the other hand, this simplicity means it is fairly inflexible. You may want to consider a DICOM renamer built in your favorite scripting language.
 
- - [dicom-rename is a Python script](https://github.com/joshy/dicom-rename).
  - [dicomsort is a Python script](https://github.com/pieper/dicomsort).
  - [rename_dir is a Matlab script that requires the proprietary Image Processing Toolbox](https://gist.github.com/htygithub/ad3597577e1de004e9f5)..
- - [dicm2nii includes the Matlab script rename_dicm that does not require any additional toolboxes](https://github.com/xiangruili/dicm2nii).
\ No newline at end of file
+ - [dicm2nii includes the Matlab script rename_dicm that does not require any additional toolboxes](https://github.com/xiangruili/dicm2nii).
+ - [DICOMSort provides a nice graphical interface]https://dicomsort.com/downloads.html), providing a nice alternative for scripting and command line solutions.


=====================================
Siemens/README.md
=====================================
@@ -2,17 +2,42 @@
 
 dcm2niix attempts to convert Siemens DICOM format images to NIfTI. This page describes some vendor-specific details.
 
-## Vida XA10A
+## Vida XA10 and XA11
 
-The Siemens Vida introduced the new XA10A DICOM format. Users are strongly encouraged to export data using the "Enhanced" format and to not use any of the "Anonymize" features on the console. The consequences of these options is discussed in detail in [issue 236](https://github.com/rordenlab/dcm2niix/issues/236). In brief, the Vida can export to enhanced, mosaic or classic 2D. Note that the mosaics are considered secondary capture images intended for quality assurance only. The mosaic scans lack several "Type 1" DICOM properties, necessarily limiting conversion. The non-mosaic 2D enhanced DICOMs are compact and efficient, but appear to have limited details relative to the enhanced output. Finally, each of the formats (enhanced, mosaic, classic) can be exported as anonymized. The Siemens console anonymization of current XA10A (Fall 2018) strips many useful tags. Siemens suggests "the use an offline/in-house anonymization software instead." Another limitation of the current XA10A format is that it retains no versioning details for software and hardware stepping, despite the fact that the data format is rapidly evolving. If you use a Vida, you are strongly encouraged to log every hardware or software upgrade to allow future analyses to identify and regress out any effects of these modifications.  Since the XA10A format does not have a CSA header, dcm2niix will attempt to use the new private DICOM tags to populate the BIDS file. These tags are described in [issue 240](https://github.com/rordenlab/dcm2niix/issues/240).
+The Siemens Vida introduced the new XA10 DICOM format. Users are strongly encouraged to export data using the "Enhanced" format and to not use any of the "Anonymize" features on the console. The consequences of these options is discussed in detail in [issue 236](https://github.com/rordenlab/dcm2niix/issues/236). In brief, the Vida can export to enhanced, mosaic or classic 2D. Note that the mosaics are considered secondary capture images intended for quality assurance only. The mosaic scans lack several "Type 1" DICOM properties, necessarily limiting conversion. The non-mosaic 2D enhanced DICOMs are compact and efficient, but appear to have limited details relative to the enhanced output. Finally, each of the formats (enhanced, mosaic, classic) can be exported as anonymized. The Siemens console anonymization of current XA10A (Fall 2018) strips many useful tags. Siemens suggests "the use an offline/in-house anonymization software instead." Another limitation of the current XA10A format is that it retains no versioning details for software and hardware stepping, despite the fact that the data format is rapidly evolving. If you use a Vida, you are strongly encouraged to log every hardware or software upgrade to allow future analyses to identify and regress out any effects of these modifications.  Since the XA10A format does not have a CSA header, dcm2niix will attempt to use the new private DICOM tags to populate the BIDS file. These tags are described in [issue 240](https://github.com/rordenlab/dcm2niix/issues/240).
+
+When creating enhanced DICOMs diffusion information is provided in public tags. Based on a limited sample, it seems that classic DICOMs do not store diffusion data for XA10, and use private tags for [XA11](https://www.nitrc.org/forum/forum.php?thread_id=10013&forum_id=4703).
+
+Public Tags
+```
+(0018,9089) FD -0.20\-0.51\-0.83 #DiffusionGradientOrientation
+(0018,9087) FD 1000 #DiffusionBValue
+
+```
+
+Private Tags
+```
+(0019,100c) IS 1000 #SiemensDiffusionBValue
+(0019,100e) FD -0.20\-0.51\-0.83 #SiemensDiffusionGradientOrientation
+
+```
+
+In theory, the public DICOM tag 'Frame Acquisition Date Time' (0018,9074) and the private tag 'Time After Start' (0021,1104) should each allow one to infer slice timing. The tag 0018,9074 uses the DT (date time) format, for example "20190621095520.330000" providing the YYYYYMMDDHHMMSS. Unfortunately, the Siemens de-identification routines will scramble these values, as time of data could be considered an identifiable attribute. The tag 0021,1104 is saved in DS (decimal string) format, for example "4.635" reporting the number of seconds since acquisition started. Be aware that some [Siemens Vida multi-band sequences](https://github.com/rordenlab/dcm2niix/issues/303) appear to fill these tags with the single-band times rather than the actual acquisition times. Therefore, neither of these two methods is perfectly reliable in determining slice timing.
 
 ## CSA Header
 
-Many crucial Siemens parameters are stored in the [proprietary CSA header](http://nipy.org/nibabel/dicom/siemens_csa.html). This has a binary section that allows quick reading for many useful parameters. It also includes an ASCII text portion that includes a lot of information but is slow to parse and poorly curated.
+Many crucial Siemens parameters are stored in the [proprietary CSA header](http://nipy.org/nibabel/dicom/siemens_csa.html). This has a binary section that allows quick reading for many useful parameters. It also includes an ASCII text portion that includes a lot of information but is slow to parse and poorly curated. Be aware that Siemens Vida scanners do not generate a CSA header.
 
 ## Slice Timing
 
-The CSA header provides [slice timing](https://www.mccauslandcenter.sc.edu/crnl/tools/stc), and therefore dcm2niix should provide accurate slice timing information for non-XA10 datasets. For archival studies, be aware that some sequences [incorrectly reported slice timing](https://github.com/rordenlab/dcm2niix/issues/126).
+
+See the [dcm_qa_stc](https://github.com/neurolabusc/dcm_qa_stc) repository with sample data that exhibits different methods used by Siemens to record slice timing.
+
+Older software (e.g. A25 through B13) sometimes populates the tag sSliceArray.ucMode in the [CSA Series Header (0029, 1020)](https://nipy.org/nibabel/dicom/siemens_csa.html) where the values [1, 2, and 4](https://github.com/xiangruili/dicm2nii/issues/18) correspond to Ascending, Descending and Interleaved acquisitions.
+
+For software versions B15 through E11 where all slices of a volume are stored as a single mosaic file, the proprietary [CSA Image Header (0029,1010)](https://nipy.org/nibabel/dicom/siemens_csa.html) contains the array MosaicRefAcqTimes that provides [slice timing](https://www.mccauslandcenter.sc.edu/crnl/tools/stc). For volumes where each 2D slice is saved as a separate DICOM file, one can infer slice order from the DICOM tag Acquisition Time (0008,0032).
+
+ The prior section describes Vida slice timing issues seen with the XA software series. In brief, dcm2niix will use Frame Acquisition Time (0018,9074) to determine slice times. Some Siemens DICOMs store slice timings in the private tag [0019,1029](https://github.com/rordenlab/dcm2niix/issues/296). In theory, this could be used when the CSA header is missing. For archival studies, be aware that some sequences [incorrectly reported slice timing](https://github.com/rordenlab/dcm2niix/issues/126). The [SPM slice timing wiki](https://en.wikibooks.org/w/index.php?title=SPM/Slice_Timing&stable=0#Siemens_scanners) provides further information on Siemens slice timing.
 
 ## Total Readout Time
 
@@ -20,8 +45,60 @@ One often wants to determine [echo spacing, bandwidth, ](https://support.brainvo
 
 ## Diffusion Tensor Notes
 
-Diffusion specific parameters are described on the [NA-MIC](https://www.na-mic.org/wiki/NAMIC_Wiki:DTI:DICOM_for_DWI_and_DTI#Private_vendor:_Siemens) website. Gradient vectors are reported with respect to the scanner bore, and dcm2niix will attempt to re-orient these to [FSL format](http://justinblaber.org/brief-introduction-to-dwmri/) [bvec files](https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/FDT/FAQ#What_conventions_do_the_bvecs_use.3F).
+Diffusion specific parameters are described on the [NA-MIC](https://www.na-mic.org/wiki/NAMIC_Wiki:DTI:DICOM_for_DWI_and_DTI#Private_vendor:_Siemens) website. Gradient vectors are reported with respect to the scanner bore, and dcm2niix will attempt to re-orient these to [FSL format](http://justinblaber.org/brief-introduction-to-dwmri/) [bvec files](https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/FDT/FAQ#What_conventions_do_the_bvecs_use.3F). For the Vida, see the Vida section for specific diffusion details.
+
+## Arterial Spin Labeling
+
+Tools like [ExploreASL](https://sites.google.com/view/exploreasl) and [FSL BASIL](https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/BASIL) can help process arterial spin labeling data. These tools require sequence details. These details differ between different sequences. If you create a BIDS JSON file with dcm2niix, the following tags will be created, using the same names used in the Siemens sequence PDFs. Note different sequences provide different values.
+
+ep2d_pcasl, ep2d_pcasl_UI_PHC //pCASL 2D [Danny J.J. Wang](http://www.loft-lab.org)
+ - LabelOffset
+ - PostLabelDelay
+ - NumRFBlocks
+ - RFGap
+ - MeanGzx10
+ - PhiAdjust
+
+tgse_pcasl //pCASL 3D [Danny J.J. Wang](http://www.loft-lab.org)
+ - RFGap
+ - MeanGzx10
+ - T1
+
+ep2d_pasl //PASL 2D Siemens Product
+ - InversionTime
+ - SaturationStopTime
+
+tgse_pasl //PASL 3D [Siemens Product](http://adni.loni.usc.edu/wp-content/uploads/2010/05/ADNI3_Basic_Siemens_Skyra_E11.pdf)
+ - BolusDuration
+ - InversionTime
+
+ep2d_fairest //PASL 2D http://www.pubmed.com/11746944 http://www.pubmed.com/21606572
+ - PostInversionDelay
+ - PostLabelDelay
 
+to_ep2d_VEPCASL //pCASL 2D specific tags - Oxford (Thomas OKell)
+ - InversionTime
+ - BolusDuration
+ - TagRFFlipAngle
+ - TagRFDuration
+ - TagRFSeparation
+ - MeanTagGradient
+ - TagGradientAmplitude
+ - TagDuration
+ - MaximumT1Opt
+ - InitialPostLabelDelay [Array]
+  
+jw_tgse_VEPCASL //pCASL 3D Oxford
+ - TagRFFlipAngle
+ - TagRFDuration
+ - TagRFSeparation
+ - MaximumT1Opt
+ - Tag0
+ - Tag1
+ - Tag2
+ - Tag3
+ - InitialPostLabelDelay [Array]
+ 
 ## Sample Datasets
 
  - [Slice timing dataset](httphttps://www.nitrc.org/plugins/mwiki/index.php/dcm2nii:MainPage#Slice_timing_corrections://www.nitrc.org/plugins/mwiki/index.php/dcm2nii:MainPage).


=====================================
SuperBuild/SuperBuild.cmake
=====================================
@@ -30,7 +30,7 @@ if(USE_STATIC_RUNTIME)
             unset(STATIC_LIBCXX CACHE)
             # Only on some Centos/Redhat systems
             message(FATAL_ERROR
-                "\"USE_STATIC_RUNTIME\" set to ON but \"libstdcxx.a\" not found! \
+                "\"USE_STATIC_RUNTIME\" set to ON but \"libstdc++.a\" not found! Set it to OFF or \
                  \"yum install libstdc++-static\" to resolve the error.")
         endif()
     endif()


=====================================
Toshiba/README.md
=====================================
@@ -0,0 +1,20 @@
+## About
+
+dcm2niix attempts to convert Toshiba DICOM format images to NIfTI. This page notes vendor specific conversion details.
+
+## Diffusion Weighted Imaging Notes
+
+In contrast to several other vendors, Toshiba uses public tags to report diffusion properties. Specifically, [DiffusionBValue (0018,9087)](http://dicomlookup.com/lookup.asp?sw=Tnumber&q=(0018,9087)) and [DiffusionGradientOrientation (0018,9089)](http://dicomlookup.com/lookup.asp?sw=Tnumber&q=(0018,9089)). Be aware that these tags are only populated for images where a diffusion gradient is applied. Consider a typical diffusion series where some volumes are acquired with B=0 while others have B=1000. In this case, only the volumes with B>0 will report a DiffusionBValue.
+
+## Unknown Properties
+
+The (BIDS format)[https://bids.neuroimaging.io] can record several sequence properties that are useful for processing MRI data. The DICOM headers created by Toshiba scanners are very clean and minimalistic, and do not report several of these advanced properties. Therefore, dcm2niix is unable to populate these properties of the JSON file. This reflects a limitation of the DICOM images, not of dcm2niix.
+
+ - SliceTiming is not recorded. This can be useful for slice time correction.
+ - Phase encoding polarity is not record. This is useful for undistortion with [TOPUP](https://fsl.fmrib.ox.ac.uk/fsl/fslwiki/topup).
+
+
+## Sample Datasets
+
+ - [Toshiba Aquilion](https://www.aliza-dicom-viewer.com/download/datasets).
+ - [Toshiba 3T Galan Diffusion Dataset](https://github.com/neurolabusc/dcm_qa_toshiba).


=====================================
Troubleshooting/README.md
=====================================
@@ -0,0 +1,15 @@
+## About
+
+The DICOM standard has become the dominant imaging format in medicine. However, it is necessarily complex. The relative simplicity of NIfTI makes it popular with many scientific tools.Further, to protect participant privacy scientists often wish to anonymize the datasets, removing [protected health information](https://www.hipaajournal.com/considered-phi-hipaa/). It is much easier to ensure a simple format is completely anonymized relative to a complex format.The role of dcm2niix is to convert these images into the simpler NIfTI standard. A challenge is that the DICOM standard is implemented differently by different vendors, and is evolving. Indeed, the complexity of the standard means that many DICOM images do not perfectly conform to the standard. To thoroughly read these images, one needs to develop an understanding of how each vender has interpreted the DICOM standard. Due to these factors, dcm2niix may not always create the results you expect.
+
+This page explains situations where dcm2niix may fail or generate impoverished results. If this page is unable to resolve your problem, you may want to consider creating a [new issue report on the Github web page](https://github.com/rordenlab/dcm2niix/issues).
+
+## Common DICOM Problems
+
+The DICOM standard is very complex. In addition, dcm2niix attempts to extract a rich amount of meta data. For example, knowing about diffusion direction, phase encoding polarity and slice timing are all important details for scientists. Yet many of these details are not described by public DICOM tags. Therefore, dcm2niix must determine the vendor that generated the images. This allows dcm2niix to decipher the private tags used by the vendors. While the community has reversed-engineered data from the major vendors, data from unfamiliar vendors can cause issues. Further, tools that attempt to anonymize or otherwise modify DICOM data often inadvertently remove vital meta data or corrupt the DICOM images.
+
+If you have a problem with a DICOM scan, your first step should be to inspect the DICOM header understand the providence of the image. The DICOM images created by the scanner are often saved in slightly altered forms by other tools that attempt to anonymize or process the images. It is typically these tools that effectively corrupt the images. In particular, the recent Enhanced DICOM images generated by Siemens Vida scanners and Philips scanners use a recent variation of DICOM. Many older DICOM tools are not familiar with this dialect, and corrupt every enhanced DICOM image they receive. Therefore, if you have a problem, it is worthwhile to first get an image direct from your scanner. If this raw data converts correctly, it suggests a subsequent tool is responsible for tampering with the data.
+
+In general, you should be very cautious to use any tool to manipulate your raw DICOM data. The complexity of DICOM makes them very fragile. Attempts to change the transfer syntax (e.g. internally compress), anonymize or change the value representation from Explicit to Implicit can all corrupt some forms of DICOM data. Archival quality data should be tampered with as little as possible.
+
+If you are unsure of the providence of your image, you can inspect the DICOM header. MacOS users can use the free [Horos](https://horosproject.org/) application to inspect the meta data using a graphical interface. The command line tools [dcmdump](https://support.dcmtk.org/docs/dcmdump.html) and [gdcmdump](http://gdcm.sourceforge.net/html/gdcmdump.html). For example, typing 'dcmconv myDICOM.dcm > log.txt' will generate  text file of your complete DICOM header. The first public tag to check is the Manufacturer (0008,0070): the major vendors are Siemens, Philips and GE. Data from other vendors is likely to have more issues. The next tag to check is the Implementation Version Name and the SourceApplicationEntityTitle (0002,0016) - these is the tool that created your image. For images direct off the scanner this will usually be named after the scanner model (e.g. a Siemens E11C Prisma might report "MR_VE11C", a Philips Examination Workstation might report "EWS R2.5'). In general, the most popular free tools have been used by many users, and generate good DICOM images. For example, "dcm4che","GDCM" and "OFFIS DCMTK" all refer to popular and robust tools. On the other hand, "MATLAB IPT 9.4" suggests that the file was manipulated by a Matlab script, and since it is so easy to generate Matlab scripts it is possible that the user did not consider all the possible unintended consequences of manipulating the image.


=====================================
appveyor.yml
=====================================
@@ -2,10 +2,6 @@ version: build-{build}
 
 image: Visual Studio 2015
 
-branches:
-  only:
-  - master
-
 configuration: Release
 
 platform: x64
@@ -45,7 +41,7 @@ after_build:
 - ps: >-
     cd c:\projects\dcm2niix
 
-    7z a dcm2niix_$($env:DATE)_win.zip c:\projects\dcm2niix\build\bin\* >$null
+    7z a dcm2niix_win.zip c:\projects\dcm2niix\build\bin\* >$null
 
 artifacts:
   - path: dcm2niix*.zip


=====================================
console/CMakeLists.txt
=====================================
@@ -24,6 +24,9 @@ if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
     set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-dead_strip")
 elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
     # using GCC
+    if(NOT (${CMAKE_CXX_COMPILER_VERSION} VERSION_LESS 7.1.0))
+        add_definitions(-Wno-format-overflow)    # available since GCC 7.1.0
+    endif()
     if(NOT (${CMAKE_CXX_COMPILER_VERSION} VERSION_LESS 4.5.0))
         add_definitions(-Wno-unused-result)    # available since GCC 4.5.0
     endif()
@@ -187,4 +190,15 @@ if(BATCH_VERSION)
     list(APPEND PROGRAMS dcm2niibatch)
 endif()
 
+
+if(APPLE)
+    message("--   Adding Apple plist")
+    set_target_properties(dcm2niix PROPERTIES LINK_FLAGS "-Wl,-sectcreate,__TEXT,__info_plist,${CMAKE_SOURCE_DIR}/Info.plist")
+    #Apple notarization requires a Info.plist
+    # For .app bundles, the Info.plist is a separate file, for executables it is appended as a section
+    #you can check that the Info.plist section has been inserted with either of these commands
+    # otool -l ./dcm2niix | grep info_plist -B1 -A10
+    # launchctl plist ./dcm2niix
+endif()
+
 install(TARGETS ${PROGRAMS} DESTINATION bin)


=====================================
console/Info.plist
=====================================
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>CFBundleExecutable</key>
+	<string>dcm2niix</string>
+	<key>CFBundleIdentifier</key>
+	<string>com.mricro.dcm2niix</string>
+	<key>CFBundleInfoDictionaryVersion</key>
+	<string>6.0</string>
+	<key>CFBundleName</key>
+	<string>dcm2niix</string>
+	<key>CFBundleShortVersionString</key>
+	<string>1.0</string>
+	<key>CFBundleVersion</key>
+	<string>1</string>
+	<key>CFBundleSupportedPlatforms</key>
+	<array>
+		<string>MacOSX</string>
+	</array>
+	<key>CFBundlePackageType</key>
+	<string>APPL</string>
+</dict>
+</plist>


=====================================
console/jpg_0XC3.cpp
=====================================
@@ -275,7 +275,7 @@ unsigned char *  decode_JPEG_SOF_0XC3 (const char *fn, int skipBytes, bool verbo
         abortGoto("Decoding error: no Huffman tables.\n");
     }
     //NEXT: unpad data - delete byte that follows $FF
-    int lIsRestartSegments = 0;
+    //int lIsRestartSegments = 0;
     long lIncI = lRawPos; //input position
     long lIncO = lRawPos; //output position
     do {
@@ -285,8 +285,8 @@ unsigned char *  decode_JPEG_SOF_0XC3 (const char *fn, int skipBytes, bool verbo
                 lIncI = lIncI+1;
             else if (lRawRA[lIncI+1] == 0xD9)
                 lIncO = -666; //end of padding
-            else
-                lIsRestartSegments = lRawRA[lIncI+1];
+            //else
+            //    lIsRestartSegments = lRawRA[lIncI+1];
         }
         lIncI++;
         lIncO++;


=====================================
console/main_console.cpp
=====================================
@@ -40,6 +40,7 @@
 #include <stdio.h>
 #include "nii_dicom_batch.h"
 #include "nii_dicom.h"
+#include "nifti1_io_core.h"
 #include <math.h>
 
 #if !defined(_WIN64) && !defined(_WIN32)
@@ -66,34 +67,37 @@ const char* removePath(const char* path) { // "/usr/path/filename.exe" -> "filen
     return path;
 } //removePath()
 
+char bool2Char(bool b) {
+	if (b) return('y');
+	return('n');
+}
+
 void showHelp(const char * argv[], struct TDCMopts opts) {
     const char *cstr = removePath(argv[0]);
     printf("usage: %s [options] <in_folder>\n", cstr);
     printf(" Options :\n");
     printf("  -1..-9 : gz compression level (1=fastest..9=smallest, default %d)\n", opts.gzLevel);
-    char bidsCh = 'n';
-    if (opts.isCreateBIDS) bidsCh = 'y';
-    printf("  -b : BIDS sidecar (y/n/o [o=only: no NIfTI], default %c)\n", bidsCh);
-    if (opts.isAnonymizeBIDS) bidsCh = 'y'; else bidsCh = 'n';
-    printf("   -ba : anonymize BIDS (y/n, default %c)\n", bidsCh);
-    printf("  -c : comment stored in NIfTI aux_file (up to 24 characters)\n");
+    printf("  -a : adjacent DICOMs (images from same series always in same folder) for faster conversion (n/y, default n)\n");
+    printf("  -b : BIDS sidecar (y/n/o [o=only: no NIfTI], default %c)\n", bool2Char(opts.isCreateBIDS));
+    printf("   -ba : anonymize BIDS (y/n, default %c)\n", bool2Char(opts.isAnonymizeBIDS));
+    printf("  -c : comment stored in NIfTI aux_file (provide up to 24 characters)\n");
     printf("  -d : directory search depth. Convert DICOMs in sub-folders of in_folder? (0..9, default %d)\n", opts.dirSearchDepth);
-    if (opts.isSortDTIbyBVal) bidsCh = 'y'; else bidsCh = 'n';
-    //printf("  -d : diffusion volumes sorted by b-value (y/n, default %c)\n", bidsCh);
+    printf("  -e : export as NRRD instead of NIfTI (y/n, default n)\n");
     #ifdef mySegmentByAcq
      #define kQstr " %%q=sequence number,"
     #else
      #define kQstr ""
     #endif
-    printf("  -f : filename (%%a=antenna (coil) name, %%b=basename, %%c=comments, %%d=description, %%e=echo number, %%f=folder name, %%i=ID of patient, %%j=seriesInstanceUID, %%k=studyInstanceUID, %%m=manufacturer, %%n=name of patient, %%p=protocol,%s %%r=instance number, %%s=series number, %%t=time, %%u=acquisition number, %%v=vendor, %%x=study ID; %%z=sequence name; default '%s')\n", kQstr, opts.filename);
+    printf("  -f : filename (%%a=antenna (coil) name, %%b=basename, %%c=comments, %%d=description, %%e=echo number, %%f=folder name, %%i=ID of patient, %%j=seriesInstanceUID, %%k=studyInstanceUID, %%m=manufacturer, %%n=name of patient, %%o=mediaObjectInstanceUID, %%p=protocol,%s %%r=instance number, %%s=series number, %%t=time, %%u=acquisition number, %%v=vendor, %%x=study ID; %%z=sequence name; default '%s')\n", kQstr, opts.filename);
     printf("  -g : generate defaults file (y/n/o/i [o=only: reset and write defaults; i=ignore: reset defaults], default n)\n");
     printf("  -h : show help\n");
     printf("  -i : ignore derived, localizer and 2D images (y/n, default n)\n");
-    char max16Ch = 'n';
-    if (opts.isMaximize16BitRange) max16Ch = 'y';
-    printf("  -l : losslessly scale 16-bit integers to use dynamic range (y/n, default %c)\n", max16Ch);
-    printf("  -m : merge 2D slices from same series regardless of study time, echo, coil, orientation, etc. (y/n, default n)\n");
-    printf("  -n : only convert this series number - can be used up to %i times (default convert all)\n", MAX_NUM_SERIES);
+	char max16Ch = 'n';
+    if (opts.isMaximize16BitRange == kMaximize16BitRange_True) max16Ch = 'y';
+    if (opts.isMaximize16BitRange == kMaximize16BitRange_Raw) max16Ch = 'o';
+    printf("  -l : losslessly scale 16-bit integers to use dynamic range (y/n/o [yes=scale, no=no, but uint16->int16, o=original], default %c)\n", max16Ch);
+    printf("  -m : merge 2D slices from same series regardless of echo, exposure, etc. (n/y or 0/1/2, default 2) [no, yes, auto]\n");
+    printf("  -n : only convert this series CRC number - can be used up to %i times (default convert all)\n", MAX_NUM_SERIES);
     printf("  -o : output directory (omit to save to input folder)\n");
     printf("  -p : Philips precise float (not display) scaling (y/n, default y)\n");
     printf("  -r : rename instead of convert DICOMs (y/n, default n)\n");
@@ -102,10 +106,16 @@ void showHelp(const char * argv[], struct TDCMopts opts) {
     #if !defined(_WIN64) && !defined(_WIN32) //shell script for Unix only
 	printf("  -u : up-to-date check\n");
 	#endif
-	printf("  -v : verbose (n/y or 0/1/2 [no, yes, logorrheic], default 0)\n");
-    printf("  -x : crop (y/n, default n)\n");
-    char gzCh = 'n';
+	printf("  -v : verbose (n/y or 0/1/2, default 0) [no, yes, logorrheic]\n");
+//#define kNAME_CONFLICT_SKIP 0 //0 = write nothing for a file that exists with desired name
+//#define kNAME_CONFLICT_OVERWRITE 1 //1 = overwrite existing file with same name
+//#define kNAME_CONFLICT_ADD_SUFFIX 2 //default 2 = write with new suffix as a new file
+    printf("  -w : write behavior for name conflicts (0,1,2, default 2: 0=skip duplicates, 1=overwrite, 2=add suffix)\n");
+   	printf("  -x : crop 3D acquisitions (y/n/i, default n, use 'i'gnore to neither crop nor rotate 3D acquistions)\n");
+   	    char gzCh = 'n';
     if (opts.isGz) gzCh = 'y';
+#if defined(_WIN64) || defined(_WIN32)
+    //n.b. the optimal use of pigz requires pipes that are not provided for Windows
     #ifdef myDisableZLib
 		if (strlen(opts.pigzname) > 0)
 			printf("  -z : gz compress images (y/n/3, default %c) [y=pigz, n=no, 3=no,3D]\n", gzCh);
@@ -118,8 +128,11 @@ void showHelp(const char * argv[], struct TDCMopts opts) {
 		printf("  -z : gz compress images (y/i/n/3, default %c) [y=pigz, i=internal:miniz, n=no, 3=no,3D]\n", gzCh);
 		#endif
     #endif
-
-#if defined(_WIN64) || defined(_WIN32)
+    printf("  --big-endian : byte order (y/n/o, default o) [y=big-end, n=little-end, o=optimal/native]\n");
+   	printf("  --progress : report progress (y/n, default n)\n");
+    printf("  --terse : omit filename post-fixes (can cause overwrites)\n");
+    printf("  --version : report version\n");
+   	printf("  --xml : Slicer format features\n");
     printf(" Defaults stored in Windows registry\n");
     printf(" Examples :\n");
     printf("  %s c:\\DICOM\\dir\n", cstr);
@@ -128,6 +141,23 @@ void showHelp(const char * argv[], struct TDCMopts opts) {
     printf("  %s -f mystudy%%s c:\\DICOM\\dir\n", cstr);
     printf("  %s -o \"c:\\dir with spaces\\dir\" c:\\dicomdir\n", cstr);
 #else
+    #ifdef myDisableZLib
+		if (strlen(opts.pigzname) > 0)
+			printf("  -z : gz compress images (y/o/n/3, default %c) [y=pigz, o=optimal pigz, n=no, 3=no,3D]\n", gzCh);
+		else
+			printf("  -z : gz compress images (y/o/n/3, default %c)  [y=pigz(MISSING!), o=optimal(requires pigz), n=no, 3=no,3D]\n", gzCh);
+    #else
+    	#ifdef myDisableMiniZ
+    	printf("  -z : gz compress images (y/o/i/n/3, default %c) [y=pigz, o=optimal pigz, i=internal:zlib, n=no, 3=no,3D]\n", gzCh);
+		#else
+		printf("  -z : gz compress images (y/o/i/n/3, default %c) [y=pigz, o=optimal pigz, i=internal:miniz, n=no, 3=no,3D]\n", gzCh);
+		#endif
+    #endif
+   	printf("  --big-endian : byte order (y/n/o, default o) [y=big-end, n=little-end, o=optimal/native]\n");
+   	printf("  --progress : Slicer format progress information (y/n, default n)\n");
+   	printf("  --terse : omit filename post-fixes (can cause overwrites)\n");
+    printf("  --version : report version\n");
+   	printf("  --xml : Slicer format features\n");
     printf(" Defaults file : %s\n", opts.optsname);
     printf(" Examples :\n");
     printf("  %s /Users/chris/dir\n", cstr);
@@ -201,11 +231,24 @@ int checkUpToDate() {
 
 #endif //shell script for UNIX only
 
+void showXML() {
+//https://www.slicer.org/wiki/Documentation/Nightly/Developers/SlicerExecutionModel#XML_Schema
+    printf("<?xml version=""1.0"" encoding=""utf-8""?>\n");
+    printf("<executable>\n");
+    printf("<title>dcm2niix</title>\n");
+    printf("<description>DICOM importer</description>\n");
+    printf("  <parameters>\n");
+    printf("    At least one parameter\n");
+    printf("  </parameters>\n");
+    printf("</executable>\n");
+}
+
 //#define mydebugtest
 int main(int argc, const char * argv[])
 {
     struct TDCMopts opts;
     bool isSaveIni = false;
+    bool isOutNameSpecified = false;
     bool isResetDefaults = false;
     readIniFile(&opts, argv); //set default preferences
 #ifdef mydebugtest
@@ -230,9 +273,41 @@ int main(int argc, const char * argv[])
     int lastCommandArg = 0;
     while (i < (argc)) { //-1 as final parameter is DICOM directory
         if ((strlen(argv[i]) > 1) && (argv[i][0] == '-')) { //command
-            if (argv[i][1] == 'h')
+            if (argv[i][1] == 'h') {
                 showHelp(argv, opts);
-            else if ((argv[i][1] >= '1') && (argv[i][1] <= '9')) {
+            } else if (( ! strcmp(argv[i], "--big-endian")) && ((i+1) < argc)) {
+				i++;
+				if ((littleEndianPlatform()) && ((argv[i][0] == 'y') || (argv[i][0] == 'Y'))) { 
+                    opts.isSaveNativeEndian = false;
+                    printf("NIfTI data will be big-endian (byte-swapped)\n");
+                }
+                if ((!littleEndianPlatform()) && ((argv[i][0] == 'n') || (argv[i][0] == 'N'))) {
+                    opts.isSaveNativeEndian = false;
+                    printf("NIfTI data will be little-endian\n");
+                }
+            } else if ( ! strcmp(argv[i], "--terse")) {
+				opts.isAddNamePostFixes = false;
+            } else if ( ! strcmp(argv[i], "--version")) {
+				printf("%s\n", kDCMdate);
+            	return kEXIT_REPORT_VERSION;
+            } else if (( ! strcmp(argv[i], "--progress")) && ((i+1) < argc)) {
+				i++;
+				if ((argv[i][0] == 'n') || (argv[i][0] == 'N')  || (argv[i][0] == '0'))
+                    opts.isProgress = 0;
+                else
+                    opts.isProgress = 1;
+                if (argv[i][0] == '2') opts.isProgress = 2; //logorrheic
+            } else if ( ! strcmp(argv[i], "--xml"))  {
+				showXML();
+				return EXIT_SUCCESS;
+            } else if ((argv[i][1] == 'a') && ((i+1) < argc)) { //adjacent DICOMs
+				i++;
+                if (invalidParam(i, argv)) return 0;
+                if ((argv[i][0] == 'n') || (argv[i][0] == 'N')  || (argv[i][0] == '0'))
+                    opts.isOneDirAtATime = false;
+                else
+                    opts.isOneDirAtATime = true;
+           } else if ((argv[i][1] >= '1') && (argv[i][1] <= '9')) {
             	opts.gzLevel = abs((int)strtol(argv[i], NULL, 10));
             	if (opts.gzLevel > 11)
         	 		opts.gzLevel = 11;
@@ -267,6 +342,11 @@ int main(int argc, const char * argv[])
                 i++;
                 if ((argv[i][0] >= '0') && (argv[i][0] <= '9'))
                 	opts.dirSearchDepth = abs((int)strtol(argv[i], NULL, 10));
+            } else if ((argv[i][1] == 'e') && ((i+1) < argc)) {
+                i++;
+                if (invalidParam(i, argv)) return 0;
+                if ((argv[i][0] == 'y') || (argv[i][0] == 'Y')  || (argv[i][0] == '1'))
+                    opts.isSaveNRRD = true;
             } else if ((argv[i][1] == 'g') && ((i+1) < argc)) {
                 i++;
                 if (invalidParam(i, argv)) return 0;
@@ -297,17 +377,24 @@ int main(int argc, const char * argv[])
             } else if ((argv[i][1] == 'l') && ((i+1) < argc)) {
                 i++;
                 if (invalidParam(i, argv)) return 0;
-                if ((argv[i][0] == 'n') || (argv[i][0] == 'N')  || (argv[i][0] == '0'))
-                    opts.isMaximize16BitRange = false;
+                if ((argv[i][0] == 'o') || (argv[i][0] == 'O'))
+                    opts.isMaximize16BitRange = kMaximize16BitRange_Raw;
+                else if ((argv[i][0] == 'n') || (argv[i][0] == 'N')  || (argv[i][0] == '0'))
+                    opts.isMaximize16BitRange = kMaximize16BitRange_False;
                 else
-                    opts.isMaximize16BitRange = true;
+                    opts.isMaximize16BitRange = kMaximize16BitRange_True;
             } else if ((argv[i][1] == 'm') && ((i+1) < argc)) {
                 i++;
                 if (invalidParam(i, argv)) return 0;
                 if ((argv[i][0] == 'n') || (argv[i][0] == 'N')  || (argv[i][0] == '0'))
-                    opts.isForceStackSameSeries = false;
-                else
-                    opts.isForceStackSameSeries = true;
+                    opts.isForceStackSameSeries = 0;
+                if ((argv[i][0] == 'y') || (argv[i][0] == 'Y')  || (argv[i][0] == '1'))
+                    opts.isForceStackSameSeries = 1;
+				if ((argv[i][0] == '2'))
+                    opts.isForceStackSameSeries = 2;
+                if ((argv[i][0] == 'o') || (argv[i][0] == 'O'))
+                    opts.isForceStackDCE = false;
+
             } else if ((argv[i][1] == 'p') && ((i+1) < argc)) {
                 i++;
                 if (invalidParam(i, argv)) return 0;
@@ -338,6 +425,9 @@ int main(int argc, const char * argv[])
             } else if (argv[i][1] == 'u') {
 				return checkUpToDate();
 			#endif
+			} else if ((argv[i][1] == 'v') && ((i+1) >= argc)) {
+				printf("%s\n", kDCMdate);
+            	return kEXIT_REPORT_VERSION;
             } else if ((argv[i][1] == 'v') && ((i+1) < argc)) {
                 i++;
                 if (invalidParam(i, argv)) return 0;
@@ -347,12 +437,26 @@ int main(int argc, const char * argv[])
                     opts.isVerbose = 2;
                 else
                     opts.isVerbose = 1; //1: verbose ON
+            } else if ((argv[i][1] == 'w') && ((i+1) < argc)) {
+                i++;
+                if (invalidParam(i, argv)) return 0;
+                if (argv[i][0] == '0') opts.nameConflictBehavior = 0;
+                if (argv[i][0] == '1') opts.nameConflictBehavior = 1;
+                if (argv[i][0] == '2') opts.nameConflictBehavior = 2;
+
+                //if ((argv[i][0] == 'n') || (argv[i][0] == 'N')  || (argv[i][0] == '0'))
+                //    opts.isOneDirAtATime = false;
+                //else
+                //    opts.isOneDirAtATime = true;
             } else if ((argv[i][1] == 'x') && ((i+1) < argc)) {
                 i++;
                 if (invalidParam(i, argv)) return 0;
                 if ((argv[i][0] == 'n') || (argv[i][0] == 'N')  || (argv[i][0] == '0'))
                     opts.isCrop = false;
-                else
+                else if ((argv[i][0] == 'i') || (argv[i][0] == 'I')) {
+                	opts.isRotate3DAcq = false;
+                	opts.isCrop = false;
+                } else
                     opts.isCrop = true;
             } else if ((argv[i][1] == 'y') && ((i+1) < argc)) {
                 i++;
@@ -380,17 +484,20 @@ int main(int argc, const char * argv[])
                     opts.isGz = false;
                 else
                     opts.isGz = true;
+                if (argv[i][0] == 'o')
+                    opts.isPipedGz = true; //pipe to pigz without saving uncompressed to disk
             } else if ((argv[i][1] == 'f') && ((i+1) < argc)) {
                 i++;
                 strcpy(opts.filename,argv[i]);
+                isOutNameSpecified = true;
             } else if ((argv[i][1] == 'o') && ((i+1) < argc)) {
                 i++;
                 strcpy(opts.outdir,argv[i]);
             } else if ((argv[i][1] == 'n') && ((i+1) < argc)) {
               i++;
-              float seriesNumber = atof(argv[i]);
+              double seriesNumber = atof(argv[i]); 
               if (seriesNumber < 0)
-              	opts.numSeries = -1; //report series: convert none
+              	opts.numSeries = -1.0; //report series: convert none
               else if ((opts.numSeries >= 0) && (opts.numSeries < MAX_NUM_SERIES)) {
                   opts.seriesNumber[opts.numSeries] = seriesNumber;
                   opts.numSeries += 1;
@@ -410,6 +517,16 @@ int main(int argc, const char * argv[])
     	printf("n.b. Setting directory search depth of zero invokes internal gz (network mode)\n");
 	}
 	#endif
+	if ((opts.isRenameNotConvert) && (!isOutNameSpecified)) { //sensible naming scheme for renaming option
+		//strcpy(opts.filename,argv[i]);
+		//2019 - now include "%o" to append media SOP UID, as instance number is not required to be unique
+		#if defined(_WIN64) || defined(_WIN32)
+		strcpy(opts.filename,"%t\\%s_%p\\%4r_%o.dcm"); //nrrd or nhdr (windows folders)
+		#else
+		strcpy(opts.filename,"%t/%s_%p/%4r_%o.dcm"); //nrrd or nhdr (unix folders)
+		#endif
+		printf("renaming without output filename, assuming '-f %s'\n", opts.filename);
+	}
     if (isSaveIni)
     	saveIniFile(opts);
     //printf("%d %d",argc,lastCommandArg);


=====================================
console/makefile
=====================================
@@ -4,6 +4,11 @@ CFLAGS=-s -O3
 # Debugging
 #CFLAGS=-g
 
+#Leak tests:
+# https://clang.llvm.org/docs/AddressSanitizer.html
+# clang++ -O1 -g -fsanitize=address -fno-omit-frame-pointer -I.  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
+
+
 #run "make" for default build
 #run "JPEGLS=1 make" for JPEGLS build
 JFLAGS=
@@ -14,7 +19,15 @@ endif
 ifneq ($(OS),Windows_NT)
 	OS = $(shell uname)
  	ifeq "$(OS)" "Darwin"
-		CFLAGS=-dead_strip -O3
+		#CFLAGS=-dead_strip -O3
+		#CFLAGS= -O3
+		CFLAGS=-O3 -sectcreate __TEXT __info_plist Info.plist
+		#Apple notarization requires a Info.plist
+		# For .app bundles, the Info.plist is a separate file, for executables it is appended as a section
+		#you can check that the Info.plist section has been inserted with either of these commands
+		# otool -l ./dcm2niix | grep info_plist -B1 -A10
+		# launchctl plist ./dcm2niix 
+		#MacOS links g++ to clang++, for gcc install via homebrew and replace g++ with /usr/local/bin/gcc-9		
 	endif
 endif
 all:


=====================================
console/nifti1.h
=====================================
@@ -7,6 +7,10 @@
            - added DT_RGBA32 and NIFTI_TYPE_RGBA32
            - added NIFTI_INTENT codes:
                 TIME_SERIES, NODE_INDEX, RGB_VECTOR, RGBA_VECTOR, SHAPE
+
+        08 Mar 2019 [PT,DRG]
+           - Updated to include [qs]form_code = 5
+
  */
 
 #ifndef _NIFTI_HEADER_
@@ -142,7 +146,6 @@ extern "C" {
  */
                         /*************************/  /************************/
 struct nifti_1_header { /* NIFTI-1 usage         */  /* ANALYZE 7.5 field(s) */
-//typedef struct __attribute__((packed))
                         /*************************/  /************************/
 
                                            /*--- was header_key substruct ---*/
@@ -277,7 +280,7 @@ typedef struct nifti_1_header nifti_1_header ;
    program can simply ignore all extended header sections simply by jumping
    straight to the image data using vox_offset.
 -----------------------------------------------------------------------------*/
-   
+
 /*! \struct nifti1_extender
     \brief This structure represents a 4-byte string that should follow the
            binary nifti_1_header data in a NIFTI-1 header file.  If the char
@@ -475,15 +478,15 @@ typedef struct nifti1_extension nifti1_extension ;
    when it encounters a dataset with a type it doesn't like.
 -----------------------------------------------------------------------------*/
 
-//#undef DT_UNKNOWN  /* defined in dirent.h on some Unix systems */
-//https://www.mail-archive.com/fltk-bugs@easysw.com/msg05850.html
+#undef DT_UNKNOWN  /* defined in dirent.h on some Unix systems */
+
 /*! \defgroup NIFTI1_DATATYPES
     \brief nifti1 datatype codes
     @{
  */
                             /*--- the original ANALYZE 7.5 type codes ---*/
 #define DT_NONE                    0
-#define DT_UNKNOWN_DT              0  //3/3/2014 CR modified to avoid conflict /usr/include/dirent
+#define DT_UNKNOWN                 0     /* what it says, dude           */
 #define DT_BINARY                  1     /* binary (1 bit/voxel)         */
 #define DT_UNSIGNED_CHAR           2     /* unsigned char (8 bits/voxel) */
 #define DT_SIGNED_SHORT            4     /* signed short (16 bits/voxel) */
@@ -911,7 +914,7 @@ typedef struct { unsigned char r,g,b; } rgb_byte ;
 
 #define NIFTI_INTENT_QUATERNION 1010
 
- /*! Dimensionless value - no params - although, as in _ESTIMATE 
+ /*! Dimensionless value - no params - although, as in _ESTIMATE
      the name of the parameter may be stored in intent_name.     */
 
 #define NIFTI_INTENT_DIMLESS    1011
@@ -1232,6 +1235,13 @@ typedef struct { unsigned char r,g,b; } rgb_byte ;
                                     /*! MNI 152 normalized coordinates. */
 
 #define NIFTI_XFORM_MNI_152      4
+
+                                    /*!  Normalized coordinates (for
+                                         any general standard template
+                                         space). Added March 8, 2019. */
+
+#define NIFTI_XFORM_TEMPLATE_OTHER  5
+
 /* @} */
 
 /*---------------------------------------------------------------------------*/
@@ -1488,4 +1498,4 @@ typedef struct { unsigned char r,g,b; } rgb_byte ;
 #endif
 /*=================*/
 
-#endif /* _NIFTI_HEADER_ */
+#endif /* _NIFTI_HEADER_ */
\ No newline at end of file


=====================================
console/nifti1_io_core.cpp
=====================================
@@ -17,6 +17,7 @@
 
 #include <stdbool.h> //requires VS 2015 or later
 #include "nifti1_io_core.h"
+#include "nifti1.h"
 #include <math.h>
 #include <stdlib.h>
 #include <sys/stat.h>
@@ -31,6 +32,7 @@
 
 #include "print.h"
 
+
 #ifndef USING_R
 void nifti_swap_8bytes( size_t n , void *ar )    // 4 bytes at a time
 {
@@ -80,6 +82,68 @@ void nifti_swap_2bytes( size_t n , void *ar )    // 2 bytes at a time
 }
 #endif
 
+/*-------------------------------------------------------------------------*/
+/*! Byte swap NIFTI-1 file header in various places and ways.
+
+    If is_nifti, swap all (even UNUSED) fields of NIfTI header.
+    Else, swap as a nifti_analyze75 struct.
+*//*---------------------------------------------------------------------- */
+void swap_nifti_header( struct nifti_1_header *h  )
+{
+
+   /* otherwise, swap all NIFTI fields */
+
+   nifti_swap_4bytes(1, &h->sizeof_hdr);
+   nifti_swap_4bytes(1, &h->extents);
+   nifti_swap_2bytes(1, &h->session_error);
+
+   nifti_swap_2bytes(8, h->dim);
+   nifti_swap_4bytes(1, &h->intent_p1);
+   nifti_swap_4bytes(1, &h->intent_p2);
+   nifti_swap_4bytes(1, &h->intent_p3);
+
+   nifti_swap_2bytes(1, &h->intent_code);
+   nifti_swap_2bytes(1, &h->datatype);
+   nifti_swap_2bytes(1, &h->bitpix);
+   nifti_swap_2bytes(1, &h->slice_start);
+
+   nifti_swap_4bytes(8, h->pixdim);
+
+   nifti_swap_4bytes(1, &h->vox_offset);
+   nifti_swap_4bytes(1, &h->scl_slope);
+   nifti_swap_4bytes(1, &h->scl_inter);
+   nifti_swap_2bytes(1, &h->slice_end);
+
+   nifti_swap_4bytes(1, &h->cal_max);
+   nifti_swap_4bytes(1, &h->cal_min);
+   nifti_swap_4bytes(1, &h->slice_duration);
+   nifti_swap_4bytes(1, &h->toffset);
+   nifti_swap_4bytes(1, &h->glmax);
+   nifti_swap_4bytes(1, &h->glmin);
+
+   nifti_swap_2bytes(1, &h->qform_code);
+   nifti_swap_2bytes(1, &h->sform_code);
+
+   nifti_swap_4bytes(1, &h->quatern_b);
+   nifti_swap_4bytes(1, &h->quatern_c);
+   nifti_swap_4bytes(1, &h->quatern_d);
+   nifti_swap_4bytes(1, &h->qoffset_x);
+   nifti_swap_4bytes(1, &h->qoffset_y);
+   nifti_swap_4bytes(1, &h->qoffset_z);
+
+   nifti_swap_4bytes(4, h->srow_x);
+   nifti_swap_4bytes(4, h->srow_y);
+   nifti_swap_4bytes(4, h->srow_z);
+
+   return ;
+}
+
+bool littleEndianPlatform ()
+{
+    uint32_t value = 1;
+    return (*((char *) &value) == 1);
+}
+
 int isSameFloat (float a, float b) {
     return (fabs (a - b) <= FLT_EPSILON);
 }
@@ -498,6 +562,288 @@ mat44 nifti_mat44_inverse( mat44 R )
 }
 #endif
 
+// Eigen decomposition for symmetric 3x3 matrices, port of public domain Java Matrix library JAMA.
+// Connelly Barnes http://barnesc.blogspot.com/2007/02/eigenvectors-of-3x3-symmetric-matrix.html
+// see also https://www.geometrictools.com/Documentation/RobustEigenSymmetric3x3.pdf
+//begin: Connelly Barnes code
+#include <math.h>
+
+#ifdef MAX
+#undef MAX
+#endif
+
+#define MAX(a, b) ((a)>(b)?(a):(b))
+
+#define n 3
+
+static double hypot2(double x, double y) {
+  return sqrt(x*x+y*y);
+}
+
+// Symmetric Householder reduction to tridiagonal form.
+
+static void tred2(double V[n][n], double d[n], double e[n]) {
+//  This is derived from the Algol procedures tred2 by
+//  Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
+//  Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
+//  Fortran subroutine in EISPACK.
+  for (int j = 0; j < n; j++) {
+    d[j] = V[n-1][j];
+  }
+  // Householder reduction to tridiagonal form.
+  for (int i = n-1; i > 0; i--) {
+    // Scale to avoid under/overflow.
+    double scale = 0.0;
+    double h = 0.0;
+    for (int k = 0; k < i; k++) {
+      scale = scale + fabs(d[k]);
+    }
+    if (scale == 0.0) {
+      e[i] = d[i-1];
+      for (int j = 0; j < i; j++) {
+        d[j] = V[i-1][j];
+        V[i][j] = 0.0;
+        V[j][i] = 0.0;
+      }
+    } else {
+      // Generate Householder vector.
+      for (int k = 0; k < i; k++) {
+        d[k] /= scale;
+        h += d[k] * d[k];
+      }
+      double f = d[i-1];
+      double g = sqrt(h);
+      if (f > 0) {
+        g = -g;
+      }
+      e[i] = scale * g;
+      h = h - f * g;
+      d[i-1] = f - g;
+      for (int j = 0; j < i; j++) {
+        e[j] = 0.0;
+      }
+      // Apply similarity transformation to remaining columns.
+      for (int j = 0; j < i; j++) {
+        f = d[j];
+        V[j][i] = f;
+        g = e[j] + V[j][j] * f;
+        for (int k = j+1; k <= i-1; k++) {
+          g += V[k][j] * d[k];
+          e[k] += V[k][j] * f;
+        }
+        e[j] = g;
+      }
+      f = 0.0;
+      for (int j = 0; j < i; j++) {
+        e[j] /= h;
+        f += e[j] * d[j];
+      }
+      double hh = f / (h + h);
+      for (int j = 0; j < i; j++) {
+        e[j] -= hh * d[j];
+      }
+      for (int j = 0; j < i; j++) {
+        f = d[j];
+        g = e[j];
+        for (int k = j; k <= i-1; k++) {
+          V[k][j] -= (f * e[k] + g * d[k]);
+        }
+        d[j] = V[i-1][j];
+        V[i][j] = 0.0;
+      }
+    }
+    d[i] = h;
+  }
+  // Accumulate transformations.
+  for (int i = 0; i < n-1; i++) {
+    V[n-1][i] = V[i][i];
+    V[i][i] = 1.0;
+    double h = d[i+1];
+    if (h != 0.0) {
+      for (int k = 0; k <= i; k++) {
+        d[k] = V[k][i+1] / h;
+      }
+      for (int j = 0; j <= i; j++) {
+        double g = 0.0;
+        for (int k = 0; k <= i; k++) {
+          g += V[k][i+1] * V[k][j];
+        }
+        for (int k = 0; k <= i; k++) {
+          V[k][j] -= g * d[k];
+        }
+      }
+    }
+    for (int k = 0; k <= i; k++) {
+      V[k][i+1] = 0.0;
+    }
+  }
+  for (int j = 0; j < n; j++) {
+    d[j] = V[n-1][j];
+    V[n-1][j] = 0.0;
+  }
+  V[n-1][n-1] = 1.0;
+  e[0] = 0.0;
+}
+
+// Symmetric tridiagonal QL algorithm.
+
+static void tql2(double V[n][n], double d[n], double e[n]) {
+//  This is derived from the Algol procedures tql2, by
+//  Bowdler, Martin, Reinsch, and Wilkinson, Handbook for
+//  Auto. Comp., Vol.ii-Linear Algebra, and the corresponding
+//  Fortran subroutine in EISPACK.
+  for (int i = 1; i < n; i++) {
+    e[i-1] = e[i];
+  }
+  e[n-1] = 0.0;
+  double f = 0.0;
+  double tst1 = 0.0;
+  double eps = pow(2.0,-52.0);
+  for (int l = 0; l < n; l++) {
+    // Find small subdiagonal element
+    tst1 = MAX(tst1,fabs(d[l]) + fabs(e[l]));
+    int m = l;
+    while (m < n) {
+      if (fabs(e[m]) <= eps*tst1) {
+        break;
+      }
+      m++;
+    }
+    // If m == l, d[l] is an eigenvalue,
+    // otherwise, iterate.
+    if (m > l) {
+      int iter = 0;
+      do {
+        iter = iter + 1;  // (Could check iteration count here.)
+        // Compute implicit shift
+        double g = d[l];
+        double p = (d[l+1] - g) / (2.0 * e[l]);
+        double r = hypot2(p,1.0);
+        if (p < 0) {
+          r = -r;
+        }
+        d[l] = e[l] / (p + r);
+        d[l+1] = e[l] * (p + r);
+        double dl1 = d[l+1];
+        double h = g - d[l];
+        for (int i = l+2; i < n; i++) {
+          d[i] -= h;
+        }
+        f = f + h;
+        // Implicit QL transformation.
+        p = d[m];
+        double c = 1.0;
+        double c2 = c;
+        double c3 = c;
+        double el1 = e[l+1];
+        double s = 0.0;
+        double s2 = 0.0;
+        for (int i = m-1; i >= l; i--) {
+          c3 = c2;
+          c2 = c;
+          s2 = s;
+          g = c * e[i];
+          h = c * p;
+          r = hypot2(p,e[i]);
+          e[i+1] = s * r;
+          s = e[i] / r;
+          c = p / r;
+          p = c * d[i] - s * g;
+          d[i+1] = h + s * (c * g + s * d[i]);
+          // Accumulate transformation.
+          for (int k = 0; k < n; k++) {
+            h = V[k][i+1];
+            V[k][i+1] = s * V[k][i] + c * h;
+            V[k][i] = c * V[k][i] - s * h;
+          }
+        }
+        p = -s * s2 * c3 * el1 * e[l] / dl1;
+        e[l] = s * p;
+        d[l] = c * p;
+        // Check for convergence.
+      } while (fabs(e[l]) > eps*tst1);
+    }
+    d[l] = d[l] + f;
+    e[l] = 0.0;
+  }
+  // Sort eigenvalues and corresponding vectors.
+  for (int i = 0; i < n-1; i++) {
+    int k = i;
+    double p = d[i];
+    for (int j = i+1; j < n; j++) {
+      if (d[j] < p) {
+        k = j;
+        p = d[j];
+      }
+    }
+    if (k != i) {
+      d[k] = d[i];
+      d[i] = p;
+      for (int j = 0; j < n; j++) {
+        p = V[j][i];
+        V[j][i] = V[j][k];
+        V[j][k] = p;
+      }
+    }
+  }
+}
+
+void eigen_decomposition(double A[n][n], double V[n][n], double d[n]) {
+  double e[n];
+  for (int i = 0; i < n; i++) {
+    for (int j = 0; j < n; j++) {
+      V[i][j] = A[i][j];
+    }
+  }
+  tred2(V, d, e);
+  tql2(V, d, e);
+}
+//end: Connelly Barnes code
+
+/*void printMat(char ch, double A[3][3]) {
+	printf("%c=[%g %g %g; %g %g %g; %g %g %g];\n", ch,
+		A[0][0],A[0][1],A[0][2],
+		A[1][0],A[1][1],A[1][2],
+		A[2][0],A[2][1],A[2][2]);
+}*/
+
+vec3 nifti_mat33_eig3(double bxx, double bxy, double bxz, double byy, double byz, double bzz) {
+    double A[3][3];
+    A[0][0] = bxx;
+    A[0][1] = bxy;
+    A[0][2] = bxz;
+    A[1][0] = bxy;
+    A[1][1] = byy;
+    A[1][2] = byz;
+    A[2][0] = bxz;
+    A[2][1] = byz;
+    A[2][2] = bzz;
+	double V[3][3];
+	double d[3];
+    eigen_decomposition(A,V,d);
+    //printMat('A',A);
+    //printf("[V,D] = eig(A) %%where A*V = V*D\n");
+    //printMat('V',V);
+    //printf("D = [%g 0 0; 0 %g 0; 0 0 %g]\n", d[0], d[1], d[2]);
+    vec3 v3;
+    v3.v[0] = V[0][2];
+    v3.v[1] = V[1][2];
+    v3.v[2] = V[2][2];
+	if (v3.v[0] < 0.0) {
+		//B-matrix underspecified to describe B-vector
+		// Describes direction but not polarity of B-vector
+		// e.g. We get an eigenvector, but eigenvalue can be + or -
+		//  https://github.com/rordenlab/dcm2niix/issues/265
+		// Like B2q We set the vector to have a positive x component by convention.
+		//  https://raw.githubusercontent.com/matthew-brett/nibabel/master/nibabel/nicom/dwiparams.py
+		// This ensures eddy will see this as a half shell and not attempt to interpret arbitrary signs
+		v3.v[0] = -v3.v[0];
+		v3.v[1] = -v3.v[1];
+		v3.v[2] = -v3.v[2];
+	}
+    //printf("bvec = [%g 0 0; 0 %g 0; 0 0 %g]\n", v3.v[0], v3.v[1], v3.v[2]);
+    return v3;
+}
 
 
 


=====================================
console/nifti1_io_core.h
=====================================
@@ -8,6 +8,8 @@
 #define STRICT_R_HEADERS
 #include "RNifti.h"
 #endif
+#include "nifti1.h"
+#include <stdint.h>
 
 #ifdef  __cplusplus
 extern "C" {
@@ -52,7 +54,10 @@ float dotProduct(vec3 u, vec3 v);
 float nifti_mat33_determ( mat33 R ) ;
 int isSameFloat (float a, float b) ;
 int isSameDouble (double a, double b) ;
+bool littleEndianPlatform ();
 
+
+vec3 nifti_mat33_eig3(double bxx, double bxy, double bxz, double byy, double byz, double bzz);
 mat33 nifti_mat33_inverse( mat33 R );
 mat33 nifti_mat33_mul( mat33 A , mat33 B );
 mat33 nifti_mat33_transpose( mat33 A ) ;
@@ -65,6 +70,7 @@ vec3 nifti_vect33mat33_mul(vec3 v, mat33 m );
 ivec3 setiVec3(int x, int y, int z);
 vec3 setVec3(float x, float y, float z);
 vec4 setVec4(float x, float y, float z);
+void  swap_nifti_header ( struct nifti_1_header *h) ;
 vec4 nifti_vect44mat44_mul(vec4 v, mat44 m );
 void nifti_swap_2bytes( size_t n , void *ar );    // 2 bytes at a time
 void nifti_swap_4bytes( size_t n , void *ar );    // 4 bytes at a time


=====================================
console/nii_dicom.cpp
=====================================
The diff for this file was not included because it is too large.

=====================================
console/nii_dicom.h
=====================================
@@ -43,13 +43,14 @@ extern "C" {
 	#define kCCsuf " CompilerNA" //unknown compiler!
 #endif
 
-#define kDCMvers "v1.0.20181125 " kJP2suf kLSsuf kCCsuf
+#define kDCMdate "v1.0.20200331"
+#define kDCMvers kDCMdate " " kJP2suf kLSsuf kCCsuf
 
 static const int kMaxEPI3D = 1024; //maximum number of EPI images in Siemens Mosaic
 static const int kMaxDTI4D = 18000; //maximum number of DTI directions for 4D (Philips) images, also maximum number of 3D slices for Philips 3D and 4D images
 static const int kMaxSlice2D = 64000; //maximum number of 2D slices in 4D (Philips) images
 
-#define kDICOMStr 64
+#define kDICOMStr 66 //64 characters plus NULL https://github.com/rordenlab/dcm2niix/issues/268
 #define kDICOMStrLarge 256
 #define kMANUFACTURER_UNKNOWN  0
 #define kMANUFACTURER_SIEMENS  1
@@ -58,6 +59,8 @@ static const int kMaxSlice2D = 64000; //maximum number of 2D slices in 4D (Phili
 #define kMANUFACTURER_TOSHIBA  4
 #define kMANUFACTURER_UIH  5
 #define kMANUFACTURER_BRUKER  6
+#define kMANUFACTURER_HITACHI 7
+#define kMANUFACTURER_CANON  8
 
 //note: note a complete modality list, e.g. XA,PX, etc
 #define kMODALITY_UNKNOWN  0
@@ -79,7 +82,18 @@ static const int kMaxSlice2D = 64000; //maximum number of 2D slices in 4D (Phili
 //#define kGE_PHASE_DIRECTION_CENTER_OUT_REV  3
 //#define kGE_PHASE_DIRECTION_CENTER_OUT  4
 
+//EXIT_SUCCESS 0
+//EXIT_FAILURE 1
 #define kEXIT_NO_VALID_FILES_FOUND  2
+#define kEXIT_REPORT_VERSION  3
+#define kEXIT_CORRUPT_FILE_FOUND  4
+#define kEXIT_INPUT_FOLDER_INVALID  5
+#define kEXIT_OUTPUT_FOLDER_INVALID  6
+#define kEXIT_OUTPUT_FOLDER_READ_ONLY  7
+#define kEXIT_RENAME_ERROR  8
+#define kEXIT_SOME_OK_SOME_BAD  8
+
+
 static const int kSliceOrientUnknown = 0;
 static const int kSliceOrientTra = 1;
 static const int kSliceOrientSag = 2;
@@ -91,7 +105,7 @@ static const int kCompressC3 = 2; //obsolete JPEG lossless
 static const int kCompress50 = 3; //obsolete JPEG lossy
 static const int kCompressRLE = 4; //run length encoding
 static const int kCompressPMSCT_RLE1 = 5; //see rle2img: Philips/ELSCINT1 run-length compression 07a1,1011= PMSCT_RLE1
-static const int kCompressJPEGLS = 5; //LoCo JPEG-LS
+static const int kCompressJPEGLS = 6; //LoCo JPEG-LS
 #ifdef myEnableJasper
     static const int kCompressSupport = kCompressYes; //JASPER for JPEG2000
 #else
@@ -155,24 +169,25 @@ static const uint8_t MAX_NUMBER_OF_DIMENSIONS = 8;
     struct TDICOMdata {
         long seriesNum;
         int xyzDim[5];
-        uint32_t coilCrc;
-        int numberOfImagesInGridUIH, numberOfDiffusionDirectionGE, phaseEncodingGE, protocolBlockStartGE, protocolBlockLengthGE, modality, dwellTime, effectiveEchoSpacingGE, phaseEncodingLines, phaseEncodingSteps, echoTrainLength, echoNum, sliceOrient, manufacturer, converted2NII, acquNum, imageNum, imageStart, imageBytes, bitsStored, bitsAllocated, samplesPerPixel,locationsInAcquisition, compressionScheme;
-        float imagingFrequency, patientWeight, zSpacing, zThick, pixelBandwidth, SAR, phaseFieldofView, accelFactPE, flipAngle, fieldStrength, TE, TI, TR, intenScale, intenIntercept, intenScalePhilips, gantryTilt, lastScanLoc, angulation[4];
+        uint32_t coilCrc, seriesUidCrc, instanceUidCrc;
+        int maxEchoNumGE, rawDataRunNumber, numberOfImagesInGridUIH, numberOfDiffusionDirectionGE, phaseEncodingGE, protocolBlockStartGE, protocolBlockLengthGE, modality, dwellTime, effectiveEchoSpacingGE, phaseEncodingLines, phaseEncodingSteps, echoTrainLength, echoNum, sliceOrient, manufacturer, converted2NII, acquNum, imageNum, imageStart, imageBytes, bitsStored, bitsAllocated, samplesPerPixel,locationsInAcquisition, locationsInAcquisitionConflict, compressionScheme;
+        float percentSampling,waterFatShift, numberOfAverages, imagingFrequency, patientWeight, zSpacing, zThick, pixelBandwidth, SAR, phaseFieldofView, accelFactPE, flipAngle, fieldStrength, TE, TI, TR, intenScale, intenIntercept, intenScalePhilips, gantryTilt, lastScanLoc, angulation[4];
         float orient[7], patientPosition[4], patientPositionLast[4], xyzMM[4], stackOffcentre[4];
         float rtia_timerGE, radionuclidePositronFraction, radionuclideTotalDose, radionuclideHalfLife, doseCalibrationFactor; //PET ISOTOPE MODULE ATTRIBUTES (C.8-57)
 		float ecat_isotope_halflife, ecat_dosage;
+		float pixelPaddingValue;  // used for both FloatPixelPaddingValue (0028, 0122) and PixelPaddingValue (0028, 0120); NaN if not present.
         double acquisitionDuration, triggerDelayTime, RWVScale, RWVIntercept, dateTime, acquisitionTime, acquisitionDate, bandwidthPerPixelPhaseEncode;
-        char coilElements[kDICOMStr], coilName[kDICOMStr], phaseEncodingDirectionDisplayedUIH[kDICOMStr], imageBaseName[kDICOMStr], scanOptions[kDICOMStr], stationName[kDICOMStr], softwareVersions[kDICOMStr], deviceSerialNumber[kDICOMStr], institutionAddress[kDICOMStr], institutionName[kDICOMStr], referringPhysicianName[kDICOMStr], seriesInstanceUID[kDICOMStr], studyInstanceUID[kDICOMStr], bodyPartExamined[kDICOMStr], procedureStepDescription[kDICOMStr], imageType[kDICOMStr], institutionalDepartmentName[kDICOMStr], manufacturersModelName[kDICOMStr], patientID[kDICOMStr], patientOrient[kDICOMStr], patientName[kDICOMStr],seriesDescription[kDICOMStr], studyID[kDICOMStr], sequenceName[kDICOMStr], protocolName[kDICOMStr],sequenceVariant[kDICOMStr],scanningSequence[kDICOMStr], patientBirthDate[kDICOMStr], patientAge[kDICOMStr],  studyDate[kDICOMStr],studyTime[kDICOMStr];
-        char imageComments[kDICOMStrLarge];
+        char coilElements[kDICOMStr], coilName[kDICOMStr], phaseEncodingDirectionDisplayedUIH[kDICOMStr], imageBaseName[kDICOMStr], scanOptions[kDICOMStr], stationName[kDICOMStr], softwareVersions[kDICOMStr], deviceSerialNumber[kDICOMStr], institutionName[kDICOMStr], referringPhysicianName[kDICOMStr], instanceUID[kDICOMStr], seriesInstanceUID[kDICOMStr], studyInstanceUID[kDICOMStr], bodyPartExamined[kDICOMStr], procedureStepDescription[kDICOMStr], imageType[kDICOMStr], institutionalDepartmentName[kDICOMStr], manufacturersModelName[kDICOMStr], patientID[kDICOMStr], patientOrient[kDICOMStr], patientName[kDICOMStr], accessionNumber[kDICOMStr], seriesDescription[kDICOMStr], studyID[kDICOMStr], sequenceName[kDICOMStr], protocolName[kDICOMStr],sequenceVariant[kDICOMStr],scanningSequence[kDICOMStr], patientBirthDate[kDICOMStr], patientAge[kDICOMStr],  studyDate[kDICOMStr],studyTime[kDICOMStr];
+        char institutionAddress[kDICOMStrLarge], imageComments[kDICOMStrLarge];
         uint32_t dimensionIndexValues[MAX_NUMBER_OF_DIMENSIONS];
         struct TCSAdata CSA;
-        bool isCoilVaries, isNonParallelSlices, isSegamiOasis, isXA10A, isScaleOrTEVaries,  isDerived, isXRay, isMultiEcho, isValid, is3DAcq, is2DAcq, isExplicitVR, isLittleEndian, isPlanarRGB, isSigned, isHasPhase, isHasImaginary, isHasReal, isHasMagnitude,isHasMixed, isFloat, isResampled, isLocalizer;
+        bool isPartialFourier, isDiffusion, isVectorFromBMatrix, isRawDataStorage, isGrayscaleSoftcopyPresentationState, isStackableSeries, isCoilVaries, isNonParallelSlices, isSegamiOasis, isXA10A, isScaleOrTEVaries, isScaleVariesEnh, isDerived, isXRay, isMultiEcho, isValid, is3DAcq, is2DAcq, isExplicitVR, isLittleEndian, isPlanarRGB, isSigned, isHasPhase, isHasImaginary, isHasReal, isHasMagnitude,isHasMixed, isFloat, isResampled, isLocalizer;
         char phaseEncodingRC, patientSex;
     };
 
     size_t nii_ImgBytes(struct nifti_1_header hdr);
     int isSameFloatGE (float a, float b);
-    void getFileName( char *pathParent, const char *path);
+    void getFileNameX( char *pathParent, const char *path, int maxLen);
     struct TDICOMdata readDICOMv(char * fname, int isVerbose, int compressFlag, struct TDTI4D *dti4D);
     struct TDICOMdata readDICOM(char * fname);
     struct TDICOMdata clear_dicom_data(void);


=====================================
console/nii_dicom_batch.cpp
=====================================
The diff for this file was not included because it is too large.

=====================================
console/nii_dicom_batch.h
=====================================
@@ -17,29 +17,44 @@ extern "C" {
 
 #ifdef USING_R
     struct TDicomSeries {
+        std::string name;
         TDICOMdata representativeData;
         std::vector<std::string> files;
     };
 #endif
 
+#define kNAME_CONFLICT_SKIP 0 //0 = write nothing for a file that exists with desired name
+#define kNAME_CONFLICT_OVERWRITE 1 //1 = overwrite existing file with same name
+#define kNAME_CONFLICT_ADD_SUFFIX 2 //default 2 = write with new suffix as a new file
+
+#define kMaximize16BitRange_False 0 //e.g. raw UINT16 values 0..4095 saved as INT16 (e.g. AFNI preserves INT16 "short", converts UINT16 to float32) 
+#define kMaximize16BitRange_True 1 //e.g. raw UINT16 values 0..4095 saved as 0..61425 UINT16 (SPM free precision)
+#define kMaximize16BitRange_Raw 2 //e.g. raw UINT16 values 0..4095 saved as UINT16 (retains raw data type, AFNI would convert to float32) 
+#define kMaximize16BitRange_Float32 3 //save 16-bit INT16 and UINT16 as FLOAT32 (AFNI will be happy, retain scale factors in Philips data where slope varies between slices)
+
 #define MAX_NUM_SERIES 16
 
     struct TDCMopts {
-        bool isRenameNotConvert, isMaximize16BitRange, isSave3D,isGz, isFlipY,  isCreateBIDS, isSortDTIbyBVal, isAnonymizeBIDS, isOnlyBIDS, isCreateText, isIgnoreDerivedAnd2D, isPhilipsFloatNotDisplayScaling, isTiltCorrect, isRGBplanar, isOnlySingleFile, isForceStackSameSeries, isCrop;
-        int isVerbose, compressFlag, dirSearchDepth, gzLevel; //support for compressed data 0=none,
+        bool isAddNamePostFixes, isSaveNativeEndian, isSaveNRRD, isOneDirAtATime, isRenameNotConvert, isSave3D, isGz, isPipedGz, isFlipY,  isCreateBIDS, isSortDTIbyBVal, isAnonymizeBIDS, isOnlyBIDS, isCreateText, isIgnoreDerivedAnd2D, isPhilipsFloatNotDisplayScaling, isTiltCorrect, isRGBplanar, isOnlySingleFile, isForceStackDCE, isRotate3DAcq, isCrop;
+        int isMaximize16BitRange, isForceStackSameSeries, nameConflictBehavior, isVerbose, isProgress, compressFlag, dirSearchDepth, gzLevel; //support for compressed data 0=none,
         char filename[512], outdir[512], indir[512], pigzname[512], optsname[512], indirParent[512], imageComments[24];
-        float seriesNumber[MAX_NUM_SERIES];
+        double seriesNumber[MAX_NUM_SERIES]; //requires double must store -1 (report but do not convert) as well as seriesUidCrc (uint32)
         long numSeries;
 #ifdef USING_R
         bool isScanOnly;
         void *imageList;
         std::vector<TDicomSeries> series;
+
+        // Used when sorting a directory
+        std::vector<std::string> sourcePaths;
+        std::vector<std::string> targetPaths;
+        std::vector<std::string> ignoredPaths;
 #endif
     };
     void saveIniFile (struct TDCMopts opts);
     void setDefaultOpts (struct TDCMopts *opts, const char * argv[]); //either "setDefaultOpts(opts,NULL)" or "setDefaultOpts(opts,argv)" where argv[0] is path to search
     void readIniFile (struct TDCMopts *opts, const char * argv[]);
-    int nii_saveNII(char * niiFilename, struct nifti_1_header hdr, unsigned char* im, struct TDCMopts opts);
+    int nii_saveNIIx(char * niiFilename, struct nifti_1_header hdr, unsigned char* im, struct TDCMopts opts);
     //void readIniFile (struct TDCMopts *opts);
     int nii_loadDir(struct TDCMopts *opts);
     //void nii_SaveBIDS(char pathoutname[], struct TDICOMdata d, struct TDCMopts opts, struct TDTI4D *dti4D, struct nifti_1_header *h, const char * filename);


=====================================
console/nii_foreign.cpp
=====================================
@@ -96,7 +96,7 @@ unsigned char * readEcat7(const char *fname, struct TDICOMdata *dcm, struct nift
         uint16_t angular_compression, coin_samp_mode, axial_samp_mode;
         Float32 ecat_calibration_factor;
         uint16_t calibration_unitS, calibration_units_type, compression_code;
-        char study_type[12], patient_id[16], patient_name[32], patient_sex, patient_dexterity;
+        char study_type[12], patient_id[16], accession_number[16], patient_name[32], patient_sex, patient_dexterity;
         Float32 patient_age, patient_height, patient_weight;
         uint32 patient_birth_date;
         char physician_name[32], operator_name[32], study_description[32];
@@ -270,7 +270,7 @@ PACK( typedef struct {
     			isAbort = true;
     		}
     		if (num_vol < kMaxVols) {
-    			imgOffsets[num_vol]	= lhdr.r[k][1];
+    			imgOffsets[num_vol]	= (size_t)lhdr.r[k][1];
     			imgSlopes[num_vol] = ihdrN.scale_factor;
     		}
     		num_vol ++;
@@ -297,12 +297,12 @@ PACK( typedef struct {
 	unsigned char * img = NULL;
 	if ((isScaleFactorVaries) && (bytesPerVoxel == 2)) { //we need to convert volumes from 16-bit to 32-bit to preserve scaling factors
 		int num_vox = ihdr.x_dimension * ihdr.y_dimension * ihdr.z_dimension;
-		size_t bytesPerVolumeIn = num_vox * bytesPerVoxel; //bytesPerVoxel == 2
+		size_t bytesPerVolumeIn = (size_t)(num_vox * bytesPerVoxel); //bytesPerVoxel == 2
 		unsigned char * imgIn = (unsigned char*)malloc(bytesPerVolumeIn);
 		int16_t * img16i = (int16_t*) imgIn;
 		bytesPerVoxel = 4;
-		size_t bytesPerVolume = num_vox * bytesPerVoxel;
-		img = (unsigned char*)malloc(bytesPerVolume * num_vol);
+		size_t bytesPerVolume = (size_t)(num_vox * bytesPerVoxel);
+		img = (unsigned char*)malloc((size_t)(bytesPerVolume * num_vol));
 		float * img32 = (float*) img;
 		for (int v = 0; v < num_vol; v++) {
 			fseek(f, imgOffsets[v] * 512, SEEK_SET);
@@ -348,12 +348,14 @@ PACK( typedef struct {
     //copy and clean strings (ECAT can use 0x0D as a string terminator)
     strncpy(dcm->patientName, mhdr.patient_name, 32);
     strncpy(dcm->patientID, mhdr.patient_id, 16);
+    strncpy(dcm->accessionNumber, mhdr.accession_number, 16);
     strncpy(dcm->seriesDescription, mhdr.study_description, 32);
     strncpy(dcm->protocolName, mhdr.study_type, 12);
     strncpy(dcm->imageComments, mhdr.isotope_name, 8);
 	strncpy(dcm->procedureStepDescription, mhdr.radiopharmaceutical, 32);
 	strClean(dcm->patientName);
 	strClean(dcm->patientID);
+	strClean(dcm->accessionNumber);
 	strClean(dcm->seriesDescription);
 	strClean(dcm->protocolName);
 	strClean(dcm->imageComments);
@@ -368,6 +370,7 @@ PACK( typedef struct {
     	printMessage(" Time between volumes %gms\n", timeBetweenVolumes );
     	printMessage(" Patient name '%s'\n", dcm->patientName);
     	printMessage(" Patient ID '%s'\n", dcm->patientID);
+    	printMessage(" Accession number '%s'\n", dcm->accessionNumber);
     	printMessage(" Study description '%s'\n", dcm->seriesDescription);
     	printMessage(" Study type '%s'\n", dcm->protocolName);
     	printMessage(" Isotope name '%s'\n", dcm->imageComments);
@@ -427,7 +430,7 @@ int  convert_foreign (const char *fn, struct TDCMopts opts){
 	//struct TDTI4D dti4D;
 	//nii_SaveBIDS(niiFilename, dcm, opts, &dti4D, &hdr, fn);
 	nii_SaveBIDS(niiFilename, dcm, opts, &hdr, fn);
-	ret = nii_saveNII(niiFilename, hdr, img, opts);
+	ret = nii_saveNIIx(niiFilename, hdr, img, opts);
 	free(img);
     return ret;
 }// convert_foreign()


=====================================
console/print.h
=====================================
@@ -11,9 +11,10 @@
 	#ifdef USING_R
 		#define R_USE_C99_IN_CXX
 		#include <R_ext/Print.h>
-		#define printMessage(...) { Rprintf("[dcm2niix info] "); Rprintf(__VA_ARGS__); }
-		#define printWarning(...) { Rprintf("[dcm2niix WARNING] "); Rprintf(__VA_ARGS__); }
-		#define printError(...) { Rprintf("[dcm2niix ERROR] "); Rprintf(__VA_ARGS__); }
+		#define printMessage(...)   do { Rprintf("[dcm2niix info] "); Rprintf(__VA_ARGS__); } while (0)
+		#define printWarning(...)   do { Rprintf("[dcm2niix WARNING] "); Rprintf(__VA_ARGS__); } while (0)
+		#define printError(...)     do { Rprintf("[dcm2niix ERROR] "); Rprintf(__VA_ARGS__); } while (0)
+		#define printError(frac)     do { Rprintf("[dcm2niix PROGRESS] %g", frac); } while (0)
 	#else
 		#ifdef myUseCOut
 			//for piping output to Qtextedit
@@ -32,10 +33,12 @@
 			  delete[] buf;
 			}
 			#define printError(...) do { printMessage("Error: "); printMessage(__VA_ARGS__);} while(0)
+			#define printProgress(frac) do { printMessage("Progress: %g\n", frac);} while(0)
 		#else
 			#include<stdio.h>
 			#define printMessage printf
 			//#define printMessageError(...) fprintf (stderr, __VA_ARGS__)
+			#define printProgress(frac) do { printMessage("Progress: %g\n", frac);} while(0)
 			#ifdef myErrorStdOut //for XCode MRIcro project, pipe errors to stdout not stderr
 				#define printError(...) do { printMessage("Error: "); printMessage(__VA_ARGS__);} while(0)
 			#else


=====================================
console/ujpeg.h
=====================================
@@ -9,7 +9,7 @@ typedef enum _nj_result {
     NJ_OUT_OF_MEM,    // out of memory
     NJ_INTERNAL_ERR,  // internal error
     NJ_SYNTAX_ERROR,  // syntax error
-    __NJ_FINISHED,    // used internally, will never be reported
+    __NJ_FINISHED    // used internally, will never be reported
 } nj_result_t;
 
 // njInit: Initialize NanoJPEG.


=====================================
license.txt
=====================================
@@ -5,8 +5,16 @@ nifti.h, nifti1_io.h/nifti1_io_core.cpp is public domain
   http://sourceforge.net/projects/niftilib/files/latest/download
 ujpeg.h/ujpeg.cpp uses the MIT license (see file for license text)
   http://keyj.emphy.de/nanojpeg/
-miniz.c is public domain (http://unlicense.org)
+miniz.c is optional, it is public domain (http://unlicense.org)
  https://code.google.com/p/miniz/
+OpenJpeg is optional, it uses a BSD license
+ https://github.com/uclouvain/openjpeg/blob/master/LICENSE
+Charls is optional, it uses a BSD license
+ https://github.com/team-charls/charls/blob/master/LICENSE.md
+zlib is optional and includes a simple license
+ https://www.zlib.net/zlib_license.html
+Jasper is optional and provides its own license
+ https://github.com/mdadams/jasper/blob/master/LICENSE
 
 ---
 The Software has been developed for research purposes only and is not a clinical tool


=====================================
notarize.command
=====================================
@@ -0,0 +1,79 @@
+#!/bin/bash
+
+basedir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+
+# Assumes ~/.bash_profile is set correctly, e.g. 
+#  CODE_SIGN_SIGNATURE="Developer ID Application: John Doe"
+#  APPLE_ID_USER=doe at gmail.com
+#  DCM2NIIX_SPECIFIC_PASSWORD=bbzj-zowb-bzji-ynkl
+#  export APPLE_ID_USER DCM2NIIX_SPECIFIC_PASSWORD CODE_SIGN_SIGNATURE
+
+CODE_SIGN_SIGNATURE=$CODE_SIGN_SIGNATURE
+APPLE_ID_USER=$APPLE_ID_USER
+APP_SPECIFIC_PASSWORD=$DCM2NIIX_SPECIFIC_PASSWORD
+
+cd ${basedir}
+
+mkdir build && cd build
+cmake -DZLIB_IMPLEMENTATION=Cloudflare -DUSE_JPEGLS=ON -DUSE_OPENJPEG=ON ..
+make
+
+cd bin
+
+# Clean up temporary files
+rm -f dcm2niix_macOS.dmg
+rm -f upload_log_file.txt
+rm -f request_log_file.txt
+rm -f log_file.txt
+
+# https://stackoverflow.com/questions/2870992/automatic-exit-from-bash-shell-script-on-error
+# terminate on error
+set -e
+
+echo "Verifying Info.plist"
+launchctl plist dcm2niix
+
+echo "Code signing dcm2niix..."
+codesign -vvv --force --strict --options=runtime --timestamp -s "$CODE_SIGN_SIGNATURE" dcm2niix
+codesign --verify --verbose --strict dcm2niix
+
+echo "Creating disk image..."
+
+hdiutil create -volname dcm2niix -srcfolder `pwd` -ov -format UDZO -layout SPUD -fs HFS+J  dcm2niix_macOS.dmg
+
+# Notarizing with Apple...
+echo "Uploading..."
+xcrun altool --notarize-app -t osx --file dcm2niix_macOS.dmg --primary-bundle-id com.mricro.dcm2niix -u $APPLE_ID_USER -p $APP_SPECIFIC_PASSWORD --output-format xml > upload_log_file.txt
+
+# WARNING: if there is a 'product-errors' key in upload_log_file.txt something went wrong
+# we could parse it here and bail but not sure how to check for keys existing with PListBuddy
+# /usr/libexec/PlistBuddy -c "Print :product-errors:0:message" upload_log_file.txt
+
+# now we need to query apple's server to the status of notarization
+# when the "xcrun altool --notarize-app" command is finished the output plist
+# will contain a notarization-upload->RequestUUID key which we can use to check status
+echo "Checking status..."
+sleep 20
+REQUEST_UUID=`/usr/libexec/PlistBuddy -c "Print :notarization-upload:RequestUUID" upload_log_file.txt`
+while true; do
+  xcrun altool --notarization-info $REQUEST_UUID -u $APPLE_ID_USER -p $APP_SPECIFIC_PASSWORD --output-format xml > request_log_file.txt
+  # parse the request plist for the notarization-info->Status Code key which will
+  # be set to "success" if the package was notarized
+  STATUS=`/usr/libexec/PlistBuddy -c "Print :notarization-info:Status" request_log_file.txt`
+  if [ "$STATUS" != "in progress" ]; then
+    break
+  fi
+  # echo $STATUS
+  echo "$STATUS"
+  sleep 10
+done
+
+# download the log file to view any issues
+/usr/bin/curl -o log_file.txt `/usr/libexec/PlistBuddy -c "Print :notarization-info:LogFileURL" request_log_file.txt`
+
+# staple
+echo "Stapling..."
+xcrun stapler staple dcm2niix_macOS.dmg
+xcrun stapler validate dcm2niix_macOS.dmg
+
+open log_file.txt



View it on GitLab: https://salsa.debian.org/med-team/dcm2niix/-/commit/af44ba06ee1781c66fc8d5e9f7d54305c4940a59

-- 
View it on GitLab: https://salsa.debian.org/med-team/dcm2niix/-/commit/af44ba06ee1781c66fc8d5e9f7d54305c4940a59
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/debian-med-commit/attachments/20200929/e3120560/attachment-0001.html>


More information about the debian-med-commit mailing list