Skip to content

Commit

Permalink
dcm2niix, DICOMRead3 addition (freesurfer#888)
Browse files Browse the repository at this point in the history
* 1. check in package dcm2niix
2. add DICOMRead3/niiRead3 to convert dicom using dcm2niix
3. fix dcmGetDWIParams() to use stricmp() to compare the Manufacturer tag

* set TI to -1 when there is no TI in dicom file for MGH_FREESURFER

* remove unused codes

Co-authored-by: Yujing Huang <[email protected]>
  • Loading branch information
yhuang43 and Yujing Huang authored Oct 21, 2021
1 parent b964143 commit 2e54670
Show file tree
Hide file tree
Showing 71 changed files with 33,633 additions and 60 deletions.
6 changes: 6 additions & 0 deletions include/DICOMRead.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
#include "dicom_objects.h"
#include "condition.h"

#include "nii_dicom.h"
#include "nii_dicom_batch.h"

#define NUMBEROFTAGS 24
#define SHORTSIZE 16
#ifndef INTSIZE
Expand Down Expand Up @@ -59,6 +62,7 @@ typedef unsigned short int BOOL;
char *SDCMStatusFile = 0;
char *SDCMListFile = 0;
int UseDICOMRead2 = 1; // use new dicom reader by default
int UseDICOMRead3 = 0;
/* These variables allow the user to change the first tag checked to
get the slice thickness. This is needed with siemens mag res
angiogram (MRAs) */
Expand All @@ -69,6 +73,7 @@ int AutoSliceResElTag = 0; // automatically determine which tag to use based on
extern char *SDCMStatusFile;
extern char *SDCMListFile;
extern int UseDICOMRead2;
extern int UseDICOMRead3;
extern long SliceResElTag1;
extern long SliceResElTag2;
extern int AutoSliceResElTag;
Expand Down Expand Up @@ -286,6 +291,7 @@ int CompareDCMFileInfo(const void *a, const void *b);
int DCMCountFrames(DICOMInfo **dcmfi_list, int nlist);
int DCMSliceDir(DICOMInfo **dcmfi_list, int nlist);
MRI *DICOMRead2(const char *dcmfile, int LoadVolume);
MRIFSSTRUCT *DICOMRead3(const char *dcmfile, int LoadVolume);

DCM_ELEMENT *GetElementFromFile(const char *dicomfile, long grpid, long elid);
int AllocElementData(DCM_ELEMENT *e);
Expand Down
2 changes: 1 addition & 1 deletion mri_convert/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ project(mri_convert)
# ATH: temporarily turning off this warning
add_compile_options(-Wno-self-assign)

include_directories(${FS_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/packages/dicom)
include_directories(${FS_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/packages/dicom ${CMAKE_SOURCE_DIR}/packages/dcm2niix)

add_executable(mri_convert mri_convert.cpp)
add_help(mri_convert mri_convert.help.xml)
Expand Down
4 changes: 4 additions & 0 deletions mri_convert/mri_convert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1141,6 +1141,10 @@ int main(int argc, char *argv[])
forced_in_type = string_to_type(in_type_string);
force_in_type_flag = TRUE;
}
else if (strcmp(argv[i], "-dicomread3") == 0)
{
UseDICOMRead3 = 1;
}
else if(strcmp(argv[i], "-dicomread2") == 0)
{
UseDICOMRead2 = 1;
Expand Down
2 changes: 1 addition & 1 deletion mri_otl/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
project(mri_otl)

include_directories(${FS_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/packages/dicom)
include_directories(${FS_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/packages/dicom ${CMAKE_SOURCE_DIR}/packages/dcm2niix)

add_executable(list_otl_labels list_otl_labels.cpp)
target_link_libraries(list_otl_labels utils)
Expand Down
2 changes: 1 addition & 1 deletion mri_parse_sdcmdir/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
project(mri_parse_sdcmdir)

include_directories(${FS_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/packages/dicom)
include_directories(${FS_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/packages/dicom ${CMAKE_SOURCE_DIR}/packages/dcm2niix)

add_executable(mri_parse_sdcmdir mri_parse_sdcmdir.cpp)
target_link_libraries(mri_parse_sdcmdir utils)
Expand Down
1 change: 1 addition & 0 deletions mri_probedicom/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ if(OPENGL_FOUND)
${FS_INCLUDE_DIRS}
${CMAKE_SOURCE_DIR}/packages/dicom
${CMAKE_SOURCE_DIR}/packages/glut
${CMAKE_SOURCE_DIR}/packages/dcm2niix
${X11_INCLUDE_DIR}
)

Expand Down
2 changes: 1 addition & 1 deletion mri_watershed/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
project(mri_watershed)

include_directories(${FS_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/packages/dicom)
include_directories(${FS_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR}/packages/dicom ${CMAKE_SOURCE_DIR}/packages/dcm2niix)

add_executable(mri_watershed mri_watershed.cpp)
add_help(mri_watershed mri_watershed.help.xml)
Expand Down
1 change: 1 addition & 0 deletions packages/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ add_subdirectories(
xml2
minc
dicom
dcm2niix
cephes
netcdf
tetgen
Expand Down
233 changes: 233 additions & 0 deletions packages/dcm2niix/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,233 @@
cmake_minimum_required(VERSION 2.8.11)

project(dcm2niix)

# Option Choose whether to use static runtime
include(ucm.cmake)
option(USE_STATIC_RUNTIME "Use static runtime" ON)
if(USE_STATIC_RUNTIME)
ucm_set_runtime(STATIC)
else()
ucm_set_runtime(DYNAMIC)
endif()

# Basic CMake build settings
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING
"Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug;Release;RelWithDebInfo;MinSizeRel")
endif()

if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
# using Clang
add_definitions(-fno-caret-diagnostics)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-dead_strip")
elseif(${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU")
# 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()
if(NOT (${CMAKE_CXX_COMPILER_VERSION} VERSION_LESS 4.8.0))
add_definitions(-fno-diagnostics-show-caret) # available since GCC 4.8.0
endif()
elseif(MSVC)
# using Visual Studio C++
add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4018") # '<': signed/unsigned mismatch
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4068") # unknown pragma
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4101") # unreferenced local variable
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4244") # 'initializing': conversion from 'double' to 'int', possible loss of data
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4267") # 'initializing': conversion from 'size_t' to 'int', possible loss of data
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4305") # 'argument': truncation from 'double' to 'float'
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4308") # negative integral constant converted to unsigned type
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4334") # '<<': result of 32-bit shift implicitly converted to 64 bits
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4800") # 'uint32_t' : forcing value to bool 'true' or 'false'
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4819") # The file contains a character that cannot be represented in the current code page
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4996") # 'access': The POSIX name for this item is deprecated
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:8388608") # set "Stack Reserve Size" to 8MB (default value is 1MB)
endif()

# Compiler dependent flags
include (CheckCXXCompilerFlag)
if(UNIX)
check_cxx_compiler_flag(-march=armv8-a+crc ARM_CRC)
if(ARM_CRC)
# wrong answer for Apple Silicon: check_cxx_compiler_flag(-msse2 HAS_SSE2)
else()
check_cxx_compiler_flag(-msse2 HAS_SSE2)
if(HAS_SSE2)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse2 -mfpmath=sse")
endif()
endif()
endif()

set(PROGRAMS dcm2niix)

set(DCM2NIIX_SRCS
main_console.cpp
nii_dicom.cpp
jpg_0XC3.cpp
ujpeg.cpp
nifti1_io_core.cpp
nii_foreign.cpp
nii_ortho.cpp
nii_dicom_batch.cpp)

option(USE_JPEGLS "Build with JPEG-LS support using CharLS" OFF)
if(USE_JPEGLS)
add_definitions(-DmyEnableJPEGLS)
if(MSVC)
add_definitions(-DCHARLS_STATIC)
endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")

set(CHARLS_SRCS
charls/jpegls.cpp
charls/jpegmarkersegment.cpp
charls/interface.cpp
charls/jpegstreamwriter.cpp
charls/jpegstreamreader.cpp)
add_executable(dcm2niix ${DCM2NIIX_SRCS} ${CHARLS_SRCS})
else()
add_executable(dcm2niix ${DCM2NIIX_SRCS})
endif()

set(ZLIB_IMPLEMENTATION "Miniz" CACHE STRING "Choose zlib implementation.")
set_property(CACHE ZLIB_IMPLEMENTATION PROPERTY STRINGS "Miniz;System;Custom")
if(NOT ${ZLIB_IMPLEMENTATION} STREQUAL "Miniz")
if(NOT ${ZLIB_IMPLEMENTATION} STREQUAL "System")
set(ZLIB_ROOT ${ZLIB_ROOT} CACHE PATH "Specify custom zlib root directory.")
if(NOT ZLIB_ROOT)
message(FATAL_ERROR "ZLIB_ROOT needs to be set to locate custom zlib!")
endif()
endif()
find_package(ZLIB REQUIRED)
add_definitions(-DmyDisableMiniZ)
target_include_directories(dcm2niix PRIVATE ${ZLIB_INCLUDE_DIRS})
target_link_libraries(dcm2niix ${ZLIB_LIBRARIES})
endif()

option(USE_TURBOJPEG "Use TurboJPEG to decode classic JPEG" OFF)
if(USE_TURBOJPEG)
find_package(PkgConfig REQUIRED)
pkg_check_modules(TURBOJPEG REQUIRED libturbojpeg)
add_definitions(-DmyTurboJPEG)
target_include_directories(dcm2niix PRIVATE ${TURBOJPEG_INCLUDEDIR})
target_link_libraries(dcm2niix ${TURBOJPEG_LIBRARIES})
endif()

option(USE_JASPER "Build with JPEG2000 support using Jasper" OFF)
if(USE_JASPER)
find_package(Jasper REQUIRED)
add_definitions(-DmyEnableJasper)
target_include_directories(dcm2niix PRIVATE ${JASPER_INCLUDE_DIR})
target_link_libraries(dcm2niix ${JASPER_LIBRARIES})
endif()

option(USE_OPENJPEG "Build with JPEG2000 support using OpenJPEG" OFF)
if(USE_OPENJPEG)
set(OpenJPEG_DIR "${OpenJPEG_DIR}" CACHE PATH "Path to OpenJPEG configuration file" FORCE)

find_package(OpenJPEG REQUIRED)

if(WIN32)
if(BUILD_SHARED_LIBS)
add_definitions(-DOPJ_EXPORTS)
else()
add_definitions(-DOPJ_STATIC)
endif()
endif()

target_include_directories(dcm2niix PRIVATE ${OPENJPEG_INCLUDE_DIRS})
target_link_libraries(dcm2niix ${OPENJPEG_LIBRARIES})
else ()
add_definitions(-DmyDisableOpenJPEG)
endif()

option(BATCH_VERSION "Build dcm2niibatch for multiple conversions" OFF)
if(BATCH_VERSION)
set(DCM2NIIBATCH_SRCS
main_console_batch.cpp
nii_dicom.cpp
jpg_0XC3.cpp
ujpeg.cpp
nifti1_io_core.cpp
nii_foreign.cpp
nii_ortho.cpp
nii_dicom_batch.cpp)

if(USE_JPEGLS)
add_executable(dcm2niibatch ${DCM2NIIBATCH_SRCS} ${CHARLS_SRCS})
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
add_executable(dcm2niibatch ${DCM2NIIBATCH_SRCS})
endif()

set(YAML-CPP_DIR ${YAML-CPP_DIR} CACHE PATH "Path to yaml-cpp configuration file" FORCE)

find_package(YAML-CPP REQUIRED)
target_include_directories(dcm2niibatch PRIVATE ${YAML_CPP_INCLUDE_DIR})
target_link_libraries(dcm2niibatch ${YAML_CPP_LIBRARIES})

if(ZLIB_FOUND)
target_include_directories(dcm2niibatch PRIVATE ${ZLIB_INCLUDE_DIRS})
target_link_libraries(dcm2niibatch ${ZLIB_LIBRARIES})
endif()

if(TURBOJPEG_FOUND)
target_include_directories(dcm2niibatch PRIVATE ${TURBOJPEG_INCLUDEDIR})
target_link_libraries(dcm2niibatch ${TURBOJPEG_LIBRARIES})
endif()

if(JASPER_FOUND)
target_include_directories(dcm2niibatch PRIVATE ${JASPER_INCLUDE_DIR})
target_link_libraries(dcm2niibatch ${JASPER_LIBRARIES})
endif()

if(OPENJPEG_FOUND)
target_include_directories(dcm2niibatch PRIVATE ${OPENJPEG_INCLUDE_DIRS})
target_link_libraries(dcm2niibatch ${OPENJPEG_LIBRARIES})
endif()

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()

### start of addition for FREESURFER
# we should not need this if we use target_compile_definitions()
#target_link_libraries(dcm2niix nifti ${ZLIB_LIBRARIES})

set(LIBRARY dcm2niixfs)
add_library(dcm2niixfs STATIC
dcm2fsWrapper.cpp
nii_dicom.cpp
jpg_0XC3.cpp
ujpeg.cpp
nifti1_io_core.cpp
nii_foreign.cpp
nii_ortho.cpp
nii_dicom_batch.cpp)
target_compile_definitions(dcm2niixfs PUBLIC -DMGH_FREESURFER -DUSING_MGH_NIFTI_IO)

set(DCM2NIIXFSEXE dcm2niixfsexe)
add_executable(${DCM2NIIXFSEXE} dcm2fsmain.cpp)
target_link_libraries(${DCM2NIIXFSEXE} dcm2niixfs nifti ${ZLIB_LIBRARIES})
### end of addition for FREESURFER

install(TARGETS ${PROGRAMS} DESTINATION bin)
### additions for FREESURFER
install(TARGETS ${LIBRARY} DESTINATION bin)
install(TARGETS ${DCM2NIIXFSEXE} DESTINATION bin)
24 changes: 24 additions & 0 deletions packages/dcm2niix/Info.plist
Original file line number Diff line number Diff line change
@@ -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>
29 changes: 29 additions & 0 deletions packages/dcm2niix/charls/License.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
https://github.com/team-charls/charls

Copyright (c) 2007-2010, Jan de Vaan
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.

* Neither the name of my employer, nor the names of its contributors may be
used to endorse or promote products derived from this software without
specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Loading

0 comments on commit 2e54670

Please sign in to comment.