From 8713d6f217109a56503635e9a3b665ea08f391ca Mon Sep 17 00:00:00 2001 From: GDCM Upstream Date: Fri, 5 May 2023 11:51:20 +0200 Subject: [PATCH] GDCM 2023-05-05 (401a81d7) Code extracted from: https://github.com/malaterre/GDCM.git at commit 401a81d746c980dae71957d4e6126b633d2b2952 (release). --- CMakeLists.txt | 113 +- Source/Common/CMakeLists.txt | 18 +- Source/Common/gdcmASN1.cxx | 2 +- Source/Common/gdcmBase64.cxx | 2 +- Source/Common/gdcmConfigure.h.in | 4 + Source/Common/gdcmDirectory.cxx | 12 +- Source/Common/gdcmEvent.h | 4 +- Source/Common/gdcmFileNameEvent.h | 2 +- Source/Common/gdcmFilename.cxx | 18 +- Source/Common/gdcmMD5.cxx | 12 +- .../gdcmOpenSSLCryptographicMessageSyntax.cxx | 8 + ...dcmOpenSSLP7CryptographicMessageSyntax.cxx | 8 + Source/Common/gdcmSHA1.cxx | 10 +- Source/Common/gdcmSubject.cxx | 2 +- Source/Common/gdcmSwapCode.cxx | 2 +- Source/Common/gdcmSwapCode.h | 1 - Source/Common/gdcmSwapper.txx | 10 +- Source/Common/gdcmSystem.cxx | 32 +- Source/Common/gdcmTerminal.cxx | 11 +- Source/Common/gdcmTesting.cxx | 19 +- Source/Common/gdcmTesting.h | 4 +- Source/Common/gdcmUnpacker12Bits.cxx | 12 +- Source/Common/gdcmUnpacker12Bits.h | 2 +- Source/Common/zipstreamimpl.hpp | 19 +- Source/DataDictionary/CSAHeader.xml | 14 +- Source/DataDictionary/ParseDicts.py | 2 +- Source/DataDictionary/dicomhdr.html | 26 +- .../gdcmCSAHeaderDefaultDicts.cxx | 12 +- .../DataDictionary/gdcmDefaultGroupNames.cxx | 2 +- Source/DataDictionary/gdcmDictConverter.cxx | 2 +- Source/DataDictionary/gdcmGlobal.cxx | 6 +- .../gdcmPrivateDefaultDicts.cxx | 1674 ++++++++++++++--- Source/DataDictionary/gdcmUIDs.cxx | 2 +- Source/DataDictionary/privatedicts.xml | 1443 ++++++++++++-- .../gdcmBasicOffsetTable.h | 1 - .../gdcmByteSwapFilter.cxx | 2 - .../gdcmByteSwapFilter.h | 2 +- .../gdcmByteValue.cxx | 2 +- .../gdcmByteValue.h | 1 - .../gdcmCP246ExplicitDataElement.h | 1 - .../gdcmCSAHeader.cxx | 13 +- .../gdcmCSAHeader.h | 10 +- .../gdcmDataElement.cxx | 28 + .../gdcmDataSet.cxx | 22 +- .../gdcmDataSet.h | 19 +- .../gdcmDataSetEvent.h | 4 +- .../gdcmElement.h | 30 +- .../gdcmExplicitDataElement.txx | 23 +- .../gdcmFileMetaInformation.cxx | 9 +- .../gdcmFileMetaInformation.h | 17 +- .../gdcmFileSet.h | 1 - .../gdcmFragment.h | 8 +- .../gdcmItem.cxx | 2 +- .../gdcmItem.h | 2 +- .../gdcmMrProtocol.cxx | 16 +- .../gdcmPDBHeader.cxx | 14 +- .../gdcmPDBHeader.h | 2 + .../gdcmParseException.h | 2 +- .../gdcmPreamble.cxx | 2 +- .../gdcmPreamble.h | 3 +- .../gdcmPrivateTag.cxx | 19 +- .../gdcmPrivateTag.h | 24 + .../gdcmReader.cxx | 10 +- .../gdcmSequenceOfFragments.cxx | 4 +- .../gdcmSequenceOfFragments.h | 2 +- .../gdcmSequenceOfItems.h | 4 +- .../gdcmTag.cxx | 4 +- .../gdcmTransferSyntax.cxx | 6 +- .../gdcmVM.cxx | 6 +- .../gdcmVR.cxx | 4 +- .../gdcmWriter.cxx | 4 +- Source/InformationObjectDefinition/Part3.xml | 14 +- .../Template.xml.in | 2 +- .../InformationObjectDefinition/gdcmDefs.cxx | 2 +- Source/InformationObjectDefinition/gdcmDefs.h | 2 +- .../gdcmIODEntry.cxx | 2 +- .../gdcmTableReader.cxx | 8 +- .../InformationObjectDefinition/gdcmType.cxx | 2 +- .../InformationObjectDefinition/gdcmUsage.cxx | 2 +- .../gdcmXMLDictReader.cxx | 4 +- .../gdcmXMLPrivateDictReader.cxx | 4 +- .../MediaStorageAndFileFormat/CMakeLists.txt | 16 + .../gdcmAnonymizeEvent.h | 2 +- .../gdcmAnonymizer.cxx | 140 +- .../gdcmAnonymizer.h | 30 +- .../MediaStorageAndFileFormat/gdcmBitmap.cxx | 17 +- .../gdcmBitmapToBitmapFilter.cxx | 4 +- .../MediaStorageAndFileFormat/gdcmCleaner.cxx | 1314 +++++++++++++ .../MediaStorageAndFileFormat/gdcmCleaner.h | 90 + .../gdcmConstCharWrapper.h | 2 +- .../MediaStorageAndFileFormat/gdcmCurve.cxx | 14 +- .../gdcmDICOMDIRGenerator.cxx | 2 +- .../MediaStorageAndFileFormat/gdcmDPath.cxx | 158 ++ Source/MediaStorageAndFileFormat/gdcmDPath.h | 56 + .../gdcmDataSetHelper.cxx | 20 +- .../gdcmDataSetHelper.h | 2 - .../gdcmDictPrinter.cxx | 42 +- .../gdcmDictPrinter.h | 2 +- .../gdcmDirectionCosines.cxx | 6 +- .../gdcmDirectionCosines.h | 2 +- .../gdcmDirectoryHelper.cxx | 6 +- Source/MediaStorageAndFileFormat/gdcmDumper.h | 1 - .../gdcmEquipmentManufacturer.cxx | 276 ++- .../gdcmEquipmentManufacturer.h | 33 +- .../gdcmFileAnonymizer.cxx | 2 +- .../gdcmFileChangeTransferSyntax.cxx | 6 +- .../gdcmFileExplicitFilter.cxx | 6 +- .../gdcmFileStreamer.cxx | 15 +- .../gdcmIPPSorter.cxx | 2 +- .../gdcmIconImageGenerator.cxx | 54 +- .../MediaStorageAndFileFormat/gdcmImage.cxx | 6 +- .../gdcmImageApplyLookupTable.cxx | 10 +- ...cmImageChangePhotometricInterpretation.cxx | 18 +- .../gdcmImageChangeTransferSyntax.cxx | 7 +- .../gdcmImageCodec.cxx | 19 +- .../gdcmImageHelper.cxx | 34 +- .../gdcmImageReader.cxx | 6 +- .../gdcmImageRegionReader.cxx | 10 +- .../gdcmJPEG12Codec.cxx | 2 +- .../gdcmJPEG16Codec.cxx | 2 +- .../gdcmJPEG2000Codec.cxx | 44 +- .../gdcmJPEG8Codec.cxx | 2 +- .../gdcmJPEGBITSCodec.hxx | 4 +- .../gdcmJPEGCodec.cxx | 12 +- .../gdcmJPEGLSCodec.cxx | 86 +- .../gdcmLookupTable.cxx | 27 +- .../MediaStorageAndFileFormat/gdcmMEC_MR3.cxx | 37 + .../MediaStorageAndFileFormat/gdcmMEC_MR3.h | 43 + .../gdcmOrientation.cxx | 1 - .../gdcmOrientation.h | 2 +- .../MediaStorageAndFileFormat/gdcmOverlay.cxx | 4 +- .../gdcmPGXCodec.cxx | 59 +- .../MediaStorageAndFileFormat/gdcmPVRGCodec.h | 1 - .../gdcmPersonName.h | 2 +- .../gdcmPixelFormat.cxx | 2 +- .../gdcmPixelFormat.h | 2 +- .../gdcmPixmapReader.cxx | 2 +- .../gdcmPixmapReader.h | 1 - .../gdcmPixmapWriter.cxx | 4 +- .../MediaStorageAndFileFormat/gdcmPrinter.cxx | 14 +- .../MediaStorageAndFileFormat/gdcmPrinter.h | 2 +- .../gdcmRAWCodec.cxx | 6 +- .../gdcmRLECodec.cxx | 16 +- .../gdcmRescaler.cxx | 6 +- .../MediaStorageAndFileFormat/gdcmRescaler.h | 2 +- .../gdcmScanner2.cxx | 612 ++++++ .../MediaStorageAndFileFormat/gdcmScanner2.h | 208 ++ .../MediaStorageAndFileFormat/gdcmSegment.cxx | 3 - .../gdcmSegmentReader.cxx | 2 +- .../gdcmSegmentReader.h | 2 +- .../gdcmSegmentedPaletteColorLookupTable.cxx | 5 +- .../gdcmSerieHelper.cxx | 2 +- .../MediaStorageAndFileFormat/gdcmSpacing.cxx | 2 - .../MediaStorageAndFileFormat/gdcmSpacing.h | 2 +- .../gdcmSplitMosaicFilter.cxx | 26 +- .../gdcmStrictScanner2.cxx | 621 ++++++ .../gdcmStrictScanner2.h | 215 +++ .../gdcmStringFilter.cxx | 8 +- .../gdcmStringFilter.h | 2 +- .../MediaStorageAndFileFormat/gdcmSurface.cxx | 14 +- .../gdcmSurfaceWriter.cxx | 2 +- .../MediaStorageAndFileFormat/gdcmTagPath.cxx | 6 +- .../gdcmUIDGenerator.cxx | 3 +- .../gdcmUIDGenerator.h | 7 +- .../gdcmAAssociateACPDU.cxx | 2 +- .../gdcmBaseQuery.cxx | 12 +- .../gdcmBaseRootQuery.cxx | 4 - .../gdcmBaseRootQuery.h | 2 +- .../gdcmCompositeNetworkFunctions.cxx | 8 +- Source/MessageExchangeDefinition/gdcmDIMSE.h | 4 +- .../gdcmNormalizedNetworkFunctions.cxx | 4 +- .../gdcmPDUFactory.cxx | 2 +- .../gdcmPresentationDataValue.cxx | 4 +- .../gdcmQueryFactory.h | 1 - .../gdcmServiceClassUser.cxx | 22 +- .../gdcmULActionAE.cxx | 2 +- .../gdcmULActionDT.cxx | 5 +- .../gdcmULConnectionManager.cxx | 13 +- .../gdcmULConnectionManager.h | 2 +- .../MessageExchangeDefinition/gdcmULEvent.h | 4 +- .../gdcmWLMFindQuery.cxx | 4 +- Utilities/gdcm_expat.h | 2 +- Utilities/gdcm_md5.h | 2 +- Utilities/gdcm_openjpeg.h | 2 +- Utilities/gdcm_uuid.h | 2 +- Utilities/gdcm_zlib.h | 2 +- Utilities/gdcmcharls/interface.cpp | 4 +- Utilities/gdcmcharls/jpegstreamreader.cpp | 2 +- Utilities/gdcmext/csa.c | 323 ++++ Utilities/gdcmext/csa.h | 29 + Utilities/gdcmext/mec_mr3.c | 446 +++++ Utilities/gdcmext/mec_mr3.h | 29 + Utilities/gdcmext/mec_mr3_dict.c | 868 +++++++++ Utilities/gdcmext/mec_mr3_dict.h | 32 + Utilities/gdcmext/mec_mr3_io.c | 862 +++++++++ Utilities/gdcmext/mec_mr3_io.h | 30 + Utilities/gdcmrle/rle.cxx | 12 +- Utilities/gdcmutfcpp/README.GDCM.txt | 4 + Utilities/gdcmuuid/CMakeLists.txt | 2 + Utilities/gdcmuuid/COPYING | 56 +- Utilities/gdcmuuid/compare.c | 19 +- Utilities/gdcmuuid/config.h | 1 + Utilities/gdcmuuid/copy.c | 46 + Utilities/gdcmuuid/gen_uuid.c | 812 +++++--- Utilities/gdcmuuid/isnull.c | 49 + Utilities/gdcmuuid/pack.c | 49 +- Utilities/gdcmuuid/parse.c | 68 +- Utilities/gdcmuuid/unpack.c | 37 +- Utilities/gdcmuuid/unparse.c | 26 +- Utilities/gdcmuuid/uuid.h | 54 +- Utilities/gdcmuuid/uuidP.h | 33 +- Utilities/gdcmuuid/uuid_mangle.h.in | 32 +- Utilities/gdcmuuid/uuid_time.c | 193 +- Utilities/gdcmuuid/uuidd.h | 54 + Utilities/socketxx/socket++/sockinet.cpp | 10 +- Utilities/socketxx/socket++/sockstream.cpp | 2 +- Utilities/socketxx/socket++/sockstream.h | 2 +- 217 files changed, 10945 insertions(+), 1778 deletions(-) create mode 100644 Source/MediaStorageAndFileFormat/gdcmCleaner.cxx create mode 100644 Source/MediaStorageAndFileFormat/gdcmCleaner.h create mode 100644 Source/MediaStorageAndFileFormat/gdcmDPath.cxx create mode 100644 Source/MediaStorageAndFileFormat/gdcmDPath.h create mode 100644 Source/MediaStorageAndFileFormat/gdcmMEC_MR3.cxx create mode 100644 Source/MediaStorageAndFileFormat/gdcmMEC_MR3.h create mode 100644 Source/MediaStorageAndFileFormat/gdcmScanner2.cxx create mode 100644 Source/MediaStorageAndFileFormat/gdcmScanner2.h create mode 100644 Source/MediaStorageAndFileFormat/gdcmStrictScanner2.cxx create mode 100644 Source/MediaStorageAndFileFormat/gdcmStrictScanner2.h create mode 100644 Utilities/gdcmext/csa.c create mode 100644 Utilities/gdcmext/csa.h create mode 100644 Utilities/gdcmext/mec_mr3.c create mode 100644 Utilities/gdcmext/mec_mr3.h create mode 100644 Utilities/gdcmext/mec_mr3_dict.c create mode 100644 Utilities/gdcmext/mec_mr3_dict.h create mode 100644 Utilities/gdcmext/mec_mr3_io.c create mode 100644 Utilities/gdcmext/mec_mr3_io.h create mode 100644 Utilities/gdcmuuid/config.h create mode 100644 Utilities/gdcmuuid/copy.c create mode 100644 Utilities/gdcmuuid/isnull.c create mode 100644 Utilities/gdcmuuid/uuidd.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c3c707b45f..d96fc7ad690 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,7 +17,7 @@ endif() #---------------------------------------------------------------------------- project(GDCM - VERSION 3.0.10 + VERSION 3.0.22 LANGUAGES CXX C ) ## NOTE: the "DESCRIPTION" feature of project() was introduced in cmake 3.10.0 @@ -28,6 +28,7 @@ set(GDCM_MAJOR_VERSION ${GDCM_VERSION_MAJOR}) set(GDCM_MINOR_VERSION ${GDCM_VERSION_MINOR}) set(GDCM_BUILD_VERSION ${GDCM_VERSION_PATCH}) set(GDCM_VERSION "${GDCM_VERSION_MAJOR}.${GDCM_VERSION_MINOR}.${GDCM_VERSION_PATCH}") # ${GDCM_VERSION_TWEAK} +set(GDCM_SHORT_VERSION "${GDCM_VERSION_MAJOR}.${GDCM_VERSION_MINOR}") mark_as_advanced(CMAKE_BACKWARDS_COMPATIBILITY CMAKE_BUILD_TYPE CMAKE_INSTALL_PREFIX) set(GDCM_CMAKE_DIR "${GDCM_SOURCE_DIR}/CMake" CACHE INTERNAL "") @@ -133,6 +134,12 @@ if(NOT LIBRARY_OUTPUT_PATH) mark_as_advanced(LIBRARY_OUTPUT_PATH) endif() +# TODO: The following should be used for CMake 3 and beyond, +# EXECUTABLE_OUTPUT_PATH and LIBRARY_OUTPUT_PATH are deprecated +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH}) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${LIBRARY_OUTPUT_PATH}) + #----------------------------------------------------------------------------- # Adding GDCM_DATA_ROOT if(GDCM_STANDALONE) @@ -497,11 +504,14 @@ endif() #----------------------------------------------------------------------------- # Wrapping if(GDCM_STANDALONE) - option(GDCM_WRAP_PYTHON "build python wrapping" OFF) + option(GDCM_WRAP_PYTHON "build gdcm/python wrapping" OFF) + option(VTKGDCM_WRAP_PYTHON "build vtkgdcm/python wrapping" OFF) option(GDCM_WRAP_PERL "build perl wrapping (experimental !)" OFF) option(GDCM_WRAP_PHP "build php wrapping" OFF) - option(GDCM_WRAP_JAVA "build java wrapping" OFF) - option(GDCM_WRAP_CSHARP "build csharp wrapping" OFF) + option(GDCM_WRAP_JAVA "build gdcm/java wrapping" OFF) + option(VTKGDCM_WRAP_JAVA "build vtkgdcm/java wrapping" OFF) + option(GDCM_WRAP_CSHARP "build gdcm/csharp wrapping" OFF) + option(VTKGDCM_WRAP_CSHARP "build vtkgdcm/csharp wrapping" OFF) mark_as_advanced(GDCM_WRAP_PHP) mark_as_advanced(GDCM_WRAP_PERL) mark_as_advanced(GDCM_USE_ACTIVIZ) @@ -650,7 +660,96 @@ if(GDCM_STANDALONE) mark_as_advanced(VTK_DIR) set(GDCM_VTK_DIR ${VTK_DIR}) mark_as_advanced(GDCM_USE_PARAVIEW) - add_subdirectory(Utilities/VTK) + + set(VTKGDCM_NAME vtkgdcm CACHE STRING "vtk-gdcm lib name") + mark_as_advanced(VTKGDCM_NAME) + + if(VTK_VERSION VERSION_LESS 8.90) + add_subdirectory(Utilities/VTK) + else() + message(STATUS "Building Utilities/VTK as a VTK 9 Module") + # TODO: use VTKGDCM_NAME instead of vtkgdcm + + option(VTKGDCM_VERSIONED_INSTALL "Install with versioned names." ON) + mark_as_advanced(VTKGDCM_VERSIONED_INSTALL) + if(VTKGDCM_VERSIONED_INSTALL) + set(vtk_version_suffix "-${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION}") + set(vtkgdcm_library_suffix "${VTK_MAJOR_VERSION}.${VTK_MINOR_VERSION}") + else() + set(vtk_version_suffix "") + set(vtkgdcm_library_suffix "") + endif() + if(DEFINED GDCM_CUSTOM_LIBRARY_SUFFIX) + set(vtkgdcm_library_suffix "${GDCM_CUSTOM_LIBRARY_SUFFIX}") + endif() + + vtk_module_scan( + MODULE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/Utilities/VTK/vtkgdcm.module" + REQUEST_MODULES "GDCM::vtkgdcm" + PROVIDES_MODULES vtkgdcm_modules + ENABLE_TESTS "${GDCM_BUILD_TESTING}" + ) + + # documented at https://vtk.org/doc/nightly/html/group__module.html + vtk_module_build( + MODULES ${vtkgdcm_modules} + INSTALL_EXPORT GDCM + ARCHIVE_DESTINATION "${GDCM_INSTALL_LIB_DIR}" + HEADERS_DESTINATION "${GDCM_INSTALL_INCLUDE_DIR}/vtk${vtk_version_suffix}" + CMAKE_DESTINATION "${GDCM_INSTALL_PACKAGE_DIR}" + LICENSE_DESTINATION "${GDCM_INSTALL_DATA_DIR}/vtkgdcm-${GDCM_SHORT_VERSION}" + HIERARCHY_DESTINATION "${GDCM_INSTALL_LIB_DIR}/vtk${vtk_version_suffix}/hierarchy/vtkgdcm" + LIBRARY_NAME_SUFFIX "${vtkgdcm_library_suffix}" + VERSION "${GDCM_VERSION}" + SOVERSION "1" + # TODO: these are probably not set as they should be + #USE_EXTERNAL "${GDCM_USE_EXTERNAL}" + #TEST_DATA_TARGET vtkgdcmData + #TEST_INPUT_DATA_DIRECTORY "${vtkgdcm_test_data_directory_input}" + #TEST_OUTPUT_DATA_DIRECTORY "${vtkgdcm_test_data_directory_output}" + ) + + if(VTKGDCM_WRAP_PYTHON) + find_package(PythonInterp ${VTK_PYTHON_VERSION} QUIET) + + vtk_module_wrap_python( + MODULES ${vtkgdcm_modules} + TARGET GDCM::vtkgdcmpython + INSTALL_EXPORT vtkgdcmPython + PYTHON_PACKAGE "vtkgdcm" + CMAKE_DESTINATION "${GDCM_INSTALL_PACKAGE_DIR}" + LIBRARY_DESTINATION "${GDCM_INSTALL_LIB_DIR}" + MODULE_DESTINATION "${GDCM_VTK_INSTALL_PYTHONMODULE_DIR}" + SOABI "${Python${VTK_PYTHON_VERSION}_SOABI}" + BUILD_STATIC OFF + ) + + file(GENERATE + OUTPUT "${CMAKE_BINARY_DIR}/${GDCM_VTK_INSTALL_PYTHONMODULE_DIR}/vtkgdcm/__init__.py" + CONTENT "from .vtkgdcm import *\n\n__all__ = ['vtkgdcm']\n__version__ = \"${GDCM_VERSION}\"\n") + install( + FILES "${CMAKE_BINARY_DIR}/${GDCM_VTK_INSTALL_PYTHONMODULE_DIR}/vtkgdcm/__init__.py" + DESTINATION "${GDCM_VTK_INSTALL_PYTHONMODULE_DIR}/vtkgdcm/") + + export( + EXPORT vtkgdcmPython + NAMESPACE GDCM:: + FILE "${GDCM_INSTALL_PACKAGE_DIR}/vtkgdcmPython-targets.cmake") + install( + EXPORT vtkgdcmPython + NAMESPACE GDCM:: + FILE vtkgdcmPython-targets.cmake + DESTINATION "${GDCM_INSTALL_PACKAGE_DIR}") + endif() + + if(VTKGDCM_WRAP_JAVA) + # TODO: this is broken, incomplete, needs lots of work + vtk_module_wrap_java( + MODULES ${vtkgdcm_modules} + WRAPPED_MODULES vtkgdcm_java_wrapped_modules + JAVA_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles") + endif() + endif() endif() endif() @@ -805,11 +904,11 @@ if(GDCM_STANDALONE) # disabled for ITK distribution of gdcm if(GDCM_USE_VTK) foreach(comp ${components}) if( "${comp}" STREQUAL "PythonModule" ) - if(VTK_WRAP_PYTHON) + if(VTK_WRAP_PYTHON AND VTKGDCM_WRAP_PYTHON) list(APPEND components VTK${comp}) endif() elseif( "${comp}" STREQUAL "JavaModule" ) - if(VTK_WRAP_JAVA) + if(VTK_WRAP_JAVA AND VTKGDCM_WRAP_JAVA) list(APPEND components VTK${comp}) endif() else() diff --git a/Source/Common/CMakeLists.txt b/Source/Common/CMakeLists.txt index 16f2e638d53..d635692e687 100644 --- a/Source/Common/CMakeLists.txt +++ b/Source/Common/CMakeLists.txt @@ -62,8 +62,11 @@ CHECK_CXX_SOURCE_COMPILES( "int main() { const char *f = __FUNCTION__; return 0;}" GDCM_CXX_HAS_FUNCTION) CHECK_CXX_SOURCE_COMPILES( - "\#include \nint main() { const wchar_t fn[10] = {}; std::ifstream is( fn ); return 0;}" + "\#include \nint main() { const wchar_t fn[10] = {}; std::ifstream is( fn ); std::wcerr << fn; return 0;}" GDCM_HAVE_WCHAR_IFSTREAM) +CHECK_CXX_SOURCE_COMPILES( + "\#include \n#include \n#include \nint main() { std::u16string u16; std::string utf8 = std::wstring_convert, char16_t>{}.to_bytes(u16); }" + GDCM_HAVE_CODECVT) if(GDCM_USE_SYSTEM_OPENSSL) set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIR}) set(CMAKE_REQUIRED_LIBRARIES ${OPENSSL_LIBRARIES} @@ -74,6 +77,9 @@ CHECK_CXX_SOURCE_COMPILES( #HAVE_CMS_RECIPIENT_KEY) "\#include \nint main() { CMS_add0_recipient_password(0,0,0,0,0,0,0); return 0;}" GDCM_HAVE_CMS_RECIPIENT_PASSWORD) +CHECK_CXX_SOURCE_COMPILES( + "\#include \nint main() { const void*mem; int len; BIO_new_mem_buf(mem, len); }" + OPENSSL_HAS_CONST_VOID_BIO_NEW_MEM_BUF) endif() #----------------------------------------------------------------------------- @@ -164,6 +170,11 @@ set(Common_SRCS ${Common_SRCS} gdcmOpenSSLP7CryptoFactory.cxx gdcmOpenSSLP7CryptographicMessageSyntax.cxx ) +if(OPENSSL_HAS_CONST_VOID_BIO_NEW_MEM_BUF) +set_source_files_properties( + gdcmOpenSSLP7CryptographicMessageSyntax.cxx + PROPERTIES COMPILE_FLAGS "-DOPENSSL_HAS_CONST_VOID_BIO_NEW_MEM_BUF") +endif() endif() if(GDCM_USE_SYSTEM_OPENSSL AND GDCM_HAVE_CMS_RECIPIENT_PASSWORD) @@ -171,6 +182,11 @@ set(Common_SRCS ${Common_SRCS} gdcmOpenSSLCryptoFactory.cxx gdcmOpenSSLCryptographicMessageSyntax.cxx ) +if(OPENSSL_HAS_CONST_VOID_BIO_NEW_MEM_BUF) +set_source_files_properties( + gdcmOpenSSLCryptographicMessageSyntax.cxx + PROPERTIES COMPILE_FLAGS "-DOPENSSL_HAS_CONST_VOID_BIO_NEW_MEM_BUF") +endif() endif() if(GDCM_BUILD_TESTING) diff --git a/Source/Common/gdcmASN1.cxx b/Source/Common/gdcmASN1.cxx index ef5ab2573e5..afab05e02e6 100644 --- a/Source/Common/gdcmASN1.cxx +++ b/Source/Common/gdcmASN1.cxx @@ -14,7 +14,7 @@ #include "gdcmASN1.h" #include "gdcmSystem.h" -#include +#include #ifdef GDCM_USE_SYSTEM_OPENSSL #include diff --git a/Source/Common/gdcmBase64.cxx b/Source/Common/gdcmBase64.cxx index fbe2290acb4..8eac3481eb0 100644 --- a/Source/Common/gdcmBase64.cxx +++ b/Source/Common/gdcmBase64.cxx @@ -12,7 +12,7 @@ =========================================================================*/ #include "gdcmBase64.h" -#include // memcpy +#include // memcpy #include namespace gdcm diff --git a/Source/Common/gdcmConfigure.h.in b/Source/Common/gdcmConfigure.h.in index 8ac4b8d8a97..4a5d68f5660 100644 --- a/Source/Common/gdcmConfigure.h.in +++ b/Source/Common/gdcmConfigure.h.in @@ -117,6 +117,10 @@ // UTF-8 #cmakedefine GDCM_HAVE_WCHAR_IFSTREAM +// https://stackoverflow.com/questions/15615136/is-codecvt-not-a-std-header +// https://stackoverflow.com/questions/50867257/c-use-of-wstring-convert-on-linux +#cmakedefine GDCM_HAVE_CODECVT + #cmakedefine GDCM_FORCE_BIGENDIAN_EMULATION #ifndef GDCM_OVERRIDE_BROKEN_IMPLEMENTATION diff --git a/Source/Common/gdcmDirectory.cxx b/Source/Common/gdcmDirectory.cxx index 684b99605cf..cf87700de25 100644 --- a/Source/Common/gdcmDirectory.cxx +++ b/Source/Common/gdcmDirectory.cxx @@ -14,11 +14,11 @@ #include "gdcmDirectory.h" #include "gdcmTrace.h" +#include +#include +#include // strerror #include -#include -#include #include //stat function -#include // strerror #ifdef _MSC_VER #include @@ -65,8 +65,10 @@ unsigned int Directory::Explore(FilenameType const &name, bool recursive) std::wstring dirName = System::ConvertToUNC(name.c_str()); Directories.push_back(ToUtf8(dirName)); WIN32_FIND_DATAW fileData; - if ('\\' != dirName[dirName.size()-1]) dirName.push_back('\\'); - assert( '\\' == dirName[dirName.size()-1] ); + if ('\\' == dirName[dirName.size() - 1]) + dirName = dirName.substr(0, dirName.size() - 1); + if ('/' != dirName[dirName.size() - 1]) dirName.push_back('/'); + assert( '/' == dirName[dirName.size()-1] ); const std::wstring firstfile = dirName+L"*"; HANDLE hFile = FindFirstFileW(firstfile.c_str(), &fileData); diff --git a/Source/Common/gdcmEvent.h b/Source/Common/gdcmEvent.h index 9de2455717a..7f2c50dab64 100644 --- a/Source/Common/gdcmEvent.h +++ b/Source/Common/gdcmEvent.h @@ -49,7 +49,7 @@ public : }; /// Generic inserter operator for Event and its subclasses. -inline std::ostream& operator<<(std::ostream& os, Event &e) +inline std::ostream& operator<<(std::ostream& os, const Event &e) { e.Print(os); return os; @@ -71,7 +71,7 @@ inline std::ostream& operator<<(std::ostream& os, Event &e) { return dynamic_cast(e) ? true : false; } \ virtual ::gdcm::Event* MakeObject() const override \ { return new Self; } \ - classname(const Self&s) : super(s){}; \ + classname(const Self&s) : super(s){} \ private: \ void operator=(const Self&); \ } diff --git a/Source/Common/gdcmFileNameEvent.h b/Source/Common/gdcmFileNameEvent.h index 76cbcf4a401..8120debd51e 100644 --- a/Source/Common/gdcmFileNameEvent.h +++ b/Source/Common/gdcmFileNameEvent.h @@ -34,7 +34,7 @@ class FileNameEvent : public AnyEvent FileNameEvent(const char *s = ""):m_FileName(s) {} ~FileNameEvent() override = default; - FileNameEvent(const Self&s) : AnyEvent(s){}; + FileNameEvent(const Self&s) : AnyEvent(s){} void operator=(const Self&) = delete; diff --git a/Source/Common/gdcmFilename.cxx b/Source/Common/gdcmFilename.cxx index abfc1058d01..5384510dbff 100644 --- a/Source/Common/gdcmFilename.cxx +++ b/Source/Common/gdcmFilename.cxx @@ -12,10 +12,10 @@ =========================================================================*/ #include "gdcmFilename.h" -#include -#include // realpath -#include -#include +#include +#include +#include // realpath +#include namespace gdcm { @@ -28,7 +28,7 @@ const char *Filename::GetPath() { std::string fn = ToUnixSlashes(); - std::string::size_type slash_pos = fn.rfind("/"); + std::string::size_type slash_pos = fn.rfind('/'); if(slash_pos != std::string::npos) { Path = fn.substr(0, slash_pos); @@ -52,14 +52,14 @@ const char *Filename::GetName() #if defined(_WIN32) std::string::size_type slash_pos = filename.find_last_of("/\\"); #else - std::string::size_type slash_pos = filename.find_last_of("/"); + std::string::size_type slash_pos = filename.find_last_of('/'); #endif if(slash_pos != std::string::npos) { - return &FileName[0] + slash_pos + 1; + return FileName.data() + slash_pos + 1; } - return &FileName[0]; + return FileName.data(); } const char *Filename::ToWindowsSlashes() @@ -142,7 +142,7 @@ inline void Realpath(const char *path, std::string & resolved_path) const char *Filename::GetExtension() { std::string name = GetName(); - std::string::size_type dot_pos = name.rfind("."); + std::string::size_type dot_pos = name.rfind('.'); if(dot_pos != std::string::npos) { return GetName() + dot_pos; diff --git a/Source/Common/gdcmMD5.cxx b/Source/Common/gdcmMD5.cxx index 530743912ba..a4f985cee36 100644 --- a/Source/Common/gdcmMD5.cxx +++ b/Source/Common/gdcmMD5.cxx @@ -19,8 +19,12 @@ #elif defined(GDCM_BUILD_TESTING) #include "gdcm_md5.h" #endif +#include #include #include +#if defined(_MSC_VER) && (_MSC_VER < 1900) +#define snprintf _snprintf +#endif // http://stackoverflow.com/questions/13256446/compute-md5-hash-value-by-c-winapi namespace gdcm @@ -39,7 +43,7 @@ bool MD5::Compute(const char *buffer, size_t buf_len, char digest_str[33]) MD5_Update(&ctx, buffer, buf_len); MD5_Final(digest, &ctx); for (int di = 0; di < 16; ++di) - sprintf(digest_str+2*di, "%02x", digest[di]); + snprintf(digest_str+2*di, 3, "%02x", digest[di]); digest_str[2*16] = '\0'; return true; #elif defined(GDCM_BUILD_TESTING) @@ -49,7 +53,7 @@ bool MD5::Compute(const char *buffer, size_t buf_len, char digest_str[33]) md5_append(&state, (const md5_byte_t *)buffer, buf_len); md5_finish(&state, digest); for (int di = 0; di < 16; ++di) - sprintf(digest_str+2*di, "%02x", digest[di]); + snprintf(digest_str+2*di, 3, "%02x", digest[di]); digest_str[2*16] = '\0'; return true; #else @@ -90,7 +94,7 @@ static bool process_file(const char *filename, md5_byte_t *digest) const size_t file_size = System::FileSize(filename); std::vector v( file_size ); - char *buffer = &v[0]; + char *buffer = v.data(); file.read(buffer, file_size); md5_state_t state; @@ -124,7 +128,7 @@ bool MD5::ComputeFile(const char *filename, char digest_str[33]) for (int di = 0; di < 16; ++di) { - sprintf(digest_str+2*di, "%02x", digest[di]); + snprintf(digest_str+2*di, 3, "%02x", digest[di]); } digest_str[2*16] = '\0'; return true; diff --git a/Source/Common/gdcmOpenSSLCryptographicMessageSyntax.cxx b/Source/Common/gdcmOpenSSLCryptographicMessageSyntax.cxx index ac07b73620e..ffc9a9a9e40 100644 --- a/Source/Common/gdcmOpenSSLCryptographicMessageSyntax.cxx +++ b/Source/Common/gdcmOpenSSLCryptographicMessageSyntax.cxx @@ -97,7 +97,11 @@ bool OpenSSLCryptographicMessageSyntax::Encrypt(char *output, size_t &outlen, co goto err; } +#ifdef OPENSSL_HAS_CONST_VOID_BIO_NEW_MEM_BUF in = BIO_new_mem_buf((const void*)array, (int)len); +#else + in = BIO_new_mem_buf((void*)array, (int)len); +#endif if(!in) { gdcmErrorMacro( "Error at creating the input memory buffer." ); @@ -183,7 +187,11 @@ bool OpenSSLCryptographicMessageSyntax::Decrypt(char *output, size_t &outlen, co goto err; } +#ifdef OPENSSL_HAS_CONST_VOID_BIO_NEW_MEM_BUF in = BIO_new_mem_buf((const void*)array, (int)len); +#else + in = BIO_new_mem_buf((void*)array, (int)len); +#endif if (!in) { gdcmErrorMacro( "Error at creating the input memory buffer." ); diff --git a/Source/Common/gdcmOpenSSLP7CryptographicMessageSyntax.cxx b/Source/Common/gdcmOpenSSLP7CryptographicMessageSyntax.cxx index 640dadde2de..8e44d5041a2 100644 --- a/Source/Common/gdcmOpenSSLP7CryptographicMessageSyntax.cxx +++ b/Source/Common/gdcmOpenSSLP7CryptographicMessageSyntax.cxx @@ -153,7 +153,11 @@ class CryptographicMessageSyntaxInternals gdcmErrorMacro( "len is too big: " << len ); return false; } +#ifdef OPENSSL_HAS_CONST_VOID_BIO_NEW_MEM_BUF BIO *data = BIO_new_mem_buf((const void*)array, (int)len); +#else + BIO *data = BIO_new_mem_buf((void*)array, (int)len); +#endif if(!data) { gdcmErrorMacro( "BIO_new_mem_buf" ); @@ -308,7 +312,11 @@ bool OpenSSLP7CryptographicMessageSyntax::Decrypt(char *output, size_t &outlen, gdcmErrorMacro( "len is too big: " << len ); return false; } +#ifdef OPENSSL_HAS_CONST_VOID_BIO_NEW_MEM_BUF data = BIO_new_mem_buf((const void*)array, (int)len); +#else + data = BIO_new_mem_buf((void*)array, (int)len); +#endif if(!data) goto err; diff --git a/Source/Common/gdcmSHA1.cxx b/Source/Common/gdcmSHA1.cxx index f70d926b5cf..01b8163eb12 100644 --- a/Source/Common/gdcmSHA1.cxx +++ b/Source/Common/gdcmSHA1.cxx @@ -18,9 +18,9 @@ #include #endif -#include // memcmp -#include // malloc -#include // sprintf +#include // snprintf +#include // malloc +#include // memcmp /* */ @@ -62,7 +62,7 @@ bool SHA1::Compute(const char *buffer, unsigned long buf_len, char digest[]) for (int di = 0; di < 20; ++di) { - sprintf(digest+2*di, "%02x", output[di]); + snprintf(digest+2*di, 3, "%02x", output[di]); } digest[2*20] = '\0'; @@ -131,7 +131,7 @@ bool SHA1::ComputeFile(const char *filename, char digest_str[20*2+1]) for (int di = 0; di < 20; ++di) { - sprintf(digest_str+2*di, "%02x", digest[di]); + snprintf(digest_str+2*di, 3, "%02x", digest[di]); } digest_str[2*20] = '\0'; return true; diff --git a/Source/Common/gdcmSubject.cxx b/Source/Common/gdcmSubject.cxx index d32e4d6e614..df1191f9679 100644 --- a/Source/Common/gdcmSubject.cxx +++ b/Source/Common/gdcmSubject.cxx @@ -200,7 +200,7 @@ PrintObservers(std::ostream& os, std::string indent) const { const Event * e = (*i)->m_Event; const Command* c = (*i)->m_Command; (void)c; - os << indent << e->GetEventName() << "(" /*<< c->GetNameOfClass()*/ << ")\n"; + os << indent << e->GetEventName() << "(" /* << c->GetNameOfClass() */ << ")\n"; } return true; } diff --git a/Source/Common/gdcmSwapCode.cxx b/Source/Common/gdcmSwapCode.cxx index 65ded97ccd6..4d46f86351a 100644 --- a/Source/Common/gdcmSwapCode.cxx +++ b/Source/Common/gdcmSwapCode.cxx @@ -12,7 +12,7 @@ =========================================================================*/ #include "gdcmSwapCode.h" -#include +#include namespace gdcm { diff --git a/Source/Common/gdcmSwapCode.h b/Source/Common/gdcmSwapCode.h index 81530087835..5ca89442e72 100644 --- a/Source/Common/gdcmSwapCode.h +++ b/Source/Common/gdcmSwapCode.h @@ -22,7 +22,6 @@ namespace gdcm /** * \brief SwapCode representation - * \details */ class GDCM_EXPORT SwapCode { diff --git a/Source/Common/gdcmSwapper.txx b/Source/Common/gdcmSwapper.txx index fe32d6c2753..d63ccd5d799 100644 --- a/Source/Common/gdcmSwapper.txx +++ b/Source/Common/gdcmSwapper.txx @@ -133,7 +133,10 @@ namespace gdcm return tempF; } - template <> inline Tag SwapperNoOp::Swap(Tag val); + template <> inline Tag SwapperNoOp::Swap(Tag val) + { + return Tag( Swap(val.GetGroup()), Swap(val.GetElement()) ); + } template <> inline void SwapperNoOp::SwapArray(uint8_t *, size_t ) {} @@ -206,7 +209,10 @@ namespace gdcm return tempF; } - template <> inline Tag SwapperDoOp::Swap(Tag val); + template <> inline Tag SwapperDoOp::Swap(Tag val) + { + return Tag( Swap((uint32_t)val.GetElementTag()) ); + } template <> inline void SwapperDoOp::SwapArray(uint8_t *, size_t ) {} diff --git a/Source/Common/gdcmSystem.cxx b/Source/Common/gdcmSystem.cxx index fd60ce569f2..5d31526d088 100644 --- a/Source/Common/gdcmSystem.cxx +++ b/Source/Common/gdcmSystem.cxx @@ -20,23 +20,22 @@ #include #include -#include -#include -#include // strspn -#include -#include +#include +#include +#include // PATH_MAX +#include // snprintf +#include +#include // strspn #include -#include // PATH_MAX // gettimeofday #ifdef GDCM_HAVE_SYS_TIME_H #include #endif -#include +#include #ifdef GDCM_HAVE_WINSOCK_H #include #endif -#include // snprintf #if defined(_MSC_VER) && (_MSC_VER < 1900) #define snprintf _snprintf #endif @@ -229,7 +228,7 @@ bool System::FileIsDirectory(const char* name) if(stat(name, &fs) == 0) #endif { -#if _WIN32 +#ifdef _WIN32 return ((fs.st_mode & _S_IFDIR) != 0); #else return S_ISDIR(fs.st_mode); @@ -607,10 +606,10 @@ const char *System::GetCurrentResourcesDirectory() */ inline int getlastdigit(unsigned char *data, unsigned long size) { - int extended, carry = 0; + int carry = 0; for(unsigned int i=0;i -#include +#include #include +#include +#if defined(_MSC_VER) && (_MSC_VER < 1900) +#define snprintf _snprintf +#endif #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN @@ -75,12 +78,12 @@ class ConsoleImp void setbgcolor(int col) { bgcolor = col; } //std::string resettextcolor() const { // char command[13]; - // sprintf(command, "%c[%d;%d;%dm", 0x1B, 0, 0, 0); + // snprintf(command, sizeof(command), "%c[%d;%d;%dm", 0x1B, 0, 0, 0); // return command; //} std::string textcolor() const { char command[16]; - int n = sprintf(command, "%c[%d;%d;%dm", 0x1B, attribute, fgcolor + 30, bgcolor + 40); + int n = snprintf(command, sizeof(command), "%c[%d;%d;%dm", 0x1B, attribute, fgcolor + 30, bgcolor + 40); assert( n < 16 ); (void)n; return command; } diff --git a/Source/Common/gdcmTesting.cxx b/Source/Common/gdcmTesting.cxx index edca34a74d0..0460443bc64 100644 --- a/Source/Common/gdcmTesting.cxx +++ b/Source/Common/gdcmTesting.cxx @@ -16,8 +16,8 @@ #include "gdcmSystem.h" #include "gdcmMD5.h" -#include // strcmp -#include // malloc +#include // malloc +#include // strcmp namespace gdcm @@ -27,14 +27,14 @@ namespace gdcm #error how did that happen ? #endif -#include "gdcmDataFileNames.cxx" -#include "gdcmMD5DataImages.cxx" -#include "gdcmMD5DataBrokenImages.cxx" -#include "gdcmMediaStorageDataFiles.cxx" -#include "gdcmStreamOffsetDataFiles.cxx" +#include "gdcmDataFileNames.cxx" // NOLINT(bugprone-suspicious-include) +#include "gdcmMD5DataImages.cxx" // NOLINT(bugprone-suspicious-include) +#include "gdcmMD5DataBrokenImages.cxx" // NOLINT(bugprone-suspicious-include) +#include "gdcmMediaStorageDataFiles.cxx" // NOLINT(bugprone-suspicious-include) +#include "gdcmStreamOffsetDataFiles.cxx" // NOLINT(bugprone-suspicious-include) // After gdcmStreamOffsetDataFiles: -#include "gdcmSelectedTagsOffsetDataFiles.cxx" -#include "gdcmSelectedPrivateGroupOffsetDataFiles.cxx" +#include "gdcmSelectedTagsOffsetDataFiles.cxx" // NOLINT(bugprone-suspicious-include) +#include "gdcmSelectedPrivateGroupOffsetDataFiles.cxx" // NOLINT(bugprone-suspicious-include) bool Testing::ComputeMD5(const char *buffer, size_t buf_len, char digest_str[33]) @@ -451,6 +451,7 @@ static const LossyFile gdcmLossyFilenames[] = { { 0,"Bug_Siemens_PrivateIconNoItem.dcm" }, { 0,"HardcopyColor_YBR_RCT_J2K_PC1.dcm" }, { 0,"PET-GE-dicomwrite-PixelDataSQUNv2.dcm" }, +{ 0,"MEDILABValidCP246_EVRLESQasOB.dcm" }, { 0, nullptr } }; diff --git a/Source/Common/gdcmTesting.h b/Source/Common/gdcmTesting.h index b52c78e7a94..09d1eb8e0f9 100644 --- a/Source/Common/gdcmTesting.h +++ b/Source/Common/gdcmTesting.h @@ -31,8 +31,8 @@ namespace gdcm class GDCM_EXPORT Testing { public : - Testing() = default;; - ~Testing() = default;; + Testing() = default; + ~Testing() = default; /// MD5 stuff /// digest_str needs to be at least : strlen = [2*16+1]; diff --git a/Source/Common/gdcmUnpacker12Bits.cxx b/Source/Common/gdcmUnpacker12Bits.cxx index 93e0fcb2a3f..12e292d35e4 100644 --- a/Source/Common/gdcmUnpacker12Bits.cxx +++ b/Source/Common/gdcmUnpacker12Bits.cxx @@ -23,13 +23,12 @@ bool Unpacker12Bits::Unpack(char *out, const char *in, size_t n) short *q = (short*)(void*)out; const unsigned char *p = (const unsigned char*)in; const unsigned char *end = p+n; - unsigned char b0,b1,b2; while (p!=end) { - b0 = *p++; - b1 = *p++; - b2 = *p++; + unsigned char b0 = *p++; + unsigned char b1 = *p++; + unsigned char b2 = *p++; *q++ = (short)(((b1 & 0xf) << 8) + b0); *q++ = (short)((b1>>4) + (b2<<4)); } @@ -42,12 +41,11 @@ bool Unpacker12Bits::Pack(char *out, const char *in, size_t n) unsigned char *q = (unsigned char*)out; const unsigned short *p = (const unsigned short*)(const void*)in; const unsigned short *end = (const unsigned short*)(const void*)(in+n); - unsigned short b0,b1; while(p!=end) { - b0 = *p++; - b1 = *p++; + unsigned short b0 = *p++; + unsigned short b1 = *p++; *q++ = (unsigned char)(b0 & 0xff); *q++ = (unsigned char)((b0 >> 8) + ((b1 & 0xf) << 4)); diff --git a/Source/Common/gdcmUnpacker12Bits.h b/Source/Common/gdcmUnpacker12Bits.h index c2419c16072..b290028c816 100644 --- a/Source/Common/gdcmUnpacker12Bits.h +++ b/Source/Common/gdcmUnpacker12Bits.h @@ -20,10 +20,10 @@ namespace gdcm { /** * \brief Pack/Unpack 12 bits pixel into 16bits - * \details * \li You can only pack an even number of 16bits, which means a multiple of 4 (expressed in bytes) * \li You can only unpack a multiple of 3 bytes * + * \details * This class has no purpose in general purpose DICOM implementation. However * to be able to cope with some early ACR-NEMA file generated by a well-known * private vendor, one would need to unpack 12bits Stored Pixel Value into a diff --git a/Source/Common/zipstreamimpl.hpp b/Source/Common/zipstreamimpl.hpp index c0448904a7a..39781c56964 100644 --- a/Source/Common/zipstreamimpl.hpp +++ b/Source/Common/zipstreamimpl.hpp @@ -143,9 +143,7 @@ basic_zip_streambuf::overflow(int_type c) template std::streamsize basic_zip_streambuf::flush() { - std::streamsize written_byte_size = 0, total_written_byte_size = 0; - - size_t remainder = 0; + std::streamsize total_written_byte_size = 0; // updating crc _crc = crc32(_crc, _zip_stream.next_in, @@ -156,14 +154,15 @@ std::streamsize basic_zip_streambuf::flush() _err = deflate(&_zip_stream, Z_FINISH); if(_err == Z_OK || _err == Z_STREAM_END) { - written_byte_size = static_cast(_output_buffer.size()) - _zip_stream.avail_out; + std::streamsize written_byte_size = static_cast(_output_buffer.size()) - _zip_stream.avail_out; total_written_byte_size += written_byte_size; // output buffer is full, dumping to ostream _ostream.write( (const char_type*) &(_output_buffer[0]), static_cast(written_byte_size/sizeof(char_type)*sizeof(char))); // checking if some bytes were not written. - if((remainder = written_byte_size%sizeof(char_type)) != 0) + size_t remainder = written_byte_size%sizeof(char_type); + if(remainder != 0) { // copy to the beginning of the stream std::streamsize theDiff = written_byte_size-remainder; @@ -242,13 +241,12 @@ bool basic_zip_streambuf::zip_to_stream( char_type *buffer, std::streamsize buffer_size) { - std::streamsize written_byte_size = 0, total_written_byte_size = 0; + std::streamsize total_written_byte_size = 0; _zip_stream.next_in = (byte_buffer_type) buffer; _zip_stream.avail_in = static_cast(buffer_size * sizeof(char_type)); _zip_stream.avail_out = static_cast(_output_buffer.size()); _zip_stream.next_out = &_output_buffer[0]; - size_t remainder = 0; // updating crc _crc = crc32(_crc, _zip_stream.next_in, @@ -260,7 +258,7 @@ bool basic_zip_streambuf::zip_to_stream( if (_err == Z_OK || _err == Z_STREAM_END) { - written_byte_size= static_cast(_output_buffer.size()) - + std::streamsize written_byte_size = static_cast(_output_buffer.size()) - _zip_stream.avail_out; total_written_byte_size += written_byte_size; // output buffer is full, dumping to ostream @@ -269,7 +267,8 @@ bool basic_zip_streambuf::zip_to_stream( static_cast(written_byte_size / sizeof(char_type))); // checking if some bytes were not written. - if((remainder = written_byte_size % sizeof(char_type)) != 0) + size_t remainder = written_byte_size % sizeof(char_type); + if(remainder != 0) { // copy to the beginning of the stream std::streamsize theDiff = written_byte_size-remainder; @@ -285,6 +284,8 @@ bool basic_zip_streambuf::zip_to_stream( } while(_zip_stream.avail_in != 0 && _err == Z_OK); + (void)total_written_byte_size; + return _err == Z_OK; } diff --git a/Source/DataDictionary/CSAHeader.xml b/Source/DataDictionary/CSAHeader.xml index 94853663d5d..86150374f21 100644 --- a/Source/DataDictionary/CSAHeader.xml +++ b/Source/DataDictionary/CSAHeader.xml @@ -36,7 +36,7 @@ sKSpace.ucPhasePartialFourier = 0x10 --> - + @@ -70,9 +70,9 @@ sKSpace.ucPhasePartialFourier = 0x10 - + - + @@ -97,7 +97,7 @@ sKSpace.ucPhasePartialFourier = 0x10 - + @@ -146,7 +146,7 @@ sKSpace.ucPhasePartialFourier = 0x10 - + @@ -208,8 +208,8 @@ sKSpace.ucPhasePartialFourier = 0x10 - - + + diff --git a/Source/DataDictionary/ParseDicts.py b/Source/DataDictionary/ParseDicts.py index 76abe9e8a60..cfd39d08b12 100755 --- a/Source/DataDictionary/ParseDicts.py +++ b/Source/DataDictionary/ParseDicts.py @@ -124,7 +124,7 @@ def Open(self): #print "Other Full line:", s2 self.AddOutputLine(s2) else: - # we have a suspicioulsy long line, so what that could + # we have a suspiciously long line, so what that could # happen, let's check: if self.IsAFullLine(previousbuffer): self.AddOutputLine(previousbuffer) diff --git a/Source/DataDictionary/dicomhdr.html b/Source/DataDictionary/dicomhdr.html index 282af63d372..b4198994554 100644 --- a/Source/DataDictionary/dicomhdr.html +++ b/Source/DataDictionary/dicomhdr.html @@ -17,7 +17,7 @@

Image Attributes

Type VR VM -Descriptiom +Description Creator Unit @@ -164,7 +164,7 @@

Image Attributes

3 IS 1-n -References one or more image frames of a Multi-frame Image SOP Instance, identifying which frames are siginificantly related to this image +References one or more image frames of a Multi-frame Image SOP Instance, identifying which frames are significantly related to this image acquisition   @@ -204,7 +204,7 @@

Image Attributes

3 IS 1-n -References one or more image frames of a Multi-frame Image SOP Instance, identifying which frames are siginificantly related to this image +References one or more image frames of a Multi-frame Image SOP Instance, identifying which frames are significantly related to this image acquisition   @@ -357,7 +357,7 @@

Image Attributes

3 SH 1 -User defined name for the Scanning Sequence and Sequence Varaint combination +User defined name for the Scanning Sequence and Sequence Variant combination acquisition   @@ -380,7 +380,7 @@

Image Attributes

2C DS 1 -The period of time in msec between the beginning of a pulse sequence and the beginning of a succeeding (essentially identical) pulse sequence. Required except when Scanning Sequence is EP and Sequnece Variant is not segmented k-space +The period of time in msec between the beginning of a pulse sequence and the beginning of a succeeding (essentially identical) pulse sequence. Required except when Scanning Sequence is EP and Sequence Variant is not segmented k-space acquisition msec @@ -633,7 +633,7 @@

Image Attributes

3 IS 1 -Percent of R-R interval, based on Heart Rate (0018,1088), prescriped as a window for a valid/usable trigger +Percent of R-R interval, based on Heart Rate (0018,1088), prescribed as a window for a valid/usable trigger     @@ -1120,7 +1120,7 @@

Image Attributes

3 LO 1 -Manufacturer's seriel number of the equipment that produced the digital images +Manufacturer's serial number of the equipment that produced the digital images acquisition/application   @@ -1314,7 +1314,7 @@

Image Attributes

Example: channel 0: 00000001 channel 3: 00000111 -· +� acquisition   @@ -1436,7 +1436,7 @@

Image Attributes

1 UL 1 -Parameters used for acquisition, e.g. door open, interpolation, raw filter, Siemens seqence .... +Parameters used for acquisition, e.g. door open, interpolation, raw filter, Siemens sequence .... acquisition   @@ -1536,7 +1536,7 @@

Image Attributes

  DS 1 -Time delay after start of measurment +Time delay after start of measurement acquisition   @@ -1746,7 +1746,7 @@

Image Attributes

  SH 1 -User defined name for the Scanning Sequence and Sequence Varaint combination +User defined name for the Scanning Sequence and Sequence Variant combination acquisition   @@ -1756,7 +1756,7 @@

Image Attributes

  DS 1 -The period of time in msec between the beginning of a pulse sequence and the beginning of a succeeding (essentially identical) pulse sequence. Required except when Scanning Sequence is EP and Sequnece Variant is not segmented k-space +The period of time in msec between the beginning of a pulse sequence and the beginning of a succeeding (essentially identical) pulse sequence. Required except when Scanning Sequence is EP and Sequence Variant is not segmented k-space acquisition   @@ -2164,7 +2164,7 @@

Image Attributes

  UL 1 -Parameters used for acquisition, e.g. door open, interpolation, raw filter, Siemens seqence .· +Parameters used for acquisition, e.g. door open, interpolation, raw filter, Siemens sequence .� acquisition   diff --git a/Source/DataDictionary/gdcmCSAHeaderDefaultDicts.cxx b/Source/DataDictionary/gdcmCSAHeaderDefaultDicts.cxx index 71df6a16e3c..7d7cc0597c5 100644 --- a/Source/DataDictionary/gdcmCSAHeaderDefaultDicts.cxx +++ b/Source/DataDictionary/gdcmCSAHeaderDefaultDicts.cxx @@ -64,9 +64,9 @@ static const CSA_DICT_ENTRY CSAHeaderDataDict [] = { {"SequenceVariant","1",VR::CS,VM::VM1_n,"Variant of the Scanning Sequence"}, {"ScanOptions","2",VR::CS,VM::VM1_n,"Parameters of scanning sequence"}, {"MRAcquisitionType","2",VR::CS,VM::VM1,"Identification of date encoding scheme. Enumerated Values: 2D = frequency x phase 3D = frequency x phase x phase"}, - {"SequenceName","3",VR::SH,VM::VM1,"User defined name for the Scanning Sequence and Sequence Varaint combination"}, + {"SequenceName","3",VR::SH,VM::VM1,"User defined name for the Scanning Sequence and Sequence Variant combination"}, {"AngioFlag","3",VR::CS,VM::VM1,"Angio image indicator. Primary image for angio processing. Enumerated values: Y = image is Angio N = image is not Angio"}, - {"RepetitionTime","2C",VR::DS,VM::VM1,"The period of time in msec between the beginning of a pulse sequence and the beginning of a succeeding (essentially identical) pulse sequence. Required except when Scanning Sequence is EP and Sequnece Variant is not segmented k-space"}, + {"RepetitionTime","2C",VR::DS,VM::VM1,"The period of time in msec between the beginning of a pulse sequence and the beginning of a succeeding (essentially identical) pulse sequence. Required except when Scanning Sequence is EP and Sequence Variant is not segmented k-space"}, {"EchoTime","2",VR::DS,VM::VM1,"Time in msec between the middle of the excitation pulse and the peak of the echo produced. In the case of segmented k-space, the TE(eff) is the time between the middle of the excitation pulse to the peak of the echo that is used to cover the center of k-space)"}, {"InversionTime","2C",VR::DS,VM::VM1,"Time in msec after the middle of inverting RF pulse to middle of excitation pulse to detect the amount of longitudinal magnetization. Required if Scanning Sequence has value of IR"}, {"NumberOfAverages","3",VR::DS,VM::VM1,"Number of times a given pulse sequence is repeated before any parameter has changed"}, @@ -91,7 +91,7 @@ static const CSA_DICT_ENTRY CSAHeaderDataDict [] = { {"Skip Beats","3",VR::IS,VM::VM1,"Number of beats skipped after a detected arrhythmia"}, {"HeartRate","3",VR::IS,VM::VM1,"Beats per minute"}, {"CardiacNumberOfImages","3",VR::IS,VM::VM1,"Number of imagesb per cardiac cycle"}, - {"TriggerWindow","3",VR::IS,VM::VM1,"Percent of R-R interval, based on Heart Rate (0018,1088), prescriped as a window for a valid/usable trigger"}, + {"TriggerWindow","3",VR::IS,VM::VM1,"Percent of R-R interval, based on Heart Rate (0018,1088), prescribed as a window for a valid/usable trigger"}, {"ReconstructionDiameter","3",VR::DS,VM::VM1,"Diameter in mm of the region from within which data were used in creating the reconstruction of the image. Data may exist outside this region and portions of the patient may exist outside the region"}, {"Receive Coil","3",VR::SH,VM::VM1,"Received coil used"}, {"TransmittingCoil","3",VR::SH,VM::VM1,"Transmitted coil used"}, @@ -134,7 +134,7 @@ static const CSA_DICT_ENTRY CSAHeaderDataDict [] = { {"InstitutionName","3",VR::LO,VM::VM1,"Institution where the equipment is located that produced the digital images"}, {"InstitutionAddress","3",VR::ST,VM::VM1,"Mailing address of the institution where the equipment is located that produced the digital images"}, {"ManufacturersModelName","3",VR::LO,VM::VM1,"Manufacturer's model number of the equipment that produced the digital images"}, - {"DeviceSerialNumber","3",VR::LO,VM::VM1,"Manufacturer's seriel number of the equipment that produced the digital images"}, + {"DeviceSerialNumber","3",VR::LO,VM::VM1,"Manufacturer's serial number of the equipment that produced the digital images"}, {"SoftwareVersions","3",VR::LO,VM::VM1_n,"Manufacturer's designation of software of the equipment that produced the digital images"}, {"OverlayRows","1",VR::US,VM::VM1,"Number of Rows in Overlay"}, {"OverlayColumns","1",VR::US,VM::VM1,"Number of Columns in Overlay"}, @@ -192,8 +192,8 @@ static const CSA_DICT_ENTRY CSAHeaderDataDict [] = { {"ReferencedImageSequence","1",VR::UI,VM::VM1_n,"A sequence which provides reference to a set of Image SOP Class/Instance identifying other images significantly related to this image (localizer images)"}, //{"PatientOrientation","1",VR::CS,VM::VM1,"Patient direction of the rows and columns of the image. Not required for MR images"}, {"ScanningSequence","1",VR::CS,VM::VM1_n,"Description of the type of data taken. Enumerated values: SE = Spin Echo; IR = Inversion Recovery; GR = Gradient Recalled; EP = Echo Planar; RM = Research Mode"}, - //{"SequenceName","1",VR::SH,VM::VM1,"User defined name for the Scanning Sequence and Sequence Varaint combination"}, - //{"RepetitionTime","1",VR::DS,VM::VM1,"The period of time in msec between the beginning of a pulse sequence and the beginning of a succeeding (essentially identical) pulse sequence. Required except when Scanning Sequence is EP and Sequnece Variant is not segmented k-space"}, + //{"SequenceName","1",VR::SH,VM::VM1,"User defined name for the Scanning Sequence and Sequence Variant combination"}, + //{"RepetitionTime","1",VR::DS,VM::VM1,"The period of time in msec between the beginning of a pulse sequence and the beginning of a succeeding (essentially identical) pulse sequence. Required except when Scanning Sequence is EP and Sequence Variant is not segmented k-space"}, //{"EchoTime","1",VR::DS,VM::VM1,"Time in msec between the middle of the excitation pulse and the peak of the echo produced. In the case of segmented k-space, the TE(eff) is the time between the middle of the excitation pulse to the peak of the echo that is used to cover the center of k-space)"}, //{"InversionTime","1",VR::DS,VM::VM1,"Time in msec after the middle of inverting RF pulse to middle of excitation pulse to detect the amount of longitudinal magnetization. Required if Scanning Sequence has value of IR"}, //{"NumberOfAverages","1",VR::DS,VM::VM1,"Number of averages"}, diff --git a/Source/DataDictionary/gdcmDefaultGroupNames.cxx b/Source/DataDictionary/gdcmDefaultGroupNames.cxx index c269eacf53d..c66b675382e 100644 --- a/Source/DataDictionary/gdcmDefaultGroupNames.cxx +++ b/Source/DataDictionary/gdcmDefaultGroupNames.cxx @@ -41,7 +41,7 @@ static GROUP_ENTRY groupname[] = { {0x0019,"SPIA","SPI Acquisition"}, {0x0020,"IMG","Image"}, {0x0021,"SPIIM","SPI Image"}, - {0x0022,"OPHY","Ophtalmology"}, + {0x0022,"OPHY","Ophthalmology"}, {0x0028,"IMGP","Image Presentation"}, {0x0032,"SDY","Study"}, {0x0038,"VIS","Visit"}, diff --git a/Source/DataDictionary/gdcmDictConverter.cxx b/Source/DataDictionary/gdcmDictConverter.cxx index 1cdc73900bd..9792abec61d 100644 --- a/Source/DataDictionary/gdcmDictConverter.cxx +++ b/Source/DataDictionary/gdcmDictConverter.cxx @@ -226,7 +226,7 @@ bool DictConverter::Readuint16(const char *raw, uint16_t &ov) int r = sscanf(raw, "%04x", &v); assert( r == 1 && "Wrong Value read for uint16"); char sv[4+1]; - r = sprintf(sv, "%04x", v); + r = snprintf(sv, sizeof(sv), "%04x", v); assert( r == 4 && "Wrong Value printed for uint16"); assert( strncmp(raw, sv, 4) == 0 ); ov = v; diff --git a/Source/DataDictionary/gdcmGlobal.cxx b/Source/DataDictionary/gdcmGlobal.cxx index 927a020e790..60051a1fed3 100644 --- a/Source/DataDictionary/gdcmGlobal.cxx +++ b/Source/DataDictionary/gdcmGlobal.cxx @@ -16,8 +16,8 @@ #include "gdcmDefs.h" #include "gdcmFilename.h" -#include // PATH_MAX -#include // strcpy +#include // PATH_MAX +#include // strcpy #ifdef _WIN32 #include // MAX_PATH #endif @@ -27,7 +27,7 @@ namespace gdcm // Must NOT be initialized. Default initialization to zero is // necessary. -unsigned int GlobalCount; +static unsigned int GlobalCount; class GlobalInternal { diff --git a/Source/DataDictionary/gdcmPrivateDefaultDicts.cxx b/Source/DataDictionary/gdcmPrivateDefaultDicts.cxx index 5ad041b9366..c72b61dbf30 100644 --- a/Source/DataDictionary/gdcmPrivateDefaultDicts.cxx +++ b/Source/DataDictionary/gdcmPrivateDefaultDicts.cxx @@ -38,6 +38,575 @@ using DICT_ENTRY = struct }; static const DICT_ENTRY DICOMV3DataDict [] = { + {0x0021,0x0010,"SIEMENS MR FMRI",VR::SQ,VM::VM1,"?",false }, + {0x0021,0x0011,"SIEMENS MR FMRI",VR::LO,VM::VM1,"?",false }, + {0x0021,0x0012,"SIEMENS MR FMRI",VR::SQ,VM::VM1,"?",false }, + {0x0021,0x0013,"SIEMENS MR FMRI",VR::US,VM::VM1,"?",false }, + {0x0021,0x0014,"SIEMENS MR FMRI",VR::SQ,VM::VM1,"?",false }, + {0x0021,0x0015,"SIEMENS MR FMRI",VR::US,VM::VM1,"?",false }, + {0x0021,0x0016,"SIEMENS MR FMRI",VR::LO,VM::VM1,"?",false }, + {0x0021,0x0017,"SIEMENS MR FMRI",VR::US,VM::VM1,"?",false }, + {0x0021,0x0018,"SIEMENS MR FMRI",VR::UL,VM::VM1,"?",false }, + {0x0021,0x0019,"SIEMENS MR FMRI",VR::FL,VM::VM1,"?",false }, + {0x0021,0x0031,"SIEMENS MR FMRI",VR::SQ,VM::VM1,"?",false }, + {0x0021,0x0040,"SIEMENS MR FMRI",VR::SQ,VM::VM1,"?",false }, + {0x0021,0x0041,"SIEMENS MR FMRI",VR::LO,VM::VM1,"?",false }, + {0x0021,0x0042,"SIEMENS MR FMRI",VR::SQ,VM::VM1,"?",false }, + {0x0021,0x0043,"SIEMENS MR FMRI",VR::LO,VM::VM1,"?",false }, + {0x0021,0x0044,"SIEMENS MR FMRI",VR::US,VM::VM1,"?",false }, + {0x0021,0x0045,"SIEMENS MR FMRI",VR::LO,VM::VM1_n,"?",false }, + {0x0021,0x0046,"SIEMENS MR FMRI",VR::SQ,VM::VM1,"?",false }, + {0x0021,0x0047,"SIEMENS MR FMRI",VR::UL,VM::VM1,"?",false }, + {0x0021,0x0048,"SIEMENS MR FMRI",VR::LO,VM::VM1,"?",false }, + {0x0021,0x0049,"SIEMENS MR FMRI",VR::FD,VM::VM1,"?",false }, + {0x0021,0x004a,"SIEMENS MR FMRI",VR::FD,VM::VM1_n,"?",false }, + {0x0021,0x004b,"SIEMENS MR FMRI",VR::FL,VM::VM1,"?",false }, + {0x0009,0x0002,"CANON_MEC_MR3^10",VR::SH,VM::VM1,"?",false }, + {0x0011,0x0003,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0011,0x0004,"CANON_MEC_MR3^10",VR::SQ,VM::VM1,"?",false }, + {0x0011,0x0005,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0011,0x0006,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0011,0x0007,"CANON_MEC_MR3^10",VR::UL,VM::VM1_n,"?",false }, + {0x0011,0x0008,"CANON_MEC_MR3^10",VR::SH,VM::VM1,"?",false }, + {0x0011,0x000c,"CANON_MEC_MR3^10",VR::SS,VM::VM1,"?",false }, + {0x0011,0x000e,"CANON_MEC_MR3^10",VR::US,VM::VM2,"?",false }, + {0x0019,0x0000,"CANON_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0001,"CANON_MEC_MR3^11",VR::OB,VM::VM1,"?",false }, + {0x0019,0x0001,"CANON_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0001,"CANON_MEC_MR3^10",VR::UL,VM::VM1,"?",false }, + {0x0019,0x0002,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0002,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0002,"CANON_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0002,"CANON_MEC_MR3^13",VR::US,VM::VM1,"?",false }, + {0x0019,0x0003,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0003,"CANON_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0003,"CANON_MEC_MR3^13",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0003,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x0004,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0004,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0004,"CANON_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0004,"CANON_MEC_MR3^13",VR::US,VM::VM1,"?",false }, + {0x0019,0x0005,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0005,"CANON_MEC_MR3^12",VR::SH,VM::VM1,"?",false }, + {0x0019,0x0005,"CANON_MEC_MR3^13",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0006,"CANON_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0006,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0007,"CANON_MEC_MR3^10",VR::FL,VM::VM3,"?",false }, + {0x0019,0x0007,"CANON_MEC_MR3^12",VR::UL,VM::VM1,"?",false }, + {0x0019,0x0008,"CANON_MEC_MR3^11",VR::SH,VM::VM1,"?",false }, + {0x0019,0x0008,"CANON_MEC_MR3^13",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0008,"CANON_MEC_MR3^12",VR::UL,VM::VM1,"?",false }, + {0x0019,0x0008,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x0009,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0009,"CANON_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0009,"CANON_MEC_MR3^11",VR::SL,VM::VM2,"?",false }, + {0x0019,0x0009,"CANON_MEC_MR3^13",VR::SQ,VM::VM1,"?",false }, + {0x0019,0x000a,"CANON_MEC_MR3^13",VR::FD,VM::VM3,"?",false }, + {0x0019,0x000a,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x000a,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x000a,"CANON_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, + {0x0019,0x000b,"CANON_MEC_MR3^13",VR::FD,VM::VM1,"?",false }, + {0x0019,0x000b,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x000b,"CANON_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, + {0x0019,0x000c,"CANON_MEC_MR3^13",VR::FD,VM::VM1,"?",false }, + {0x0019,0x000c,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x000c,"CANON_MEC_MR3^12",VR::UL,VM::VM1,"?",false }, + {0x0019,0x000c,"CANON_MEC_MR3^10",VR::US,VM::VM3,"?",false }, + {0x0019,0x000d,"CANON_MEC_MR3^10",VR::SL,VM::VM6,"?",false }, + {0x0019,0x000d,"CANON_MEC_MR3^12",VR::SQ,VM::VM1,"?",false }, + {0x0019,0x000e,"CANON_MEC_MR3^10",VR::SL,VM::VM6,"?",false }, + {0x0019,0x000e,"CANON_MEC_MR3^12",VR::US,VM::VM1,"?",false }, + {0x0019,0x000f,"CANON_MEC_MR3^13",VR::SH,VM::VM1,"?",false }, + {0x0019,0x000f,"CANON_MEC_MR3^10",VR::SL,VM::VM6,"?",false }, + {0x0019,0x0010,"CANON_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0010,"CANON_MEC_MR3^10",VR::US,VM::VM2,"?",false }, + {0x0019,0x0011,"CANON_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0011,"CANON_MEC_MR3^10",VR::SL,VM::VM2,"?",false }, + {0x0019,0x0012,"CANON_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0012,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x0013,"CANON_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0013,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0014,"CANON_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0014,"CANON_MEC_MR3^13",VR::SH,VM::VM1,"?",false }, + {0x0019,0x0014,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x0015,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0016,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0017,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0018,"CANON_MEC_MR3^12",VR::UL,VM::VM1,"?",false }, + {0x0019,0x0018,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x0019,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0019,"CANON_MEC_MR3^11",VR::SQ,VM::VM1,"?",false }, + {0x0019,0x0019,"CANON_MEC_MR3^13",VR::US,VM::VM1,"?",false }, + {0x0019,0x001a,"CANON_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x001a,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x001b,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x001b,"CANON_MEC_MR3^13",VR::US,VM::VM1,"?",false }, + {0x0019,0x001c,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x001d,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x001e,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x001f,"CANON_MEC_MR3^13",VR::US,VM::VM1,"?",false }, + {0x0019,0x0022,"CANON_MEC_MR3^13",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0024,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0025,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0026,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0027,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0028,"CANON_MEC_MR3^12",VR::DS,VM::VM1,"?",false }, + {0x0019,0x0028,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0028,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0029,"CANON_MEC_MR3^10",VR::SH,VM::VM1,"?",false }, + {0x0019,0x0029,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x002a,"CANON_MEC_MR3^12",VR::DS,VM::VM3,"?",false }, + {0x0019,0x002a,"CANON_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x002a,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x002b,"CANON_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x002b,"CANON_MEC_MR3^10",VR::SH,VM::VM1,"?",false }, + {0x0019,0x002b,"CANON_MEC_MR3^12",VR::SQ,VM::VM1,"?",false }, + {0x0019,0x002c,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x002c,"CANON_MEC_MR3^11",VR::SL,VM::VM3,"?",false }, + {0x0019,0x002d,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x002d,"CANON_MEC_MR3^11",VR::SL,VM::VM3,"?",false }, + {0x0019,0x002e,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x002e,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x002f,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0030,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0030,"CANON_MEC_MR3^10",VR::UL,VM::VM1,"?",false }, + {0x0019,0x0031,"CANON_MEC_MR3^10",VR::OF,VM::VM1_n,"?",false }, + {0x0019,0x0031,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0032,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0032,"CANON_MEC_MR3^12",VR::SH,VM::VM1,"?",false }, + {0x0019,0x0032,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0033,"CANON_MEC_MR3^10",VR::SL,VM::VM3,"?",false }, + {0x0019,0x0034,"CANON_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0034,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0034,"CANON_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0035,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0035,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0036,"CANON_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0036,"CANON_MEC_MR3^10",VR::SQ,VM::VM1,"?",false }, + {0x0019,0x0037,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0038,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0038,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0039,"CANON_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0039,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x003a,"CANON_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x003a,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x003b,"CANON_MEC_MR3^10",VR::SL,VM::VM2,"?",false }, + {0x0019,0x003c,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x003d,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x003d,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x003e,"CANON_MEC_MR3^11",VR::FL,VM::VM9,"?",false }, + {0x0019,0x003e,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x003f,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x003f,"CANON_MEC_MR3^11",VR::UI,VM::VM1,"?",false }, + {0x0019,0x0040,"CANON_MEC_MR3^11",VR::US,VM::VM1,"?",false }, + {0x0019,0x0041,"CANON_MEC_MR3^11",VR::US,VM::VM1,"?",false }, + {0x0019,0x0042,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0042,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x0043,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0043,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x0044,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0044,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0045,"CANON_MEC_MR3^10",VR::SS,VM::VM1,"?",false }, + {0x0019,0x0046,"CANON_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0046,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x0047,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0048,"CANON_MEC_MR3^11",VR::LT,VM::VM1,"?",false }, + {0x0019,0x0048,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x0049,"CANON_MEC_MR3^11",VR::LT,VM::VM1,"?",false }, + {0x0019,0x0049,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x004b,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x004c,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x004c,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x004d,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x004e,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x004e,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x004f,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x0050,"CANON_MEC_MR3^10",VR::SL,VM::VM2,"?",false }, + {0x0019,0x0051,"CANON_MEC_MR3^10",VR::SL,VM::VM2,"?",false }, + {0x0019,0x0052,"CANON_MEC_MR3^12",VR::FL,VM::VM2,"?",false }, + {0x0019,0x0052,"CANON_MEC_MR3^10",VR::LO,VM::VM1,"?",false }, + {0x0019,0x0054,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x0055,"CANON_MEC_MR3^11",VR::LO,VM::VM1,"?",false }, + {0x0019,0x0055,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x0056,"CANON_MEC_MR3^10",VR::FL,VM::VM3,"?",false }, + {0x0019,0x0057,"CANON_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0057,"CANON_MEC_MR3^10",VR::FL,VM::VM3,"?",false }, + {0x0019,0x0058,"CANON_MEC_MR3^10",VR::FL,VM::VM3,"?",false }, + {0x0019,0x0058,"CANON_MEC_MR3^11",VR::US,VM::VM1,"?",false }, + {0x0019,0x0059,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0059,"CANON_MEC_MR3^11",VR::US,VM::VM1,"?",false }, + {0x0019,0x005a,"CANON_MEC_MR3^10",VR::FL,VM::VM1_n,"?",false }, + {0x0019,0x005d,"CANON_MEC_MR3^10",VR::FL,VM::VM1_n,"?",false }, + {0x0019,0x005d,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x005e,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x005e,"CANON_MEC_MR3^11",VR::US,VM::VM1,"?",false }, + {0x0019,0x005f,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x005f,"CANON_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0060,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0060,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x0061,"CANON_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0061,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x0062,"CANON_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0062,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x0063,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0063,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0065,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0065,"CANON_MEC_MR3^10",VR::SL,VM::VM2,"?",false }, + {0x0019,0x0066,"CANON_MEC_MR3^11",VR::SL,VM::VM6,"?",false }, + {0x0019,0x0068,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0069,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x006a,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x006b,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x006b,"CANON_MEC_MR3^11",VR::SL,VM::VM6,"?",false }, + {0x0019,0x006d,"CANON_MEC_MR3^11",VR::SH,VM::VM1,"?",false }, + {0x0019,0x006d,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x006e,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x006e,"CANON_MEC_MR3^11",VR::SH,VM::VM1,"?",false }, + {0x0019,0x006f,"CANON_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x006f,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0070,"CANON_MEC_MR3^10",VR::LO,VM::VM1,"?",false }, + {0x0019,0x0071,"CANON_MEC_MR3^10",VR::LO,VM::VM1,"?",false }, + {0x0019,0x0071,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0072,"CANON_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0073,"CANON_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0073,"CANON_MEC_MR3^10",VR::LO,VM::VM1,"?",false }, + {0x0019,0x0075,"CANON_MEC_MR3^10",VR::LO,VM::VM1,"?",false }, + {0x0019,0x0076,"CANON_MEC_MR3^10",VR::LO,VM::VM1,"?",false }, + {0x0019,0x0076,"CANON_MEC_MR3^12",VR::OB,VM::VM1,"?",false }, + {0x0019,0x0077,"CANON_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0078,"CANON_MEC_MR3^10",VR::LO,VM::VM1,"?",false }, + {0x0019,0x0078,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0079,"CANON_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0079,"CANON_MEC_MR3^12",VR::SQ,VM::VM1,"?",false }, + {0x0019,0x007a,"CANON_MEC_MR3^11",VR::SL,VM::VM2,"?",false }, + {0x0019,0x007b,"CANON_MEC_MR3^10",VR::LO,VM::VM1,"?",false }, + {0x0019,0x007c,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x007c,"CANON_MEC_MR3^11",VR::FL,VM::VM3,"?",false }, + {0x0019,0x007d,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x007d,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x007e,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x007e,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x007f,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x007f,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0080,"CANON_MEC_MR3^12",VR::FD,VM::VM1,"?",false }, + {0x0019,0x0080,"CANON_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0083,"CANON_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0085,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0086,"CANON_MEC_MR3^12",VR::LO,VM::VM1,"?",false }, + {0x0019,0x0086,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0087,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0087,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0087,"CANON_MEC_MR3^12",VR::SQ,VM::VM1,"?",false }, + {0x0019,0x0088,"CANON_MEC_MR3^10",VR::LO,VM::VM1,"?",false }, + {0x0019,0x0088,"CANON_MEC_MR3^12",VR::US,VM::VM1,"?",false }, + {0x0019,0x0089,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0089,"CANON_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, + {0x0019,0x008a,"CANON_MEC_MR3^10",VR::SL,VM::VM1_n,"?",false }, + {0x0019,0x008a,"CANON_MEC_MR3^11",VR::US,VM::VM1,"?",false }, + {0x0019,0x008a,"CANON_MEC_MR3^12",VR::US,VM::VM1,"?",false }, + {0x0019,0x008b,"CANON_MEC_MR3^12",VR::US,VM::VM1,"?",false }, + {0x0019,0x008c,"CANON_MEC_MR3^10",VR::UL,VM::VM1,"?",false }, + {0x0019,0x008d,"CANON_MEC_MR3^10",VR::TM,VM::VM1,"?",false }, + {0x0019,0x008e,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x008f,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0092,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0092,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0093,"CANON_MEC_MR3^10",VR::FL,VM::VM3,"?",false }, + {0x0019,0x0093,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0093,"CANON_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0094,"CANON_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0094,"CANON_MEC_MR3^12",VR::UI,VM::VM1,"?",false }, + {0x0019,0x0095,"CANON_MEC_MR3^12",VR::UI,VM::VM1,"?",false }, + {0x0019,0x0096,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x0097,"CANON_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0098,"CANON_MEC_MR3^12",VR::FL,VM::VM3,"?",false }, + {0x0019,0x0099,"CANON_MEC_MR3^12",VR::LO,VM::VM1,"?",false }, + {0x0019,0x009a,"CANON_MEC_MR3^12",VR::DS,VM::VM1,"?",false }, + {0x0019,0x009a,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x009b,"CANON_MEC_MR3^10",VR::FL,VM::VM3,"?",false }, + {0x0019,0x009b,"CANON_MEC_MR3^12",VR::IS,VM::VM1,"?",false }, + {0x0019,0x009b,"CANON_MEC_MR3^11",VR::US,VM::VM1,"?",false }, + {0x0019,0x009c,"CANON_MEC_MR3^12",VR::DS,VM::VM1,"?",false }, + {0x0019,0x009c,"CANON_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x009c,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x009d,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x009d,"CANON_MEC_MR3^12",VR::US,VM::VM1,"?",false }, + {0x0019,0x009e,"CANON_MEC_MR3^12",VR::FL,VM::VM3,"?",false }, + {0x0019,0x009e,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x009f,"CANON_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, + {0x0019,0x009f,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00a0,"CANON_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00a0,"CANON_MEC_MR3^10",VR::SL,VM::VM4,"?",false }, + {0x0019,0x00a1,"CANON_MEC_MR3^10",VR::DS,VM::VM1,"?",false }, + {0x0019,0x00a1,"CANON_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00a1,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00a2,"CANON_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00a2,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00a2,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00a3,"CANON_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00a3,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00a3,"CANON_MEC_MR3^10",VR::SL,VM::VM3,"?",false }, + {0x0019,0x00a4,"CANON_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00a4,"CANON_MEC_MR3^10",VR::FL,VM::VM3,"?",false }, + {0x0019,0x00a5,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00a5,"CANON_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00a5,"CANON_MEC_MR3^11",VR::US,VM::VM1,"?",false }, + {0x0019,0x00a6,"CANON_MEC_MR3^12",VR::FL,VM::VM2_2n,"?",false }, + {0x0019,0x00a6,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00a6,"CANON_MEC_MR3^11",VR::US,VM::VM1,"?",false }, + {0x0019,0x00a7,"CANON_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00a8,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00a8,"CANON_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00a8,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00a9,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00aa,"CANON_MEC_MR3^12",VR::FL,VM::VM3,"?",false }, + {0x0019,0x00ab,"CANON_MEC_MR3^10",VR::FL,VM::VM3,"?",false }, + {0x0019,0x00ab,"CANON_MEC_MR3^12",VR::FL,VM::VM3,"?",false }, + {0x0019,0x00ac,"CANON_MEC_MR3^12",VR::FL,VM::VM3,"?",false }, + {0x0019,0x00ac,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x00ad,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00ad,"CANON_MEC_MR3^12",VR::FL,VM::VM3,"?",false }, + {0x0019,0x00ad,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00ae,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00ae,"CANON_MEC_MR3^12",VR::FL,VM::VM3,"?",false }, + {0x0019,0x00ae,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00af,"CANON_MEC_MR3^12",VR::FL,VM::VM3,"?",false }, + {0x0019,0x00af,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00b0,"CANON_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00b0,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00b1,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00b1,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00b2,"CANON_MEC_MR3^11",VR::US,VM::VM1,"?",false }, + {0x0019,0x00b3,"CANON_MEC_MR3^12",VR::FD,VM::VM1,"?",false }, + {0x0019,0x00b3,"CANON_MEC_MR3^11",VR::US,VM::VM1,"?",false }, + {0x0019,0x00b4,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00b4,"CANON_MEC_MR3^11",VR::US,VM::VM1,"?",false }, + {0x0019,0x00b5,"CANON_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00b5,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00b6,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00b6,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00b7,"CANON_MEC_MR3^10",VR::FL,VM::VM2,"?",false }, + {0x0019,0x00b7,"CANON_MEC_MR3^11",VR::US,VM::VM1,"?",false }, + {0x0019,0x00b9,"CANON_MEC_MR3^11",VR::US,VM::VM1,"?",false }, + {0x0019,0x00ba,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00bb,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00bb,"CANON_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00bc,"CANON_MEC_MR3^10",VR::FL,VM::VM2,"?",false }, + {0x0019,0x00bc,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00bd,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00bd,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00be,"CANON_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00be,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00bf,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00c0,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00c1,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00c1,"CANON_MEC_MR3^11",VR::US,VM::VM1,"?",false }, + {0x0019,0x00c2,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00c2,"CANON_MEC_MR3^12",VR::US,VM::VM1,"?",false }, + {0x0019,0x00c3,"CANON_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00c3,"CANON_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00c3,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00c4,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00c4,"CANON_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00c5,"CANON_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00c6,"CANON_MEC_MR3^10",VR::FL,VM::VM2,"?",false }, + {0x0019,0x00c6,"CANON_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00c7,"CANON_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00c9,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00ca,"CANON_MEC_MR3^10",VR::LO,VM::VM1,"?",false }, + {0x0019,0x00cb,"CANON_MEC_MR3^10",VR::UL,VM::VM1,"?",false }, + {0x0019,0x00cc,"CANON_MEC_MR3^10",VR::UL,VM::VM1,"?",false }, + {0x0019,0x00cd,"CANON_MEC_MR3^12",VR::LO,VM::VM1,"?",false }, + {0x0019,0x00cd,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00cd,"CANON_MEC_MR3^11",VR::SL,VM::VM3,"?",false }, + {0x0019,0x00ce,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00ce,"CANON_MEC_MR3^12",VR::UL,VM::VM1,"?",false }, + {0x0019,0x00cf,"CANON_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00cf,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00d0,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x00d1,"CANON_MEC_MR3^12",VR::FL,VM::VM3,"?",false }, + {0x0019,0x00d1,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00d2,"CANON_MEC_MR3^10",VR::SL,VM::VM3,"?",false }, + {0x0019,0x00d2,"CANON_MEC_MR3^12",VR::US,VM::VM3,"?",false }, + {0x0019,0x00d3,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00d3,"CANON_MEC_MR3^12",VR::SS,VM::VM1,"?",false }, + {0x0019,0x00d4,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00d4,"CANON_MEC_MR3^12",VR::US,VM::VM2,"?",false }, + {0x0019,0x00d5,"CANON_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00d6,"CANON_MEC_MR3^12",VR::FL,VM::VM3,"?",false }, + {0x0019,0x00d7,"CANON_MEC_MR3^12",VR::US,VM::VM2,"?",false }, + {0x0019,0x00d8,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x00d9,"CANON_MEC_MR3^10",VR::SQ,VM::VM1,"?",false }, + {0x0019,0x00da,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x00db,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00dc,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00de,"CANON_MEC_MR3^12",VR::US,VM::VM1,"?",false }, + {0x0019,0x00df,"CANON_MEC_MR3^12",VR::US,VM::VM1,"?",false }, + {0x0019,0x00e0,"CANON_MEC_MR3^12",VR::US,VM::VM1,"?",false }, + {0x0019,0x00e1,"CANON_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00e1,"CANON_MEC_MR3^12",VR::FL,VM::VM3,"?",false }, + {0x0019,0x00e1,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00e2,"CANON_MEC_MR3^12",VR::FL,VM::VM3,"?",false }, + {0x0019,0x00e3,"CANON_MEC_MR3^11",VR::SL,VM::VM3,"?",false }, + {0x0019,0x00e3,"CANON_MEC_MR3^12",VR::TM,VM::VM1,"?",false }, + {0x0019,0x00e4,"CANON_MEC_MR3^11",VR::DS,VM::VM1,"?",false }, + {0x0019,0x00e4,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00e4,"CANON_MEC_MR3^12",VR::US,VM::VM2,"?",false }, + {0x0019,0x00e5,"CANON_MEC_MR3^10",VR::SQ,VM::VM1,"?",false }, + {0x0019,0x00e5,"CANON_MEC_MR3^11",VR::SQ,VM::VM1,"?",false }, + {0x0019,0x00e6,"CANON_MEC_MR3^10",VR::SQ,VM::VM1,"?",false }, + {0x0019,0x00e6,"CANON_MEC_MR3^11",VR::SQ,VM::VM1,"?",false }, + {0x0019,0x00e9,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00ea,"CANON_MEC_MR3^10",VR::UI,VM::VM1,"?",false }, + {0x0019,0x00eb,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00eb,"CANON_MEC_MR3^12",VR::US,VM::VM1,"?",false }, + {0x0019,0x00ec,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x00ec,"CANON_MEC_MR3^12",VR::US,VM::VM1,"?",false }, + {0x0019,0x00ee,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00ef,"CANON_MEC_MR3^12",VR::DS,VM::VM1,"?",false }, + {0x0019,0x00ef,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00f0,"CANON_MEC_MR3^12",VR::LO,VM::VM1,"?",false }, + {0x0019,0x00f0,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00f1,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00f1,"CANON_MEC_MR3^12",VR::LO,VM::VM1,"?",false }, + {0x0019,0x00f1,"CANON_MEC_MR3^11",VR::SL,VM::VM3,"?",false }, + {0x0019,0x00f2,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00f2,"CANON_MEC_MR3^11",VR::FL,VM::VM3,"?",false }, + {0x0019,0x00f3,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00f3,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00f4,"CANON_MEC_MR3^10",VR::FD,VM::VM1,"?",false }, + {0x0019,0x00f4,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00f5,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00f5,"CANON_MEC_MR3^11",VR::SQ,VM::VM1,"?",false }, + {0x0019,0x00f6,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00f6,"CANON_MEC_MR3^10",VR::UI,VM::VM1,"?",false }, + {0x0019,0x00f7,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00f8,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00f8,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x00f9,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00f9,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00fa,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00fa,"CANON_MEC_MR3^12",VR::LT,VM::VM1,"?",false }, + {0x0019,0x00fa,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00fb,"CANON_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00fb,"CANON_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00fb,"CANON_MEC_MR3^10",VR::UL,VM::VM1,"?",false }, + {0x0019,0x00fc,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00fc,"CANON_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00fc,"CANON_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00fd,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00fd,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00fd,"CANON_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00fe,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00fe,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00fe,"CANON_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00ff,"CANON_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00ff,"CANON_MEC_MR3^10",VR::SL,VM::VM3,"?",false }, + {0x0021,0x0002,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0021,0x0003,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0021,0x0004,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0021,0x0008,"CANON_MEC_MR3^10",VR::DS,VM::VM3,"?",false }, + {0x0021,0x0009,"CANON_MEC_MR3^10",VR::DS,VM::VM3,"?",false }, + {0x0021,0x000a,"CANON_MEC_MR3^10",VR::DS,VM::VM3,"?",false }, + {0x0021,0x000b,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0021,0x000c,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0021,0x000d,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0021,0x000f,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0021,0x0012,"CANON_MEC_MR3^10",VR::DS,VM::VM3,"?",false }, + {0x0021,0x0014,"CANON_MEC_MR3^10",VR::SQ,VM::VM1,"?",false }, + {0x0021,0x0015,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0021,0x0016,"CANON_MEC_MR3^10",VR::FL,VM::VM2,"?",false }, + {0x0021,0x0018,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0021,0x001d,"CANON_MEC_MR3^10",VR::IS,VM::VM1,"?",false }, + {0x0021,0x001f,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0021,0x0022,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0021,0x0023,"CANON_MEC_MR3^10",VR::SS,VM::VM1,"?",false }, + {0x0029,0x0001,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0029,0x0005,"CANON_MEC_MR3^10",VR::SQ,VM::VM1,"?",false }, + {0x0029,0x0006,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0029,0x0007,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0029,0x001c,"CANON_MEC_MR3^10",VR::FL,VM::VM2,"?",false }, + {0x0029,0x0021,"CANON_MEC_MR3^10",VR::SL,VM::VM3,"?",false }, + {0x0029,0x004e,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0029,0x0050,"CANON_MEC_MR3^10",VR::LO,VM::VM1,"?",false }, + {0x0029,0x0051,"CANON_MEC_MR3^10",VR::LO,VM::VM1,"?",false }, + {0x0029,0x0052,"CANON_MEC_MR3^10",VR::LO,VM::VM1,"?",false }, + {0x0029,0x0054,"CANON_MEC_MR3^10",VR::LO,VM::VM1,"?",false }, + {0x0029,0x0067,"CANON_MEC_MR3^10",VR::FD,VM::VM4,"?",false }, + {0x0029,0x0068,"CANON_MEC_MR3^10",VR::SS,VM::VM1,"?",false }, + {0x0029,0x006e,"CANON_MEC_MR3^10",VR::OB,VM::VM1,"?",false }, + {0x0029,0x0001,"CANON_MEC_MR3",VR::SQ,VM::VM1,"Other Private Data",false }, + {0x0029,0x0089,"CANON_MEC_MR3",VR::LO,VM::VM1,"?",false }, + {0x0029,0x0090,"CANON_MEC_MR3",VR::OB,VM::VM1,"Reversed EVRLE DataSet",false }, + {0x700d,0x0000,"CANON_MEC_MR3",VR::DS,VM::VM1,"Scale Factor",false }, + {0x700d,0x0005,"CANON_MEC_MR3",VR::DS,VM::VM4,"FOV",false }, + {0x700d,0x000c,"CANON_MEC_MR3",VR::CS,VM::VM1,"Receiver Gain Correction Check Flag",false }, + {0x700d,0x0020,"CANON_MEC_MR3",VR::SH,VM::VM1,"Identification Flag of 3D GDC",false }, + {0x700d,0x0010,"CANON_MEC_MR3^10",VR::DS,VM::VM1,"2nd Flip Angle [degree]",false }, + {0x700d,0x0011,"CANON_MEC_MR3^10",VR::US,VM::VM2,"Acquisition Inner Matrix",false }, + {0x700d,0x0012,"CANON_MEC_MR3^10",VR::US,VM::VM1,"MP2RAGE Flag",false }, + {0x700d,0x0013,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"Inversion efficiency of inversion recovery pulse",false }, + {0x700d,0x0014,"CANON_MEC_MR3^10",VR::SL,VM::VM1,"Number of dummy shot",false }, + {0x700d,0x0015,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"FFE total repetition time[s]",false }, + {0x700d,0x0016,"CANON_MEC_MR3^10",VR::LO,VM::VM3,"PAS Name",false }, + {0x700d,0x0017,"CANON_MEC_MR3^10",VR::LT,VM::VM1,"Intended Processing",false }, + {0x700d,0x0018,"CANON_MEC_MR3^10",VR::SS,VM::VM1,"Scanned Orientation IDs",false }, + {0x700d,0x0019,"CANON_MEC_MR3^10",VR::OB,VM::VM1,"PAS Reproduct Information",false }, + {0x700d,0x001a,"CANON_MEC_MR3^10",VR::DS,VM::VM1,"ASTAR Inversion Time",false }, + {0x700d,0x001b,"CANON_MEC_MR3^10",VR::DS,VM::VM1,"Saturation Recovery Time",false }, + {0xe201,0x0002,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0xe301,0x0000,"CANON_MEC_MR3^10",VR::SH,VM::VM1,"?",false }, + {0xe401,0x0000,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0xe401,0x0001,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0xe401,0x0002,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0xe401,0x0003,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0xe401,0x0004,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0xe401,0x0005,"CANON_MEC_MR3^10",VR::OB,VM::VM1,"?",false }, + {0xe401,0x0007,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0xe401,0x0008,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0xe401,0x0012,"CANON_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0xe401,0x0013,"CANON_MEC_MR3^10",VR::OB,VM::VM1,"?",false }, + {0xe401,0x0020,"CANON_MEC_MR3^10",VR::SQ,VM::VM1,"?",false }, + {0xe401,0x0021,"CANON_MEC_MR3^10",VR::SQ,VM::VM1,"?",false }, + {0xe401,0x0022,"CANON_MEC_MR3^10",VR::LO,VM::VM1,"?",false }, + {0xe401,0x0023,"CANON_MEC_MR3^10",VR::SH,VM::VM1,"?",false }, + {0xe401,0x0024,"CANON_MEC_MR3^10",VR::OB,VM::VM1,"?",false }, + {0xe403,0x0000,"CANON_MEC_MR3^13",VR::SH,VM::VM1,"?",false }, + {0xe403,0x0000,"CANON_MEC_MR3^10",VR::SQ,VM::VM1,"?",false }, + {0xe403,0x0001,"CANON_MEC_MR3^13",VR::OB,VM::VM1,"?",false }, + {0xe403,0x0002,"CANON_MEC_MR3^13",VR::OB,VM::VM1,"?",false }, + {0xe403,0x0003,"CANON_MEC_MR3^13",VR::OB,VM::VM1,"?",false }, + {0xee01,0x0000,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0xee01,0x0001,"CANON_MEC_MR3^10",VR::OB,VM::VM1,"?",false }, + {0xee01,0x0002,"CANON_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x6001,0x0003,"Merge eFilm Fusion",VR::CS,VM::VM1,"?",false }, + {0x6001,0x0030,"Merge eFilm Fusion",VR::US,VM::VM1,"?",false }, + {0x6001,0x0032,"Merge eFilm Fusion",VR::US,VM::VM1,"?",false }, + {0x0031,0x0000,"GEMS_MRPT_01",VR::SH,VM::VM1,"?",false }, + {0x0027,0x0001,"SIEMENS SYNGO ENHANCED IDATASET API",VR::CS,VM::VM1,"Business Unit Code",false }, + {0x0027,0x0002,"SIEMENS SYNGO ENHANCED IDATASET API",VR::LO,VM::VM1,"Application Type",false }, + {0x0027,0x0003,"SIEMENS SYNGO ENHANCED IDATASET API",VR::SQ,VM::VM1,"Application Attributes Sequence",false }, + {0x0021,0x0001,"SIEMENS MR IMA",VR::SQ,VM::VM1,"?",false }, + {0x0071,0x0002,"SIEMENS MED PT MU MAP",VR::UI,VM::VM1,"?",false }, + {0x0071,0x0021,"Visage",VR::UT,VM::VM1,"?",false }, + {0x0071,0x0022,"Visage",VR::DT,VM::VM1,"?",false }, + {0x0009,0x008c,"SIEMENS SYNGO INDEX SERVICE",VR::LO,VM::VM1,"?",false }, + {0x0009,0x0000,"MORPHING REPLAY INFO",VR::UN,VM::VM1,"?",false }, // wtf: VR is SQ but contains non-SQ nested sub-elements... + {0x0029,0x0031,"FujiFILM TM",VR::SQ,VM::VM1,"? PHI found ?",false }, // + {0x7fd9,0x0060,"agfa/studyUpdate",VR::DT,VM::VM1,"?",false }, + {0x7fdd,0x0013,"agfa/originalStudyUID",VR::UI,VM::VM1,"?",false }, // most likely UI ?? + {0x7fdb,0x0012,"agfa/seriesHeader",VR::UN,VM::VM1,"?",false }, + {0x7fdb,0x0053,"agfa/seriesHeader",VR::UN,VM::VM1,"?",false }, + {0x7fdb,0x0054,"agfa/seriesHeader",VR::UN,VM::VM1,"?",false }, + {0x7fdb,0x0055,"agfa/seriesHeader",VR::UN,VM::VM1,"?",false }, + {0x7fdd,0x0042,"Thinking Systems Private Creator",VR::UL,VM::VM1,"?",false }, + {0x7fdd,0x0093,"Thinking Systems Private Creator",VR::LO,VM::VM1,"?",false }, + {0x7fdd,0x0094,"Thinking Systems Private Creator",VR::LO,VM::VM1,"?",false }, + {0x7fdd,0x0097,"Thinking Systems Private Creator",VR::LO,VM::VM1,"?",false }, + {0x0025,0x0001,"SIEMENS MR EXTRACTED CSA HEADER",VR::SQ,VM::VM1,"?",false }, + {0x0025,0x0002,"SIEMENS MR EXTRACTED CSA HEADER",VR::LO,VM::VM1,"?",false }, + {0x0025,0x0003,"SIEMENS MR EXTRACTED CSA HEADER",VR::AT,VM::VM1,"?",false }, + {0x0025,0x0004,"SIEMENS MR EXTRACTED CSA HEADER",VR::SS,VM::VM1,"?",false }, {0x0009,0x0002,"TOSHIBA_MEC_MR3^10",VR::SH,VM::VM1,"?",false }, {0x0011,0x0003,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0011,0x0004,"TOSHIBA_MEC_MR3^10",VR::SQ,VM::VM1,"?",false }, @@ -46,6 +615,7 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0011,0x0007,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1_n,"?",false }, {0x0011,0x0008,"TOSHIBA_MEC_MR3^10",VR::SH,VM::VM1,"?",false }, {0x0011,0x000c,"TOSHIBA_MEC_MR3^10",VR::SS,VM::VM1,"?",false }, + {0x0011,0x000e,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM2,"?",false }, {0x0019,0x0000,"TOSHIBA_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, {0x0019,0x0001,"TOSHIBA_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, {0x0019,0x0001,"TOSHIBA_MEC_MR3^10",VR::UL,VM::VM1,"?",false }, @@ -103,6 +673,7 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0019,0x0013,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, {0x0019,0x0013,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0014,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0014,"TOSHIBA_MEC_MR3^13",VR::SH,VM::VM1,"?",false }, {0x0019,0x0014,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0015,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0016,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, @@ -111,13 +682,25 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0019,0x0018,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0019,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0019,"TOSHIBA_MEC_MR3^11",VR::SQ,VM::VM1,"?",false }, + {0x0019,0x0019,"TOSHIBA_MEC_MR3^13",VR::US,VM::VM1,"?",false }, {0x0019,0x001a,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0019,0x001b,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x001b,"TOSHIBA_MEC_MR3^13",VR::US,VM::VM1,"?",false }, {0x0019,0x001c,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x001d,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x001e,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x001f,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x001f,"TOSHIBA_MEC_MR3^13",VR::US,VM::VM1,"?",false }, + {0x0019,0x0020,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM2,"?",false }, + {0x0019,0x0021,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x0022,"TOSHIBA_MEC_MR3^13",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0022,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM2,"?",false }, + {0x0019,0x0023,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0024,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x0024,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0025,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x0025,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0026,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0026,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0027,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0028,"TOSHIBA_MEC_MR3^12",VR::DS,VM::VM1,"?",false }, @@ -186,6 +769,7 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0019,0x004c,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x004c,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0019,0x004d,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x004d,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x004e,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x004e,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0019,0x004f,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, @@ -231,14 +815,17 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0019,0x006e,"TOSHIBA_MEC_MR3^11",VR::SH,VM::VM1,"?",false }, {0x0019,0x006f,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x006f,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0070,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x0070,"TOSHIBA_MEC_MR3^10",VR::LO,VM::VM1,"?",false }, {0x0019,0x0071,"TOSHIBA_MEC_MR3^10",VR::LO,VM::VM1,"?",false }, {0x0019,0x0071,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0072,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0073,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x0073,"TOSHIBA_MEC_MR3^10",VR::LO,VM::VM1,"?",false }, {0x0019,0x0075,"TOSHIBA_MEC_MR3^10",VR::LO,VM::VM1,"?",false }, {0x0019,0x0076,"TOSHIBA_MEC_MR3^10",VR::LO,VM::VM1,"?",false }, {0x0019,0x0076,"TOSHIBA_MEC_MR3^12",VR::OB,VM::VM1,"?",false }, + {0x0019,0x0077,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x0078,"TOSHIBA_MEC_MR3^10",VR::LO,VM::VM1,"?",false }, {0x0019,0x0078,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0079,"TOSHIBA_MEC_MR3^12",VR::SQ,VM::VM1,"?",false }, @@ -254,6 +841,7 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0019,0x007f,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0080,"TOSHIBA_MEC_MR3^12",VR::FD,VM::VM1,"?",false }, {0x0019,0x0080,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0083,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x0084,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0085,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x0085,"TOSHIBA_MEC_MR3^12",VR::US,VM::VM1,"?",false }, @@ -268,8 +856,11 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0019,0x008a,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1_n,"?",false }, {0x0019,0x008a,"TOSHIBA_MEC_MR3^11",VR::US,VM::VM1,"?",false }, {0x0019,0x008a,"TOSHIBA_MEC_MR3^12",VR::US,VM::VM1,"?",false }, + {0x0019,0x008b,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x008b,"TOSHIBA_MEC_MR3^12",VR::US,VM::VM1,"?",false }, + {0x0019,0x008c,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x008c,"TOSHIBA_MEC_MR3^10",VR::UL,VM::VM1,"?",false }, + {0x0019,0x008d,"TOSHIBA_MEC_MR3^10",VR::TM,VM::VM1,"?",false }, {0x0019,0x008e,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x008f,"TOSHIBA_MEC_MR3^12",VR::OB,VM::VM1,"?",false }, {0x0019,0x008f,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, @@ -287,6 +878,7 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0019,0x009a,"TOSHIBA_MEC_MR3^12",VR::DS,VM::VM1,"?",false }, {0x0019,0x009a,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x009b,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM3,"?",false }, + {0x0019,0x009b,"TOSHIBA_MEC_MR3^12",VR::IS,VM::VM1,"?",false }, {0x0019,0x009b,"TOSHIBA_MEC_MR3^11",VR::US,VM::VM1,"?",false }, {0x0019,0x009c,"TOSHIBA_MEC_MR3^12",VR::DS,VM::VM1,"?",false }, {0x0019,0x009c,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, @@ -322,6 +914,7 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0019,0x00aa,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM3,"?",false }, {0x0019,0x00ab,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM3,"?",false }, {0x0019,0x00ab,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM3,"?",false }, + {0x0019,0x00ab,"TOSHIBA_MEC_MR3^11",VR::US,VM::VM1,"?",false }, {0x0019,0x00ac,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM3,"?",false }, {0x0019,0x00ac,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0019,0x00ad,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, @@ -343,6 +936,7 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0019,0x00b4,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00b4,"TOSHIBA_MEC_MR3^11",VR::US,VM::VM1,"?",false }, {0x0019,0x00b5,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00b5,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00b6,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00b6,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00b7,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM2,"?",false }, @@ -448,11 +1042,13 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0019,0x00f9,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00f9,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00fa,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00fa,"TOSHIBA_MEC_MR3^12",VR::LT,VM::VM1,"?",false }, {0x0019,0x00fa,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00fb,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x00fb,"TOSHIBA_MEC_MR3^10",VR::UL,VM::VM1,"?",false }, {0x0019,0x00fc,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x00fc,"TOSHIBA_MEC_MR3^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00fc,"TOSHIBA_MEC_MR3^12",VR::FL,VM::VM1,"?",false }, {0x0019,0x00fd,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x00fd,"TOSHIBA_MEC_MR3^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00fd,"TOSHIBA_MEC_MR3^12",VR::SL,VM::VM1,"?",false }, @@ -476,9 +1072,11 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0021,0x0015,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0x0021,0x0016,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM2,"?",false }, {0x0021,0x0018,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0021,0x001a,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0021,0x001d,"TOSHIBA_MEC_MR3^10",VR::IS,VM::VM1,"?",false }, {0x0021,0x001f,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0021,0x0022,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, + {0x0021,0x0023,"TOSHIBA_MEC_MR3^10",VR::SS,VM::VM1,"?",false }, {0x0029,0x0001,"TOSHIBA_MEC_MR3^10",VR::SL,VM::VM1,"?",false }, {0x0029,0x0005,"TOSHIBA_MEC_MR3^10",VR::SQ,VM::VM1,"?",false }, {0x0029,0x0006,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, @@ -513,6 +1111,7 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0xe401,0x0003,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0xe401,0x0004,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0xe401,0x0005,"TOSHIBA_MEC_MR3^10",VR::OB,VM::VM1,"?",false }, + {0xe401,0x0007,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0xe401,0x0008,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0xe401,0x0012,"TOSHIBA_MEC_MR3^10",VR::FL,VM::VM1,"?",false }, {0xe401,0x0013,"TOSHIBA_MEC_MR3^10",VR::OB,VM::VM1,"?",false }, @@ -531,7 +1130,7 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0xee01,0x0002,"TOSHIBA_MEC_MR3^10",VR::US,VM::VM1,"?",false }, {0x0029,0x0001,"TOSHIBA_MEC_MR3",VR::SQ,VM::VM1,"Other Private Data",false}, {0x0029,0x0002,"TOSHIBA_MEC_MR3",VR::SQ,VM::VM1,"Other Private Data 2",false}, - {0x0029,0x0090,"TOSHIBA_MEC_MR3",VR::OB,VM::VM1,"Private Data Binary",false}, + {0x0029,0x0090,"TOSHIBA_MEC_MR3",VR::OB,VM::VM1,"Reversed EVRLE DataSet",false}, {0x7fdf,0x0050,"TomTec",VR::OB,VM::VM1,"Bookmark Information",false}, {0x7fdf,0x0051,"TomTec",VR::OB,VM::VM1,"Bookmark Content",false}, {0x2013,0x0010,"BioDICOMizer",VR::LO,VM::VM1,"Custom Storage Version",false}, @@ -571,12 +1170,13 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0071,0x0024,"SIEMENS MED PT",VR::CS,VM::VM1,"Table Motion",false}, {0x0021,0x0001,"SIEMENS MR SDR 01",VR::LO,VM::VM1,"??",false}, {0x0021,0x0001,"SIEMENS MR SDS 01",VR::IS,VM::VM1,"??",false}, - {0x0021,0x0002,"SIEMENS MR SDR 01",VR::LO,VM::VM1,"??",false}, + {0x0021,0x0002,"SIEMENS MR SDR 01",VR::LO,VM::VM1_n,"??",false}, + {0x0021,0x0003,"SIEMENS MR SDR 01",VR::LO,VM::VM1,"?",false}, {0x0021,0x0003,"SIEMENS MR SDI 02",VR::DS,VM::VM1,"FrameAcquisitionDuration",false}, {0x0021,0x0004,"SIEMENS MR SDI 02",VR::DS,VM::VM1,"??",false}, {0x0021,0x0004,"SIEMENS MR SDS 01",VR::DS,VM::VM1,"??",false}, - {0x0021,0x0005,"SIEMENS MR SDS 01",VR::IS,VM::VM3,"??",false}, {0x0021,0x0005,"SIEMENS MR SDI 02",VR::IS,VM::VM1,"ICE_Dims",false}, + {0x0021,0x0005,"SIEMENS MR SDS 01",VR::IS,VM::VM3,"??",false}, {0x0021,0x0006,"SIEMENS MR SDI 02",VR::LO,VM::VM1,"ICE_Dims",false}, {0x0021,0x0006,"SIEMENS MR SDS 01",VR::LO,VM::VM1,"CoilForGradient",false}, {0x0021,0x0007,"SIEMENS MR SDS 01",VR::LO,VM::VM1,"LongModelName",false}, @@ -594,16 +1194,17 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0021,0x0016,"SIEMENS MR SDS 01",VR::DS,VM::VM1,"??",false}, {0x0021,0x0017,"SIEMENS MR SDS 01",VR::DS,VM::VM1,"??",false}, {0x0021,0x0018,"SIEMENS MR SDS 01",VR::SH,VM::VM1,"?RFSWDMostCriticalAspect?",false}, - {0x0021,0x0019,"SIEMENS MR SDS 01",VR::OW,VM::VM1,"PhoenixMetaProtocol",false}, - {0x0021,0x001a,"SIEMENS MR SDS 01",VR::LO,VM::VM1,"??",false}, + {0x0021,0x0019,"SIEMENS MR SDS 01",VR::OB,VM::VM1,"PhoenixMetaProtocol",false}, {0x0021,0x001a,"SIEMENS MR SDI 02",VR::SH,VM::VM1,"?RFSWDDataType?",false}, + {0x0021,0x001a,"SIEMENS MR SDS 01",VR::LO,VM::VM1,"??",false}, {0x0021,0x001b,"SIEMENS MR SDS 01",VR::DS,VM::VM1,"??",false}, {0x0021,0x001c,"SIEMENS MR SDI 02",VR::IS,VM::VM1,"??",false}, {0x0021,0x001c,"SIEMENS MR SDS 01",VR::DS,VM::VM3,"??",false}, {0x0021,0x001d,"SIEMENS MR SDS 01",VR::IS,VM::VM1,"??",false}, + {0x0021,0x0021,"SIEMENS MR SDI 02",VR::CS,VM::VM1,"?DiffusionDirectionality?",false}, {0x0021,0x0022,"SIEMENS MR SDS 01",VR::SH,VM::VM1,"Manufacturer",false}, + {0x0021,0x0023,"SIEMENS MR SDI 02",VR::FD,VM::VM6,"?",false }, {0x0021,0x0023,"SIEMENS MR SDS 01",VR::IS,VM::VM1,"??",false}, - {0x0021,0x0021,"SIEMENS MR SDI 02",VR::CS,VM::VM1,"?DiffusionDirectionality?",false}, {0x0021,0x0024,"SIEMENS MR SDI 02",VR::IS,VM::VM1,"??",false}, {0x0021,0x0025,"SIEMENS MR SDS 01",VR::SL,VM::VM3,"?ImaAbsTablePosition?",false}, {0x0021,0x0026,"SIEMENS MR SDS 01",VR::IS,VM::VM1_n,"?MiscSequenceParam?",false}, @@ -618,54 +1219,69 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0021,0x0031,"SIEMENS MR SDS 01",VR::IS,VM::VM1,"PtabAbsStartPosZ",false}, {0x0021,0x0032,"SIEMENS MR SDS 01",VR::SS,VM::VM1,"??",false}, {0x0021,0x0033,"SIEMENS MR SDI 02",VR::IS,VM::VM1,"?CoilForGradient2?",false}, - {0x0021,0x0035,"SIEMENS MR SDI 02",VR::IS,VM::VM1,"??",false}, {0x0021,0x0033,"SIEMENS MR SDS 01",VR::SH,VM::VM1,"??",false}, {0x0021,0x0034,"SIEMENS MR SDS 01",VR::DS,VM::VM1,"??",false}, + {0x0021,0x0035,"SIEMENS MR SDI 02",VR::IS,VM::VM1,"??",false}, {0x0021,0x0035,"SIEMENS MR SDS 01",VR::DS,VM::VM1,"??",false}, {0x0021,0x0036,"SIEMENS MR SDS 01",VR::DS,VM::VM1,"??",false}, {0x0021,0x0037,"SIEMENS MR SDS 01",VR::SH,VM::VM1,"??",false}, {0x0021,0x0038,"SIEMENS MR SDS 01",VR::DS,VM::VM1,"??",false}, {0x0021,0x003b,"SIEMENS MR SDS 01",VR::DS,VM::VM1,"??",false}, {0x0021,0x003d,"SIEMENS MR SDS 01",VR::CS,VM::VM1,"?Image Acquisition Param?",false}, + {0x0021,0x003f,"SIEMENS MR SDS 01",VR::UT,VM::VM1,"?",false }, {0x0021,0x0041,"SIEMENS MR SDI 02",VR::SH,VM::VM1,"?GSWDDataType?",false}, {0x0021,0x0042,"SIEMENS MR SDI 02",VR::IS,VM::VM1,"?RealDwellTime?",false}, {0x0021,0x0044,"SIEMENS MR SDS 01",VR::DS,VM::VM2,"??",false}, {0x0021,0x0045,"SIEMENS MR SDI 02",VR::SL,VM::VM3,"?Table Position?",false}, {0x0021,0x0045,"SIEMENS MR SDS 01",VR::CS,VM::VM1,"??",false}, + {0x0021,0x0046,"SIEMENS MR SDI 02",VR::FD,VM::VM3,"?",false }, {0x0021,0x0046,"SIEMENS MR SDS 01",VR::DS,VM::VM1,"??",false}, {0x0021,0x0047,"SIEMENS MR SDS 01",VR::CS,VM::VM1,"??",false}, - {0x0021,0x0048,"SIEMENS MR SDS 01",VR::CS,VM::VM1,"??",false}, - {0x0021,0x0049,"SIEMENS MR SDS 01",VR::CS,VM::VM1,"??",false}, {0x0021,0x0048,"SIEMENS MR SDI 02",VR::IS,VM::VM1,"??",false}, + {0x0021,0x0048,"SIEMENS MR SDS 01",VR::CS,VM::VM1,"??",false}, {0x0021,0x0049,"SIEMENS MR SDI 02",VR::IS,VM::VM1,"??",false}, - {0x0021,0x004e,"SIEMENS MR SDI 02",VR::IS,VM::VM1,"??",false}, + {0x0021,0x0049,"SIEMENS MR SDS 01",VR::CS,VM::VM1,"??",false}, + {0x0021,0x004e,"SIEMENS MR SDI 02",VR::IS,VM::VM1,"Actual 3D Ima Part Number",false}, {0x0021,0x004f,"SIEMENS MR SDI 02",VR::LO,VM::VM1,"ImaCoilString",false}, {0x0021,0x0050,"SIEMENS MR SDS 01",VR::US,VM::VM1,"??",false}, {0x0021,0x0051,"SIEMENS MR SDI 02",VR::UL,VM::VM1,"?SequenceMask?",false}, + {0x0021,0x0051,"SIEMENS MR SDS 01",VR::US,VM::VM1,"??",false}, {0x0021,0x0053,"SIEMENS MR SDI 02",VR::FD,VM::VM1,"?BandwidthPerPixelPhaseEncode?",false}, + {0x0021,0x0053,"SIEMENS MR SDS 01",VR::CS,VM::VM1,"??",false}, {0x0021,0x0054,"SIEMENS MR SDI 02",VR::US,VM::VM1,"??",false}, {0x0021,0x0056,"SIEMENS MR SDI 02",VR::LO,VM::VM1,"?PAT Mode?",false}, - {0x0021,0x0051,"SIEMENS MR SDS 01",VR::US,VM::VM1,"??",false}, - {0x0021,0x0053,"SIEMENS MR SDS 01",VR::CS,VM::VM1,"??",false}, {0x0021,0x0058,"SIEMENS MR SDI 02",VR::SH,VM::VM1,"AcquisitionMatrixText",false}, {0x0021,0x0059,"SIEMENS MR SDI 02",VR::IS,VM::VM3,"?ImaRelTablePosition?",false}, {0x0021,0x005a,"SIEMENS MR SDS 01",VR::CS,VM::VM1,"?Sequence Variant 1?",false}, {0x0021,0x005b,"SIEMENS MR SDI 02",VR::FD,VM::VM3,"Image Position (Patient)",false}, - {0x0021,0x005b,"SIEMENS MR SDS 01",VR::CS,VM::VM1,"?Sequence Variant 2?",false}, - {0x0021,0x005c,"SIEMENS MR SDS 01",VR::CS,VM::VM1,"MTR flag. MT => ON",false}, + {0x0021,0x005b,"SIEMENS MR SDS 01",VR::CS,VM::VM1_n,"?Sequence Variant 2?",false}, + {0x0021,0x005c,"SIEMENS MR SDS 01",VR::CS,VM::VM1_n,"MTR flag. MT => ON",false}, {0x0021,0x005d,"SIEMENS MR SDS 01",VR::SL,VM::VM1,"??",false}, {0x0021,0x005e,"SIEMENS MR SDI 02",VR::IS,VM::VM1,"?FrameIndex?",false}, + {0x0021,0x005e,"SIEMENS MR SDS 01",VR::LO,VM::VM1,"?",false}, + {0x0021,0x005f,"SIEMENS MR SDS 01",VR::SH,VM::VM1,"?FrameIndex?",false}, + {0x0021,0x0060,"SIEMENS MR SDS 01",VR::DT,VM::VM1,"?",false}, + {0x0021,0x0061,"SIEMENS MR SDS 01",VR::SH,VM::VM1,"?",false}, + {0x0021,0x0062,"SIEMENS MR SDS 01",VR::FL,VM::VM1,"?",false}, {0x0021,0x0063,"SIEMENS MR SDI 02",VR::IS,VM::VM1,"?Acquisition Number?",false}, + {0x0021,0x0067,"SIEMENS MR SDI 02",VR::ST,VM::VM1,"?DataRole XML?",false }, + {0x0021,0x0068,"SIEMENS MR SDI 02",VR::OB,VM::VM1,"?MRDiffusionSequence as base64 encoded?",false }, {0x0021,0x0071,"SIEMENS MR SDI 02",VR::UT,VM::VM1,"?may contain PHI?",false}, {0x0021,0x0075,"SIEMENS MR SDI 02",VR::CS,VM::VM1_n,"Image Type",false}, {0x0021,0x0076,"SIEMENS MR SDI 02",VR::LO,VM::VM1_n,"Acquisition Info",false}, {0x0021,0x0077,"SIEMENS MR SDI 02",VR::LO,VM::VM1,"Sequence Name",false}, {0x0021,0x0078,"SIEMENS MR SDI 02",VR::CS,VM::VM1,"Acquisition Type 1",false}, {0x0021,0x0079,"SIEMENS MR SDI 02",VR::CS,VM::VM1,"Acquisition Type 2",false}, + {0x0021,0x0081,"SIEMENS MR SDI 02",VR::LO,VM::VM1,"?",false}, {0x0021,0x0088,"SIEMENS MR SDI 02",VR::DS,VM::VM1,"Slice Location",false}, + {0x0021,0x0089,"SIEMENS MR SDI 02",VR::SH,VM::VM1,"?",false }, {0x0021,0x008a,"SIEMENS MR SDI 02",VR::IS,VM::VM1,"Instance/Frame Number",false}, + {0x0021,0x008b,"SIEMENS MR SDI 02",VR::SH,VM::VM1,"?",false}, + {0x0021,0x008c,"SIEMENS MR SDI 02",VR::FD,VM::VM1,"?",false}, + {0x0021,0x008d,"SIEMENS MR SDI 02",VR::FD,VM::VM1,"?",false}, + {0x0021,0x008e,"SIEMENS MR SDI 02",VR::ST,VM::VM1,"?",false}, {0x0021,0x00fe,"SIEMENS MR SDI 02",VR::SQ,VM::VM1,"??",false}, - {0x0021,0x00fe,"SIEMENS MR SDS 01",VR::SQ,VM::VM1,"??",false}, + {0x0021,0x00fe,"SIEMENS MR SDS 01",VR::SQ,VM::VM1,"Series Data Sequence",false}, {0x0089,0x0054,"SYNGO_IMAGING",VR::OW,VM::VM1,"??",false}, {0x0095,0x00fa,"SIENET",VR::PN,VM::VM1,"?Some kind of Patient Name?",false}, {0x8ff1,0x0010,"SSI Image enhancement Group",VR::LO,VM::VM1,"SSI Image enhancement Group Version",false }, @@ -703,153 +1319,163 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0011,0x0007,"PMTF INFORMATION DATA^10",VR::US,VM::VM1_n,"?",false }, {0x0011,0x0008,"PMTF INFORMATION DATA^10",VR::SH,VM::VM1,"?",false }, {0x0019,0x0000,"PMTF INFORMATION DATA^12",VR::SL,VM::VM1,"?",false }, - {0x0019,0x0001,"PMTF INFORMATION DATA^10",VR::UL,VM::VM1,"?",false }, + {0x0019,0x0001,"PMTF INFORMATION DATA^11",VR::OB,VM::VM1,"?character set?",false }, {0x0019,0x0001,"PMTF INFORMATION DATA^12",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0001,"PMTF INFORMATION DATA^10",VR::UL,VM::VM1,"?",false }, {0x0019,0x0002,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0002,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0002,"PMTF INFORMATION DATA^12",VR::SL,VM::VM1,"?",false }, - {0x0019,0x0003,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0003,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0003,"PMTF INFORMATION DATA^12",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0003,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0004,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0004,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0004,"PMTF INFORMATION DATA^12",VR::SL,VM::VM1,"?",false }, {0x0019,0x0005,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x0005,"PMTF INFORMATION DATA^12",VR::SH,VM::VM1,"?Sequence Variant?",false }, - {0x0019,0x0006,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0006,"PMTF INFORMATION DATA^12",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0006,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0007,"PMTF INFORMATION DATA^10",VR::FL,VM::VM3,"?",false }, {0x0019,0x0007,"PMTF INFORMATION DATA^11",VR::OB,VM::VM1,"?",false }, - {0x0019,0x0007,"PMTF INFORMATION DATA^12",VR::UL,VM::VM2,"?",false }, - {0x0019,0x0008,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x0007,"PMTF INFORMATION DATA^12",VR::UL,VM::VM1_2,"?",false }, {0x0019,0x0008,"PMTF INFORMATION DATA^11",VR::SH,VM::VM1,"?",false }, - {0x0019,0x0008,"PMTF INFORMATION DATA^12",VR::UL,VM::VM2,"?",false }, + {0x0019,0x0008,"PMTF INFORMATION DATA^12",VR::UL,VM::VM1_2,"?",false }, + {0x0019,0x0008,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0009,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, - {0x0019,0x0009,"PMTF INFORMATION DATA^11",VR::SL,VM::VM2,"?",false }, {0x0019,0x0009,"PMTF INFORMATION DATA^12",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0009,"PMTF INFORMATION DATA^11",VR::SL,VM::VM2,"?",false }, {0x0019,0x000a,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x000a,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x000a,"PMTF INFORMATION DATA^12",VR::SL,VM::VM1,"?",false }, {0x0019,0x000b,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x000b,"PMTF INFORMATION DATA^11",VR::OB,VM::VM1,"?",false }, {0x0019,0x000b,"PMTF INFORMATION DATA^12",VR::SL,VM::VM1,"?",false }, - {0x0019,0x000c,"PMTF INFORMATION DATA^10",VR::US,VM::VM3,"?",false }, {0x0019,0x000c,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x000c,"PMTF INFORMATION DATA^12",VR::UL,VM::VM1,"?",false }, + {0x0019,0x000c,"PMTF INFORMATION DATA^10",VR::US,VM::VM3,"?",false }, {0x0019,0x000d,"PMTF INFORMATION DATA^10",VR::SL,VM::VM6,"?",false }, {0x0019,0x000d,"PMTF INFORMATION DATA^12",VR::SQ,VM::VM1,"?",false }, {0x0019,0x000e,"PMTF INFORMATION DATA^10",VR::SL,VM::VM6,"?",false }, {0x0019,0x000e,"PMTF INFORMATION DATA^12",VR::US,VM::VM1,"?",false }, {0x0019,0x000f,"PMTF INFORMATION DATA^10",VR::SL,VM::VM6,"?",false }, - {0x0019,0x0010,"PMTF INFORMATION DATA^10",VR::US,VM::VM2,"?",false }, {0x0019,0x0010,"PMTF INFORMATION DATA^12",VR::SL,VM::VM1,"?",false }, - {0x0019,0x0011,"PMTF INFORMATION DATA^10",VR::SL,VM::VM2,"?",false }, + {0x0019,0x0010,"PMTF INFORMATION DATA^10",VR::US,VM::VM2,"?",false }, {0x0019,0x0011,"PMTF INFORMATION DATA^12",VR::SL,VM::VM1,"?",false }, - {0x0019,0x0012,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x0011,"PMTF INFORMATION DATA^10",VR::SL,VM::VM2,"?",false }, {0x0019,0x0012,"PMTF INFORMATION DATA^12",VR::SL,VM::VM1,"?",false }, - {0x0019,0x0013,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0012,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0013,"PMTF INFORMATION DATA^12",VR::FL,VM::VM1,"?",false }, - {0x0019,0x0014,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x0013,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0014,"PMTF INFORMATION DATA^12",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0014,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0015,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0016,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x0017,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, - {0x0019,0x0018,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0018,"PMTF INFORMATION DATA^12",VR::UL,VM::VM1,"?",false }, + {0x0019,0x0018,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0019,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0019,"PMTF INFORMATION DATA^11",VR::SQ,VM::VM1,"?",false }, - {0x0019,0x001a,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x001a,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x001a,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x001b,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x001c,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x001d,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x001e,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x001f,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0020,"PMTF INFORMATION DATA^10",VR::FL,VM::VM2,"?",false }, + {0x0019,0x0021,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x0022,"PMTF INFORMATION DATA^10",VR::SL,VM::VM2,"?",false }, + {0x0019,0x0023,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0024,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x0024,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0025,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x0025,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0026,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0026,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0027,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0028,"PMTF INFORMATION DATA^12",VR::DS,VM::VM1,"?",false }, {0x0019,0x0028,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0028,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, - {0x0019,0x0028,"PMTF INFORMATION DATA^12",VR::DS,VM::VM1,"?",false }, {0x0019,0x0029,"PMTF INFORMATION DATA^10",VR::SH,VM::VM1,"?",false }, {0x0019,0x0029,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, - {0x0019,0x002a,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, /* may re-use ^12 in actual dataset, hard to handle */ - {0x0019,0x002a,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x002a,"PMTF INFORMATION DATA^12",VR::DS /* TM*/,VM::VM3 /* 1 */,"?",false }, /* dual TM,1 or DS,3 !!! */ - {0x0019,0x002b,"PMTF INFORMATION DATA^10",VR::SH,VM::VM1,"?",false }, + {0x0019,0x002a,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x002a,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x002b,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x002b,"PMTF INFORMATION DATA^10",VR::SH,VM::VM1,"?",false }, {0x0019,0x002b,"PMTF INFORMATION DATA^12",VR::SQ,VM::VM1,"?",false }, {0x0019,0x002c,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x002c,"PMTF INFORMATION DATA^11",VR::SL,VM::VM3,"?",false }, {0x0019,0x002d,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x002d,"PMTF INFORMATION DATA^11",VR::SL,VM::VM3,"?",false }, - {0x0019,0x002e,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x002e,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x002e,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x002f,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, - {0x0019,0x0030,"PMTF INFORMATION DATA^10",VR::UL,VM::VM1,"?",false }, {0x0019,0x0030,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0030,"PMTF INFORMATION DATA^10",VR::UL,VM::VM1,"?",false }, {0x0019,0x0031,"PMTF INFORMATION DATA^10",VR::OF,VM::VM1_n,"?",false }, {0x0019,0x0031,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0032,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, - {0x0019,0x0032,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0032,"PMTF INFORMATION DATA^12",VR::SH,VM::VM1,"Sequence Name",false }, + {0x0019,0x0032,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0033,"PMTF INFORMATION DATA^10",VR::SL,VM::VM3,"?",false }, - {0x0019,0x0034,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0034,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0034,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0034,"PMTF INFORMATION DATA^12",VR::SL,VM::VM1,"?",false }, {0x0019,0x0035,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0035,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, - {0x0019,0x0036,"PMTF INFORMATION DATA^10",VR::SQ,VM::VM1,"?",false }, {0x0019,0x0036,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0036,"PMTF INFORMATION DATA^10",VR::SQ,VM::VM1,"?",false }, {0x0019,0x0037,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0038,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0038,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0039,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0039,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x003a,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"Repetition Time (/100)",false }, {0x0019,0x003a,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, - {0x0019,0x003a,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x003b,"PMTF INFORMATION DATA^10",VR::SL,VM::VM2,"?",false }, - {0x0019,0x003c,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x003c,"PMTF INFORMATION DATA^11",VR::FL,VM::VM3,"?",false }, + {0x0019,0x003c,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x003d,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x003d,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, - {0x0019,0x003e,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x003e,"PMTF INFORMATION DATA^11",VR::FL,VM::VM9,"?",false }, + {0x0019,0x003e,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x003f,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x003f,"PMTF INFORMATION DATA^11",VR::UI,VM::VM1,"?",false }, {0x0019,0x0040,"PMTF INFORMATION DATA^11",VR::US,VM::VM1,"?",false }, {0x0019,0x0041,"PMTF INFORMATION DATA^11",VR::US,VM::VM1,"?",false }, - {0x0019,0x0042,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0042,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, - {0x0019,0x0043,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x0042,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0043,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0043,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0044,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0044,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0045,"PMTF INFORMATION DATA^10",VR::SS,VM::VM1,"?",false }, - {0x0019,0x0046,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0046,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0046,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0047,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, - {0x0019,0x0048,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0048,"PMTF INFORMATION DATA^11",VR::LT,VM::VM1,"?QD Whole Body?",false }, - {0x0019,0x0049,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x0048,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0049,"PMTF INFORMATION DATA^11",VR::LT,VM::VM1,"?Atlas Head?",false }, + {0x0019,0x0049,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x004b,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, - {0x0019,0x004c,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x004c,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x004c,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x004d,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x004d,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?postproc series?",false }, - {0x0019,0x004e,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x004e,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x004e,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x004f,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0050,"PMTF INFORMATION DATA^10",VR::SL,VM::VM2,"?",false }, {0x0019,0x0051,"PMTF INFORMATION DATA^10",VR::SL,VM::VM2,"?",false }, - {0x0019,0x0052,"PMTF INFORMATION DATA^10",VR::LO,VM::VM1,"?",false }, {0x0019,0x0052,"PMTF INFORMATION DATA^12",VR::FL,VM::VM2,"?",false }, + {0x0019,0x0052,"PMTF INFORMATION DATA^10",VR::LO,VM::VM1,"?",false }, {0x0019,0x0054,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, - {0x0019,0x0055,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0055,"PMTF INFORMATION DATA^11",VR::LO,VM::VM1,"?",false }, + {0x0019,0x0055,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0056,"PMTF INFORMATION DATA^10",VR::FL,VM::VM3,"?",false }, - {0x0019,0x0057,"PMTF INFORMATION DATA^10",VR::FL,VM::VM3,"?",false }, {0x0019,0x0057,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0057,"PMTF INFORMATION DATA^10",VR::FL,VM::VM3,"?",false }, {0x0019,0x0058,"PMTF INFORMATION DATA^10",VR::FL,VM::VM3,"?",false }, {0x0019,0x0058,"PMTF INFORMATION DATA^11",VR::US,VM::VM1,"?",false }, {0x0019,0x0059,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, @@ -861,31 +1487,31 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0019,0x005e,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x005f,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x005f,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, - {0x0019,0x0060,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0060,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, - {0x0019,0x0061,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x0060,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0061,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, - {0x0019,0x0062,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x0061,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0062,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0062,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0063,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x0063,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0064,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, - {0x0019,0x0065,"PMTF INFORMATION DATA^10",VR::SL,VM::VM2,"?",false }, {0x0019,0x0065,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x0065,"PMTF INFORMATION DATA^10",VR::SL,VM::VM2,"?",false }, {0x0019,0x0067,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x0068,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0069,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x006a,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x006b,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x006c,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, - {0x0019,0x006d,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x006d,"PMTF INFORMATION DATA^11",VR::SH,VM::VM1,"?",false }, + {0x0019,0x006d,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x006e,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x006e,"PMTF INFORMATION DATA^11",VR::SH,VM::VM1,"Sequence Name",false }, - {0x0019,0x006f,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x006f,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, - {0x0019,0x0070,"PMTF INFORMATION DATA^10",VR::LO,VM::VM1,"?",false }, + {0x0019,0x006f,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0070,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x0070,"PMTF INFORMATION DATA^10",VR::LO,VM::VM1,"?",false }, {0x0019,0x0071,"PMTF INFORMATION DATA^10",VR::LO,VM::VM1,"?Sequence Options?",false }, {0x0019,0x0071,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0072,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, @@ -906,13 +1532,13 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0019,0x007e,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x007f,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x007f,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, - {0x0019,0x0080,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x0080,"PMTF INFORMATION DATA^12",VR::FD,VM::VM1,"Acquisition Duration",false }, + {0x0019,0x0080,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x0084,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0085,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x0085,"PMTF INFORMATION DATA^12",VR::US,VM::VM1,"?",false }, - {0x0019,0x0086,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0086,"PMTF INFORMATION DATA^12",VR::LO,VM::VM1,"?",false }, + {0x0019,0x0086,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0087,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x0087,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0087,"PMTF INFORMATION DATA^12",VR::SQ,VM::VM1,"?",false }, @@ -924,87 +1550,90 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0019,0x008a,"PMTF INFORMATION DATA^12",VR::US,VM::VM1,"Series Number Global",false }, {0x0019,0x008b,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x008b,"PMTF INFORMATION DATA^12",VR::US,VM::VM1,"?",false }, - {0x0019,0x008c,"PMTF INFORMATION DATA^10",VR::UL,VM::VM1,"?",false }, {0x0019,0x008c,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x008c,"PMTF INFORMATION DATA^10",VR::UL,VM::VM1,"?",false }, {0x0019,0x008d,"PMTF INFORMATION DATA^10",VR::TM,VM::VM1,"?",false }, {0x0019,0x008e,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, - {0x0019,0x008f,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x008f,"PMTF INFORMATION DATA^12",VR::OB,VM::VM1,"?",false }, + {0x0019,0x008f,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0090,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0091,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0092,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x0092,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0093,"PMTF INFORMATION DATA^10",VR::FL,VM::VM3,"?",false }, + {0x0019,0x0093,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x0093,"PMTF INFORMATION DATA^12",VR::SL,VM::VM1,"?num?",false }, {0x0019,0x0094,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x0094,"PMTF INFORMATION DATA^12",VR::UI,VM::VM1,"Referenced SOP Instance UID",false }, {0x0019,0x0095,"PMTF INFORMATION DATA^12",VR::UI,VM::VM1,"?",false }, - {0x0019,0x0096,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0096,"PMTF INFORMATION DATA^12",VR::LO,VM::VM1,"?PASTA?",false }, + {0x0019,0x0096,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x0098,"PMTF INFORMATION DATA^12",VR::FL,VM::VM3,"?",false }, {0x0019,0x0099,"PMTF INFORMATION DATA^12",VR::LO,VM::VM1,"Sequence Name",false }, - {0x0019,0x009a,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x009a,"PMTF INFORMATION DATA^12",VR::DS,VM::VM1,"Series Number Local",false }, + {0x0019,0x009a,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x009b,"PMTF INFORMATION DATA^12",VR::DS,VM::VM1,"?",false }, // Sometimes IS {0x0019,0x009b,"PMTF INFORMATION DATA^10",VR::FL,VM::VM3,"?",false }, {0x0019,0x009b,"PMTF INFORMATION DATA^11",VR::US,VM::VM1,"?",false }, - {0x0019,0x009b,"PMTF INFORMATION DATA^12",VR::DS,VM::VM1,"?",false }, // Sometimes IS - {0x0019,0x009c,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, - {0x0019,0x009c,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x009c,"PMTF INFORMATION DATA^12",VR::DS,VM::VM1,"?num?",false }, + {0x0019,0x009c,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x009c,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x009d,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x009d,"PMTF INFORMATION DATA^12",VR::US,VM::VM1,"?",false }, - {0x0019,0x009e,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x009e,"PMTF INFORMATION DATA^12",VR::FL,VM::VM3,"?",false }, - {0x0019,0x009f,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x009e,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x009f,"PMTF INFORMATION DATA^12",VR::FL,VM::VM1,"?",false }, - {0x0019,0x00a0,"PMTF INFORMATION DATA^10",VR::SL,VM::VM4,"?",false }, + {0x0019,0x009f,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00a0,"PMTF INFORMATION DATA^12",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00a0,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00a0,"PMTF INFORMATION DATA^10",VR::SL,VM::VM4,"?",false }, {0x0019,0x00a1,"PMTF INFORMATION DATA^10",VR::DS,VM::VM1,"?",false }, - {0x0019,0x00a1,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00a1,"PMTF INFORMATION DATA^12",VR::FL,VM::VM1,"?",false }, - {0x0019,0x00a2,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00a1,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00a2,"PMTF INFORMATION DATA^12",VR::FL,VM::VM1,"?",false }, - {0x0019,0x00a3,"PMTF INFORMATION DATA^10",VR::SL,VM::VM3,"?",false }, + {0x0019,0x00a2,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00a3,"PMTF INFORMATION DATA^12",VR::FL,VM::VM1,"?",false }, - {0x0019,0x00a4,"PMTF INFORMATION DATA^10",VR::FL,VM::VM3,"?",false }, + {0x0019,0x00a3,"PMTF INFORMATION DATA^10",VR::SL,VM::VM3,"?",false }, {0x0019,0x00a4,"PMTF INFORMATION DATA^12",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00a4,"PMTF INFORMATION DATA^10",VR::FL,VM::VM3,"?",false }, {0x0019,0x00a5,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, - {0x0019,0x00a5,"PMTF INFORMATION DATA^11",VR::US,VM::VM1,"?",false }, {0x0019,0x00a5,"PMTF INFORMATION DATA^12",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00a5,"PMTF INFORMATION DATA^11",VR::US,VM::VM1,"?",false }, + {0x0019,0x00a6,"PMTF INFORMATION DATA^12",VR::FL,VM::VM2_2n,"?",false }, {0x0019,0x00a6,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00a6,"PMTF INFORMATION DATA^11",VR::US,VM::VM1,"?",false }, - {0x0019,0x00a6,"PMTF INFORMATION DATA^12",VR::FL,VM::VM1_n,"?",false }, {0x0019,0x00a7,"PMTF INFORMATION DATA^12",VR::FL,VM::VM1,"?",false }, - {0x0019,0x00a8,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, - {0x0019,0x00a8,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00a8,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?Repetition Time (/100)",false }, {0x0019,0x00a8,"PMTF INFORMATION DATA^12",VR::FL,VM::VM1,"?",false }, - {0x0019,0x00a9,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00a8,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00a9,"PMTF INFORMATION DATA^12",VR::FL,VM::VM3,"?",false }, + {0x0019,0x00a9,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00aa,"PMTF INFORMATION DATA^12",VR::FL,VM::VM3,"?",false }, {0x0019,0x00ab,"PMTF INFORMATION DATA^10",VR::FL,VM::VM3,"?",false }, {0x0019,0x00ab,"PMTF INFORMATION DATA^12",VR::FL,VM::VM3,"?",false }, - {0x0019,0x00ac,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, + {0x0019,0x00ab,"PMTF INFORMATION DATA^11",VR::US,VM::VM1,"?",false }, {0x0019,0x00ac,"PMTF INFORMATION DATA^12",VR::FL,VM::VM3,"?",false }, + {0x0019,0x00ac,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x00ad,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, - {0x0019,0x00ad,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00ad,"PMTF INFORMATION DATA^12",VR::FL,VM::VM3,"?",false }, + {0x0019,0x00ad,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00ae,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, - {0x0019,0x00ae,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00ae,"PMTF INFORMATION DATA^12",VR::FL,VM::VM3,"?",false }, - {0x0019,0x00af,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00ae,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00af,"PMTF INFORMATION DATA^12",VR::FL,VM::VM3,"?",false }, - {0x0019,0x00b0,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00af,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00b0,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00b0,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00b1,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00b1,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00b2,"PMTF INFORMATION DATA^11",VR::US,VM::VM1,"?",false }, - {0x0019,0x00b3,"PMTF INFORMATION DATA^11",VR::US,VM::VM1,"?",false }, {0x0019,0x00b3,"PMTF INFORMATION DATA^12",VR::FD,VM::VM1,"Acquisition Duration",false }, + {0x0019,0x00b3,"PMTF INFORMATION DATA^11",VR::US,VM::VM1,"?",false }, + {0x0019,0x00b4,"PMTF INFORMATION DATA^12",VR::LO,VM::VM1,"?",false }, {0x0019,0x00b4,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00b4,"PMTF INFORMATION DATA^11",VR::US,VM::VM1,"?",false }, - {0x0019,0x00b4,"PMTF INFORMATION DATA^12",VR::LO,VM::VM1,"?",false }, - {0x0019,0x00b5,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00b5,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00b5,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00b6,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00b6,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00b7,"PMTF INFORMATION DATA^10",VR::FL,VM::VM2,"?",false }, @@ -1017,16 +1646,16 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0019,0x00bc,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00bd,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00bd,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, - {0x0019,0x00be,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"Acquisition Duration",false }, {0x0019,0x00be,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1_n,"?",false }, + {0x0019,0x00be,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"Acquisition Duration",false }, {0x0019,0x00bf,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00c0,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00c1,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00c1,"PMTF INFORMATION DATA^11",VR::US,VM::VM1,"?",false }, {0x0019,0x00c2,"PMTF INFORMATION DATA^12",VR::US,VM::VM1,"?",false }, - {0x0019,0x00c3,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00c3,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x00c3,"PMTF INFORMATION DATA^12",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00c3,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00c4,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00c4,"PMTF INFORMATION DATA^12",VR::SL,VM::VM1,"?",false }, {0x0019,0x00c5,"PMTF INFORMATION DATA^12",VR::SL,VM::VM1,"?",false }, @@ -1036,18 +1665,18 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0019,0x00c9,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00ca,"PMTF INFORMATION DATA^10",VR::LO,VM::VM1,"Sequence Name",false }, {0x0019,0x00cb,"PMTF INFORMATION DATA^10",VR::UL,VM::VM1,"?",false }, - {0x0019,0x00cc,"PMTF INFORMATION DATA^10",VR::UL,VM::VM1,"?",false }, {0x0019,0x00cc,"PMTF INFORMATION DATA^12",VR::SS,VM::VM1_n,"?",false }, + {0x0019,0x00cc,"PMTF INFORMATION DATA^10",VR::UL,VM::VM1,"?",false }, + {0x0019,0x00cd,"PMTF INFORMATION DATA^12",VR::LO,VM::VM1,"?",false }, {0x0019,0x00cd,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00cd,"PMTF INFORMATION DATA^11",VR::SL,VM::VM3,"?",false }, - {0x0019,0x00cd,"PMTF INFORMATION DATA^12",VR::LO,VM::VM1,"?",false }, {0x0019,0x00ce,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00ce,"PMTF INFORMATION DATA^12",VR::UL,VM::VM1,"?",false }, - {0x0019,0x00cf,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?acquired series (vs postproc)?",false }, {0x0019,0x00cf,"PMTF INFORMATION DATA^12",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00cf,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?acquired series (vs postproc)?",false }, {0x0019,0x00d0,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, - {0x0019,0x00d1,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00d1,"PMTF INFORMATION DATA^12",VR::FL,VM::VM3,"?",false }, + {0x0019,0x00d1,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00d2,"PMTF INFORMATION DATA^10",VR::SL,VM::VM3,"?",false }, {0x0019,0x00d2,"PMTF INFORMATION DATA^12",VR::US,VM::VM3,"?",false }, {0x0019,0x00d3,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, @@ -1057,8 +1686,8 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0019,0x00d5,"PMTF INFORMATION DATA^12",VR::FL,VM::VM1,"?",false }, {0x0019,0x00d6,"PMTF INFORMATION DATA^12",VR::FL,VM::VM3,"?",false }, {0x0019,0x00d7,"PMTF INFORMATION DATA^12",VR::US,VM::VM2,"?vect2?",false }, - {0x0019,0x00d8,"PMTF INFORMATION DATA^10",VR::US,VM::VM1_n,"?",false }, {0x0019,0x00d8,"PMTF INFORMATION DATA^12",VR::FL,VM::VM1_n,"?",false }, + {0x0019,0x00d8,"PMTF INFORMATION DATA^10",VR::US,VM::VM1_n,"?",false }, {0x0019,0x00d9,"PMTF INFORMATION DATA^10",VR::SQ,VM::VM1,"?",false }, {0x0019,0x00da,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x00db,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, @@ -1067,14 +1696,14 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0019,0x00df,"PMTF INFORMATION DATA^12",VR::US,VM::VM1,"?",false }, {0x0019,0x00e0,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x00e0,"PMTF INFORMATION DATA^12",VR::US,VM::VM1,"?",false }, - {0x0019,0x00e1,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00e1,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x00e1,"PMTF INFORMATION DATA^12",VR::FL,VM::VM3,"?vect3?",false }, + {0x0019,0x00e1,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00e2,"PMTF INFORMATION DATA^12",VR::FL,VM::VM3,"?vect3?",false }, {0x0019,0x00e3,"PMTF INFORMATION DATA^11",VR::SL,VM::VM3,"?",false }, {0x0019,0x00e3,"PMTF INFORMATION DATA^12",VR::TM,VM::VM1,"?time?",false }, - {0x0019,0x00e4,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00e4,"PMTF INFORMATION DATA^11",VR::DS,VM::VM1,"?",false }, + {0x0019,0x00e4,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00e4,"PMTF INFORMATION DATA^12",VR::US,VM::VM2,"?vect2?",false }, {0x0019,0x00e5,"PMTF INFORMATION DATA^10",VR::SQ,VM::VM1,"?",false }, {0x0019,0x00e5,"PMTF INFORMATION DATA^11",VR::SQ,VM::VM1,"?",false }, @@ -1087,33 +1716,33 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0019,0x00ec,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x00ec,"PMTF INFORMATION DATA^12",VR::US,VM::VM1,"?num?",false }, {0x0019,0x00ee,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, - {0x0019,0x00ef,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x00ef,"PMTF INFORMATION DATA^12",VR::DS,VM::VM1,"?",false }, + {0x0019,0x00ef,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00f0,"PMTF INFORMATION DATA^12",VR::LO,VM::VM1,"?",false }, {0x0019,0x00f0,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00f0,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1_n,"?",false }, - {0x0019,0x00f0,"PMTF INFORMATION DATA^12",VR::LO,VM::VM1,"?",false }, {0x0019,0x00f1,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, - {0x0019,0x00f1,"PMTF INFORMATION DATA^11",VR::SL,VM::VM3,"Diffusion b-value x Toshiba Orientation",false }, {0x0019,0x00f1,"PMTF INFORMATION DATA^12",VR::LO,VM::VM1,"?",false }, + {0x0019,0x00f1,"PMTF INFORMATION DATA^11",VR::SL,VM::VM3,"Diffusion b-value x Toshiba Orientation",false }, {0x0019,0x00f2,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, - {0x0019,0x00f2,"PMTF INFORMATION DATA^11",VR::FL,VM::VM3,"?",false }, + {0x0019,0x00f2,"PMTF INFORMATION DATA^11",VR::FL,VM::VM3,"Specific Absorption Rate Values",false }, {0x0019,0x00f3,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00f3,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00f4,"PMTF INFORMATION DATA^10",VR::FD,VM::VM1,"?",false }, {0x0019,0x00f4,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00f5,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00f5,"PMTF INFORMATION DATA^11",VR::SQ,VM::VM1,"?",false }, - {0x0019,0x00f6,"PMTF INFORMATION DATA^10",VR::UI,VM::VM1,"?",false }, {0x0019,0x00f6,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00f6,"PMTF INFORMATION DATA^10",VR::UI,VM::VM1,"?",false }, {0x0019,0x00f7,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, - {0x0019,0x00f8,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x00f8,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00f8,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?",false }, {0x0019,0x00f9,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00f9,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00fa,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x00fa,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, - {0x0019,0x00fb,"PMTF INFORMATION DATA^10",VR::UL,VM::VM1,"?",false }, {0x0019,0x00fb,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, + {0x0019,0x00fb,"PMTF INFORMATION DATA^10",VR::UL,VM::VM1,"?",false }, {0x0019,0x00fc,"PMTF INFORMATION DATA^10",VR::FL,VM::VM1,"?",false }, {0x0019,0x00fc,"PMTF INFORMATION DATA^11",VR::FL,VM::VM1,"?",false }, {0x0019,0x00fc,"PMTF INFORMATION DATA^12",VR::FL,VM::VM1,"?",false }, @@ -1123,8 +1752,8 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0019,0x00fe,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?",false }, {0x0019,0x00fe,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, {0x0019,0x00fe,"PMTF INFORMATION DATA^12",VR::SL,VM::VM1,"?",false }, - {0x0019,0x00ff,"PMTF INFORMATION DATA^10",VR::SL,VM::VM3,"?",false }, {0x0019,0x00ff,"PMTF INFORMATION DATA^11",VR::SL,VM::VM1,"?",false }, + {0x0019,0x00ff,"PMTF INFORMATION DATA^10",VR::SL,VM::VM3,"?",false }, {0x0021,0x0002,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?num?",false }, {0x0021,0x0003,"PMTF INFORMATION DATA^10",VR::SL,VM::VM1,"?num?",false }, {0x0021,0x0004,"PMTF INFORMATION DATA^10",VR::US,VM::VM1,"?num?",false }, @@ -1175,8 +1804,8 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0xe401,0x0022,"PMTF INFORMATION DATA^10",VR::LO,VM::VM1,"?MR.gdc?",false }, {0xe401,0x0023,"PMTF INFORMATION DATA^10",VR::SH,VM::VM1,"Software Version(s)",false }, {0xe401,0x0024,"PMTF INFORMATION DATA^10",VR::OB,VM::VM1,"?blob?",false }, - {0xe403,0x0000,"PMTF INFORMATION DATA^10",VR::SQ,VM::VM1,"?seq?",false }, {0xe403,0x0000,"PMTF INFORMATION DATA^13",VR::SH,VM::VM1,"?VIEW?",false }, + {0xe403,0x0000,"PMTF INFORMATION DATA^10",VR::SQ,VM::VM1,"?seq?",false }, {0xe403,0x0001,"PMTF INFORMATION DATA^13",VR::OB,VM::VM1,"?blob0?",false }, {0xe403,0x0002,"PMTF INFORMATION DATA^13",VR::OB,VM::VM1,"?blob1?",false }, {0xe403,0x0003,"PMTF INFORMATION DATA^13",VR::OB,VM::VM1,"?blob2?",false }, @@ -1588,6 +2217,9 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0023,0x0008,"AMICAS0",VR::US,VM::VM1,"?",false }, {0x0023,0x0010,"AMICAS0",VR::US,VM::VM1,"?",false }, {0x0023,0x0016,"AMICAS0",VR::SL,VM::VM1,"?",false }, + {0x0023,0x0021,"AMICAS0",VR::US,VM::VM1,"?",false }, + {0x0023,0x0022,"AMICAS0",VR::UL,VM::VM1,"?",false }, + {0x0023,0x0040,"AMICAS0",VR::US,VM::VM1,"?",false }, {0x0023,0x0043,"AMICAS0",VR::US,VM::VM1,"?",false }, {0x0023,0x0045,"AMICAS0",VR::US,VM::VM1,"?",false }, {0x0023,0x0054,"AMICAS0",VR::ST,VM::VM1,"?Performed Station AE Title?",false }, @@ -2044,6 +2676,13 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x4453,0x0005,"DR Systems, Inc.",VR::LO,VM::VM1,"DR File Suffix",false }, {0x4453,0x000a,"DR Systems, Inc.",VR::UN,VM::VM1,"DR Annotation Type",false }, {0x4453,0x000c,"DR Systems, Inc.",VR::SQ,VM::VM1,"DR Original Instance UID Sequence",false }, + {0x4453,0x000d,"DR Systems, Inc.",VR::PN,VM::VM1,"?",false }, + {0x4453,0x000e,"DR Systems, Inc.",VR::DA,VM::VM1,"?",false }, + {0x4453,0x000f,"DR Systems, Inc.",VR::CS,VM::VM1,"?",false }, + {0x4453,0x0010,"DR Systems, Inc.",VR::LO,VM::VM1,"?",false }, + {0x4453,0x0011,"DR Systems, Inc.",VR::DA,VM::VM1,"?",false }, + {0x4453,0x0012,"DR Systems, Inc.",VR::TM,VM::VM1,"?",false }, + {0x4453,0x0013,"DR Systems, Inc.",VR::LO,VM::VM1,"?",false }, {0x7fa1,0x0000,"ELGEMS_XPERT",VR::OB,VM::VM1,"XPert Composite Report Item buffer",false }, {0x7fa1,0x0010,"ELGEMS_XPERT",VR::OB,VM::VM1,"Xpert Composite Report Item Identificator",false }, {0x0003,0x0001,"ELSCINT1",VR::OW,VM::VM1,"Offset List Structure",false }, @@ -2080,6 +2719,7 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x00e1,0x0042,"ELSCINT1",VR::LO,VM::VM1,"?",false }, {0x00e1,0x0043,"ELSCINT1",VR::IS,VM::VM1,"?",false }, {0x00e1,0x0045,"ELSCINT1",VR::SL,VM::VM1,"?",false }, + {0x00e1,0x0046,"ELSCINT1",VR::OB,VM::VM1,"?",false }, {0x00e1,0x0050,"ELSCINT1",VR::DS,VM::VM1,"Acquisition Duration",false }, {0x00e1,0x0051,"ELSCINT1",VR::SH,VM::VM1,"?",false }, {0x00e1,0x0060,"ELSCINT1",VR::CS,VM::VM1,"?",false }, @@ -2093,6 +2733,9 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x00e1,0x00a0,"ELSCINT1",VR::LO,VM::VM1,"?",false }, {0x00e1,0x00c2,"ELSCINT1",VR::UI,VM::VM1,"PET-CT Multi Modality Name",false }, {0x00e1,0x00c4,"ELSCINT1",VR::DS,VM::VM1,"Private (00E1,10C4)",false }, + {0x00e1,0x00e1,"ELSCINT1",VR::US,VM::VM1,"?",false }, + {0x00e1,0x00e3,"ELSCINT1",VR::US,VM::VM1,"?",false }, + {0x00e1,0x00ec,"ELSCINT1",VR::US,VM::VM1,"?",false }, {0x00e3,0x0000,"ELSCINT1",VR::OB,VM::VM1,"?",false }, {0x00e3,0x0018,"ELSCINT1",VR::OB,VM::VM1,"?",false }, {0x00e3,0x001a,"ELSCINT1",VR::OB,VM::VM1,"?",false }, @@ -2104,6 +2747,7 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x01e1,0x0023,"ELSCINT1",VR::SH,VM::VM1,"?",false }, {0x01e1,0x0026,"ELSCINT1",VR::CS,VM::VM1,"PhantomType (private)",false }, {0x01e1,0x0034,"ELSCINT1",VR::IS,VM::VM1,"?",false }, + {0x01e1,0x0040,"ELSCINT1",VR::UI,VM::VM1,"?",false }, {0x01e1,0x0041,"ELSCINT1",VR::OW,VM::VM1,"?",false }, {0x01f1,0x0001,"ELSCINT1",VR::CS,VM::VM1,"Acquisition Type",false }, {0x01f1,0x0002,"ELSCINT1",VR::CS,VM::VM1,"Focal Spot Resolution",false }, @@ -2118,6 +2762,7 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x01f1,0x000c,"ELSCINT1",VR::DS,VM::VM2,"Scanner Relative Center",false }, {0x01f1,0x000d,"ELSCINT1",VR::DS,VM::VM1,"Rotation Angle",false }, {0x01f1,0x000e,"ELSCINT1",VR::FL,VM::VM1,"Private (01F1,100E)",false }, + {0x01f1,0x000f,"ELSCINT1",VR::CS,VM::VM1,"?",false }, {0x01f1,0x0026,"ELSCINT1",VR::DS,VM::VM1,"Pitch",false }, {0x01f1,0x0027,"ELSCINT1",VR::DS,VM::VM1,"Rotation Time",false }, {0x01f1,0x0028,"ELSCINT1",VR::DS,VM::VM1,"Table Increment",false }, @@ -2194,6 +2839,9 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x01f7,0x008b,"ELSCINT1",VR::OW,VM::VM1,"?",false }, {0x01f7,0x0091,"ELSCINT1",VR::OW,VM::VM1,"?",false }, {0x01f7,0x0095,"ELSCINT1",VR::OW,VM::VM1,"?",false }, + {0x01f7,0x0097,"ELSCINT1",VR::UN,VM::VM1,"?",false }, + {0x01f7,0x0099,"ELSCINT1",VR::UN,VM::VM1,"?",false }, + {0x01f7,0x009b,"ELSCINT1",VR::IS,VM::VM1,"iDose Level",false }, {0x01f9,0x0001,"ELSCINT1",VR::LO,VM::VM1,"SP Filter (private)",false }, {0x01f9,0x0004,"ELSCINT1",VR::IS,VM::VM1,"Adaptive Filter (private)",false }, {0x01f9,0x0005,"ELSCINT1",VR::IS,VM::VM1,"Recon Increatment (private)",false }, @@ -2313,9 +2961,11 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x07a1,0x0042,"ELSCINT1",VR::SH,VM::VM1,"?",false }, {0x07a1,0x0043,"ELSCINT1",VR::IS,VM::VM1,"?",false }, {0x07a1,0x0047,"ELSCINT1",VR::CS,VM::VM1,"?orientation?",false }, + {0x07a1,0x004a,"ELSCINT1",VR::SH,VM::VM1,"?name?",false }, {0x07a1,0x0050,"ELSCINT1",VR::US,VM::VM1,"Tamar Site Id",false }, {0x07a1,0x0056,"ELSCINT1",VR::US,VM::VM1,"?",false }, {0x07a1,0x0058,"ELSCINT1",VR::CS,VM::VM1,"?",false }, + {0x07a1,0x005a,"ELSCINT1",VR::CS,VM::VM1,"?",false }, {0x07a1,0x005d,"ELSCINT1",VR::DT,VM::VM1,"?",false }, {0x07a1,0x005f,"ELSCINT1",VR::CS,VM::VM1,"?",false }, {0x07a1,0x0070,"ELSCINT1",VR::SH,VM::VM1,"?patient name?",false }, @@ -2325,8 +2975,13 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x07a1,0x0088,"ELSCINT1",VR::CS,VM::VM1,"?Y/N?",false }, {0x07a1,0x0098,"ELSCINT1",VR::CS,VM::VM1,"?Y/N?",false }, {0x07a1,0x009f,"ELSCINT1",VR::CS,VM::VM1,"?",false }, - {0x07a1,0x00a7,"ELSCINT1",VR::SH,VM::VM1,"?",false }, + {0x07a1,0x00a7,"ELSCINT1",VR::CS,VM::VM1,"?",false }, + {0x07a1,0x00c0,"ELSCINT1",VR::ST,VM::VM1,"?",false }, + {0x07a1,0x00c1,"ELSCINT1",VR::ST,VM::VM1,"?",false }, {0x07a1,0x00c2,"ELSCINT1",VR::ST,VM::VM1,"?status sent?",false }, + {0x07a1,0x00c8,"ELSCINT1",VR::ST,VM::VM1,"?",false }, + {0x07a1,0x00c9,"ELSCINT1",VR::ST,VM::VM1,"?",false }, + {0x07a1,0x00ca,"ELSCINT1",VR::ST,VM::VM1,"?",false }, {0x07a1,0x00d0,"ELSCINT1",VR::LO,VM::VM1,"?",false }, {0x07a3,0x0001,"ELSCINT1",VR::LO,VM::VM1,"Tamar Exe Software Version",false }, {0x07a3,0x0003,"ELSCINT1",VR::CS,VM::VM1,"Tamar Study Has Sticky Note",false }, @@ -2337,16 +2992,21 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x07a3,0x0014,"ELSCINT1",VR::ST,VM::VM1,"?num?",false }, {0x07a3,0x0015,"ELSCINT1",VR::ST,VM::VM1,"?hosp. service name?",false }, {0x07a3,0x0017,"ELSCINT1",VR::SH,VM::VM1,"?num?",false }, + {0x07a3,0x0019,"ELSCINT1",VR::ST,VM::VM1,"?",false }, + {0x07a3,0x001a,"ELSCINT1",VR::ST,VM::VM1,"?",false }, {0x07a3,0x001b,"ELSCINT1",VR::ST,VM::VM1,"?num?",false }, {0x07a3,0x001c,"ELSCINT1",VR::ST,VM::VM1,"?patient name?",false }, {0x07a3,0x001d,"ELSCINT1",VR::ST,VM::VM1,"?radiologist name?",false }, {0x07a3,0x001e,"ELSCINT1",VR::ST,VM::VM1,"?num?",false }, {0x07a3,0x001f,"ELSCINT1",VR::ST,VM::VM1,"?",false }, + {0x07a3,0x0020,"ELSCINT1",VR::DA,VM::VM1,"?",false }, {0x07a3,0x0022,"ELSCINT1",VR::ST,VM::VM1,"?",false }, {0x07a3,0x0023,"ELSCINT1",VR::ST,VM::VM1,"?+sign?",false }, {0x07a3,0x0024,"ELSCINT1",VR::ST,VM::VM1,"?",false }, {0x07a3,0x0034,"ELSCINT1",VR::SH,VM::VM1,"Tamar Study Age",false }, + {0x07a3,0x0039,"ELSCINT1",VR::UL,VM::VM1,"?",false }, {0x07a3,0x0043,"ELSCINT1",VR::DS,VM::VM1_n,"?",false }, + {0x07a3,0x004c,"ELSCINT1",VR::ST,VM::VM1,"?",false }, {0x07a3,0x0052,"ELSCINT1",VR::LO,VM::VM1,"?",false }, {0x07a3,0x0055,"ELSCINT1",VR::SH,VM::VM1,"?",false }, {0x07a3,0x005c,"ELSCINT1",VR::ST,VM::VM1,"?",false }, @@ -2356,6 +3016,7 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x07a3,0x0064,"ELSCINT1",VR::IS,VM::VM1_n,"?",false }, {0x07a3,0x0065,"ELSCINT1",VR::CS,VM::VM1_n,"?yes/no bool?",false }, {0x07a3,0x0066,"ELSCINT1",VR::IS,VM::VM1,"?",false }, + {0x07a3,0x008c,"ELSCINT1",VR::CS,VM::VM1,"?",false }, {0x07a3,0x008f,"ELSCINT1",VR::CS,VM::VM1,"?",false }, {0x07a3,0x0099,"ELSCINT1",VR::CS,VM::VM1,"?yes/no bool?",false }, {0x07a3,0x009c,"ELSCINT1",VR::CS,VM::VM1,"?yes/no bool?",false }, @@ -2375,16 +3036,24 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x07a3,0x00ca,"ELSCINT1",VR::SQ,VM::VM1,"?network seq10?",false }, {0x07a3,0x00cb,"ELSCINT1",VR::SQ,VM::VM1,"?network seq11?",false }, {0x07a3,0x00cc,"ELSCINT1",VR::LO,VM::VM1,"Tamar Grid Token Version",false }, + {0x07a3,0x00ce,"ELSCINT1",VR::SQ,VM::VM1,"?",false }, {0x07a3,0x00e3,"ELSCINT1",VR::LO,VM::VM1,"?name?",false }, {0x07a3,0x00f2,"ELSCINT1",VR::CS,VM::VM1,"?",false }, {0x07a3,0x00fb,"ELSCINT1",VR::DT,VM::VM1,"?",false }, {0x07a5,0x0000,"ELSCINT1",VR::LO,VM::VM1,"?name?",false }, + {0x07a5,0x0010,"ELSCINT1",VR::UL,VM::VM1,"?",false }, {0x07a5,0x0054,"ELSCINT1",VR::DT,VM::VM1,"?",false }, {0x07a5,0x0056,"ELSCINT1",VR::CS,VM::VM1,"?",false }, + {0x07a5,0x0059,"ELSCINT1",VR::IS,VM::VM1,"?",false }, {0x07a5,0x0063,"ELSCINT1",VR::CS,VM::VM1_n,"?",false }, - {0x07a5,0x0069,"ELSCINT1",VR::LO,VM::VM1,"?",false }, + {0x07a5,0x0069,"ELSCINT1",VR::LO,VM::VM1,"?",false }, // AE sometimes ?? + {0x07a5,0x0072,"ELSCINT1",VR::DT,VM::VM1,"?",false }, {0x07a5,0x00ae,"ELSCINT1",VR::IS,VM::VM1,"?",false }, {0x07a5,0x00c8,"ELSCINT1",VR::CS,VM::VM1,"?",false }, + {0x07a5,0x00dc,"ELSCINT1",VR::UL,VM::VM1,"?",false }, + {0x07a5,0x00dd,"ELSCINT1",VR::FL,VM::VM1,"?",false }, + {0x07a5,0x00de,"ELSCINT1",VR::LO,VM::VM1,"?",false }, + {0x07a5,0x00e8,"ELSCINT1",VR::IS,VM::VM1,"?",false }, {0x5001,0x0070,"ELSCINT1",VR::SQ,VM::VM1,"?",false }, {0x5001,0x0071,"ELSCINT1",VR::SH,VM::VM1,"?",false }, {0x5001,0x0080,"ELSCINT1",VR::SQ,VM::VM1,"?",false }, @@ -2515,66 +3184,68 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0021,0x0070,"FDMS 1.0",VR::IS,VM::VM1,"Film Number within the Series",false }, {0x0021,0x0080,"FDMS 1.0",VR::OB,VM::VM1,"Equipment Type-Specific Information",false }, {0x0021,0x0090,"FDMS 1.0",VR::CS,VM::VM1,"LUT Number",false }, - {0x0023,0x0010,"FDMS 1.0",VR::SQ,VM::VM1,"?",false }, - {0x0023,0x0020,"FDMS 1.0",VR::SQ,VM::VM1,"?",false }, - {0x0023,0x0030,"FDMS 1.0",VR::SQ,VM::VM1,"?",false }, + {0x0023,0x0010,"FDMS 1.0",VR::SQ,VM::VM1,"Left-image Processing Parameter Sequence",false }, + {0x0023,0x0020,"FDMS 1.0",VR::SQ,VM::VM1,"Right-image Processing Parameter Sequence",false }, + {0x0023,0x0030,"FDMS 1.0",VR::SQ,VM::VM1,"Single-image Processing Parameter Sequence",false }, {0x0025,0x0010,"FDMS 1.0",VR::US,VM::VM1,"Relative Light Emission Amount Sk",false }, {0x0025,0x0011,"FDMS 1.0",VR::US,VM::VM1,"Term of Correction for Each IP Type St",false }, {0x0025,0x0012,"FDMS 1.0",VR::US,VM::VM1,"Reading Gain Gp",false }, - {0x0025,0x0013,"FDMS 1.0",VR::US,VM::VM1,"?",false }, - {0x0025,0x0015,"FDMS 1.0",VR::CS,VM::VM1,"?",false }, - {0x0025,0x0020,"FDMS 1.0",VR::US,VM::VM2,"?",false }, - {0x0025,0x0021,"FDMS 1.0",VR::US,VM::VM1,"?",false }, - {0x0025,0x0030,"FDMS 1.0",VR::US,VM::VM1,"?",false }, - {0x0025,0x0031,"FDMS 1.0",VR::SS,VM::VM1,"?",false }, - {0x0025,0x0032,"FDMS 1.0",VR::US,VM::VM1,"?",false }, - {0x0025,0x0033,"FDMS 1.0",VR::SS,VM::VM1,"?",false }, - {0x0025,0x0034,"FDMS 1.0",VR::SS,VM::VM1,"?",false }, - {0x0025,0x0040,"FDMS 1.0",VR::US,VM::VM1,"?",false }, - {0x0025,0x0041,"FDMS 1.0",VR::US,VM::VM1,"?",false }, - {0x0025,0x0042,"FDMS 1.0",VR::US,VM::VM1,"?",false }, - {0x0025,0x0043,"FDMS 1.0",VR::US,VM::VM1,"?",false }, - {0x0025,0x0050,"FDMS 1.0",VR::US,VM::VM1,"?",false }, - {0x0025,0x0051,"FDMS 1.0",VR::US,VM::VM1,"?",false }, - {0x0025,0x0052,"FDMS 1.0",VR::US,VM::VM1,"?",false }, - {0x0025,0x0053,"FDMS 1.0",VR::US,VM::VM1,"?",false }, - {0x0025,0x0060,"FDMS 1.0",VR::US,VM::VM1,"?",false }, - {0x0025,0x0061,"FDMS 1.0",VR::US,VM::VM1,"?",false }, - {0x0025,0x0062,"FDMS 1.0",VR::US,VM::VM1,"?",false }, - {0x0025,0x0063,"FDMS 1.0",VR::CS,VM::VM1,"?",false }, - {0x0025,0x0070,"FDMS 1.0",VR::US,VM::VM1,"?",false }, - {0x0025,0x0071,"FDMS 1.0",VR::US,VM::VM1,"?",false }, - {0x0025,0x0072,"FDMS 1.0",VR::US,VM::VM1,"?",false }, - {0x0025,0x0073,"FDMS 1.0",VR::US,VM::VM6,"?",false }, - {0x0025,0x0074,"FDMS 1.0",VR::US,VM::VM6,"?",false }, - {0x0025,0x0080,"FDMS 1.0",VR::US,VM::VM1,"?",false }, - {0x0025,0x0081,"FDMS 1.0",VR::US,VM::VM1,"?",false }, - {0x0025,0x0082,"FDMS 1.0",VR::US,VM::VM1,"?",false }, - {0x0025,0x0083,"FDMS 1.0",VR::US,VM::VM6,"?",false }, - {0x0025,0x0084,"FDMS 1.0",VR::US,VM::VM6,"?",false }, - {0x0025,0x0090,"FDMS 1.0",VR::US,VM::VM1,"?",false }, - {0x0025,0x0091,"FDMS 1.0",VR::US,VM::VM1,"?",false }, - {0x0025,0x0092,"FDMS 1.0",VR::US,VM::VM1,"?",false }, - {0x0025,0x0093,"FDMS 1.0",VR::US,VM::VM1,"?",false }, - {0x0025,0x0094,"FDMS 1.0",VR::US,VM::VM1,"?",false }, - {0x0025,0x0095,"FDMS 1.0",VR::US,VM::VM1,"?",false }, - {0x0025,0x0096,"FDMS 1.0",VR::CS,VM::VM1,"?",false }, - {0x0025,0x00a0,"FDMS 1.0",VR::US,VM::VM1,"?",false }, - {0x0025,0x00a1,"FDMS 1.0",VR::SS,VM::VM1,"?",false }, - {0x0025,0x00a2,"FDMS 1.0",VR::US,VM::VM1,"?",false }, - {0x0025,0x00a3,"FDMS 1.0",VR::SS,VM::VM1,"?",false }, - {0x0027,0x0010,"FDMS 1.0",VR::SQ,VM::VM1,"?",false }, - {0x0027,0x0020,"FDMS 1.0",VR::SQ,VM::VM1,"?",false }, - {0x0027,0x0030,"FDMS 1.0",VR::SQ,VM::VM1,"?",false }, - {0x0027,0x0040,"FDMS 1.0",VR::SQ,VM::VM1,"?",false }, - {0x0027,0x0050,"FDMS 1.0",VR::SQ,VM::VM1,"?",false }, - {0x0027,0x0060,"FDMS 1.0",VR::SQ,VM::VM1,"?",false }, - {0x0027,0x0070,"FDMS 1.0",VR::SQ,VM::VM1,"?",false }, - {0x0027,0x0080,"FDMS 1.0",VR::SQ,VM::VM1,"?",false }, - {0x0027,0x00a0,"FDMS 1.0",VR::IS,VM::VM1,"?",false }, - {0x0027,0x00a1,"FDMS 1.0",VR::CS,VM::VM2,"?",false }, - {0x0027,0x00a2,"FDMS 1.0",VR::CS,VM::VM2,"?",false }, - {0x0027,0x00a3,"FDMS 1.0",VR::SS,VM::VM1_n,"?",false }, + {0x0025,0x0013,"FDMS 1.0",VR::US,VM::VM1,"Latitude",false }, + {0x0025,0x0015,"FDMS 1.0",VR::CS,VM::VM1,"Image Processing Selection Flag",false }, + {0x0025,0x0016,"FDMS 1.0",VR::US,VM::VM1,"Min",false }, + {0x0025,0x0017,"FDMS 1.0",VR::US,VM::VM1,"Max",false }, + {0x0025,0x0020,"FDMS 1.0",VR::US,VM::VM2,"Sensitivity Shift (S-SHFT)",false }, + {0x0025,0x0021,"FDMS 1.0",VR::US,VM::VM1,"Contrast Shift (C-SHIFT)",false }, + {0x0025,0x0030,"FDMS 1.0",VR::US,VM::VM1,"GT",false }, + {0x0025,0x0031,"FDMS 1.0",VR::SS,VM::VM1,"GA",false }, + {0x0025,0x0032,"FDMS 1.0",VR::US,VM::VM1,"GC",false }, + {0x0025,0x0033,"FDMS 1.0",VR::SS,VM::VM1,"GS",false }, + {0x0025,0x0034,"FDMS 1.0",VR::SS,VM::VM1,"tan θ",false }, + {0x0025,0x0040,"FDMS 1.0",VR::US,VM::VM1,"RT",false }, + {0x0025,0x0041,"FDMS 1.0",VR::US,VM::VM1,"RN",false }, + {0x0025,0x0042,"FDMS 1.0",VR::US,VM::VM1,"RE",false }, + {0x0025,0x0043,"FDMS 1.0",VR::US,VM::VM1,"N",false }, + {0x0025,0x0050,"FDMS 1.0",VR::US,VM::VM1,"DRT",false }, + {0x0025,0x0051,"FDMS 1.0",VR::US,VM::VM1,"DRN",false }, + {0x0025,0x0052,"FDMS 1.0",VR::US,VM::VM1,"DRE",false }, + {0x0025,0x0053,"FDMS 1.0",VR::US,VM::VM1,"DN",false }, + {0x0025,0x0060,"FDMS 1.0",VR::US,VM::VM1,"ORN",false }, + {0x0025,0x0061,"FDMS 1.0",VR::US,VM::VM1,"ORE",false }, + {0x0025,0x0062,"FDMS 1.0",VR::US,VM::VM1,"ON",false }, + {0x0025,0x0063,"FDMS 1.0",VR::CS,VM::VM1,"ORD",false }, + {0x0025,0x0070,"FDMS 1.0",VR::US,VM::VM1,"MDT",false }, + {0x0025,0x0071,"FDMS 1.0",VR::US,VM::VM1,"MDB",false }, + {0x0025,0x0072,"FDMS 1.0",VR::US,VM::VM1,"MDE",false }, + {0x0025,0x0073,"FDMS 1.0",VR::US,VM::VM1_n,"MFP-DRC Suppression Characteristics Parameters",false }, + {0x0025,0x0074,"FDMS 1.0",VR::US,VM::VM1_n,"MFP-DRC Frequency Characteristics Parameters",false }, + {0x0025,0x0080,"FDMS 1.0",VR::US,VM::VM1,"MRT",false }, + {0x0025,0x0081,"FDMS 1.0",VR::US,VM::VM1,"MRB",false }, + {0x0025,0x0082,"FDMS 1.0",VR::US,VM::VM1,"MRE",false }, + {0x0025,0x0083,"FDMS 1.0",VR::US,VM::VM1_n,"MFP-USM Suppression Characteristics Parameters",false }, + {0x0025,0x0084,"FDMS 1.0",VR::US,VM::VM1_n,"MFP-USM Frequency Characteristics Parameters",false }, + {0x0025,0x0090,"FDMS 1.0",VR::US,VM::VM1,"PTE (α edge)",false }, + {0x0025,0x0091,"FDMS 1.0",VR::US,VM::VM1,"PTR (α calc)",false }, + {0x0025,0x0092,"FDMS 1.0",VR::US,VM::VM1,"PRN",false }, + {0x0025,0x0093,"FDMS 1.0",VR::US,VM::VM1,"PRE",false }, + {0x0025,0x0094,"FDMS 1.0",VR::US,VM::VM1,"PEM Sstd",false }, + {0x0025,0x0095,"FDMS 1.0",VR::US,VM::VM1,"PEM Lstd",false }, + {0x0025,0x0096,"FDMS 1.0",VR::CS,VM::VM1,"PEM Unsharp Mask Value N",false }, + {0x0025,0x00a0,"FDMS 1.0",VR::US,VM::VM1,"MFP GT",false }, + {0x0025,0x00a1,"FDMS 1.0",VR::SS,VM::VM1,"MFP GA",false }, + {0x0025,0x00a2,"FDMS 1.0",VR::US,VM::VM1,"MFP GC",false }, + {0x0025,0x00a3,"FDMS 1.0",VR::SS,VM::VM1,"MFP GS",false }, + {0x0027,0x0010,"FDMS 1.0",VR::SQ,VM::VM1,"γ Raw Data Table Sequence",false }, + {0x0027,0x0020,"FDMS 1.0",VR::SQ,VM::VM1,"β Raw Data Table Sequence",false }, + {0x0027,0x0030,"FDMS 1.0",VR::SQ,VM::VM1,"DRC Raw Data Table Sequence",false }, + {0x0027,0x0040,"FDMS 1.0",VR::SQ,VM::VM1,"MFP-DRC Raw Data Table Sequence",false }, + {0x0027,0x0050,"FDMS 1.0",VR::SQ,VM::VM1,"MFP-USM Raw Data Table Sequence",false }, + {0x0027,0x0060,"FDMS 1.0",VR::SQ,VM::VM1,"PEM α Edge Raw Data Table Sequence",false }, + {0x0027,0x0070,"FDMS 1.0",VR::SQ,VM::VM1,"PEM α Calc Raw Data Table Sequence",false }, + {0x0027,0x0080,"FDMS 1.0",VR::SQ,VM::VM1,"MFP γ Raw Data Table Sequence",false }, + {0x0027,0x00a0,"FDMS 1.0",VR::IS,VM::VM1,"No. of Data",false }, + {0x0027,0x00a1,"FDMS 1.0",VR::CS,VM::VM2,"Data Input Type",false }, + {0x0027,0x00a2,"FDMS 1.0",VR::CS,VM::VM2,"Data Output Type",false }, + {0x0027,0x00a3,"FDMS 1.0",VR::US_SS,VM::VM1_n,"Raw Data",false }, {0x0029,0x0020,"FDMS 1.0",VR::CS,VM::VM1,"Image Scanning Direction",false }, {0x0029,0x0025,"FDMS 1.0",VR::CS,VM::VM1,"Image Rotation/Reversal Information",false }, {0x0029,0x0030,"FDMS 1.0",VR::CS,VM::VM1,"Extended Reading Size Value",false }, @@ -2604,7 +3275,7 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0019,0x0070,"GE ??? From Adantage Review CS",VR::LO,VM::VM1,"CR Image Serial Number",false }, {0x0019,0x0080,"GE ??? From Adantage Review CS",VR::LO,VM::VM1,"CR Bar Code Number",false }, {0x0019,0x0090,"GE ??? From Adantage Review CS",VR::LO,VM::VM1,"CR Film Output Exposures",false }, - {0x0045,0x0067,"GE LUT Asymmetry Parameter",VR::DS,VM::VM1,"LUT Assymetry",false }, + {0x0045,0x0067,"GE LUT Asymmetry Parameter",VR::DS,VM::VM1,"LUT Asymmetry",false }, {0x0053,0x0020,"GEHC_CT_ADVAPP_001",VR::IS,VM::VM1,"ShuttleFlag",false }, {0x0053,0x0021,"GEHC_CT_ADVAPP_001",VR::IS,VM::VM1,"TableSpeedNotReachesTargetFlag",false }, {0x0053,0x0040,"GEHC_CT_ADVAPP_001",VR::SH,VM::VM1,"IterativeReconAnnotation",false }, @@ -2618,9 +3289,11 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0053,0x0065,"GEHC_CT_ADVAPP_001",VR::IS,VM::VM1,"Shutter Mode Percent",false }, {0x0053,0x0066,"GEHC_CT_ADVAPP_001",VR::LO,VM::VM1,"Image Browser Annotation",false }, {0x0053,0x0067,"GEHC_CT_ADVAPP_001",VR::IS,VM::VM1,"Overlapped Recon Flag",false }, - {0x0053,0x0068,"GEHC_CT_ADVAPP_001",VR::IS,VM::VM1,"Row Number Anotation Flag",false }, + {0x0053,0x0068,"GEHC_CT_ADVAPP_001",VR::IS,VM::VM1,"Row Number Annotation Flag",false }, {0x0053,0x006a,"GEHC_CT_ADVAPP_001",VR::IS,VM::VM1,"ODMFlag",false }, {0x0053,0x006b,"GEHC_CT_ADVAPP_001",VR::IS,VM::VM1,"ODMReductionPercent",false }, + {0x0053,0x006c,"GEHC_CT_ADVAPP_001",VR::DS,VM::VM1,"?",false }, + {0x0053,0x006d,"GEHC_CT_ADVAPP_001",VR::DS,VM::VM1,"?",false }, {0x0053,0x006f,"GEHC_CT_ADVAPP_001",VR::IS,VM::VM1,"ASiR Auto Guidance Dose Reduction Percent",false }, {0x0053,0x009d,"GEHC_CT_ADVAPP_001",VR::LO,VM::VM1,"MARsAnnotation",false }, {0x0009,0x0010,"GEIIS",VR::SQ,VM::VM1,"GE IIS Thumbnail Sequence",false }, @@ -3321,7 +3994,7 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0045,0x0062,"GEMS_FALCON_03",VR::IS,VM::VM1,"User Window Center",false }, {0x0045,0x0063,"GEMS_FALCON_03",VR::IS,VM::VM1,"User Window Width",false }, {0x0045,0x0065,"GEMS_FALCON_03",VR::IS,VM::VM1,"Requested Detector Entrance Dose",false }, - {0x0045,0x0067,"GEMS_FALCON_03",VR::DS,VM::VM3,"VOI LUT Assymmetry parameter beta",false }, + {0x0045,0x0067,"GEMS_FALCON_03",VR::DS,VM::VM3,"VOI LUT Asymmetry parameter beta",false }, {0x0045,0x0069,"GEMS_FALCON_03",VR::IS,VM::VM1,"Collimator rotation",false }, {0x0045,0x0072,"GEMS_FALCON_03",VR::DS,VM::VM1,"Collimator Width",false }, {0x0045,0x0073,"GEMS_FALCON_03",VR::DS,VM::VM1,"Collimator Height",false }, @@ -3337,6 +4010,7 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0051,0x000a,"GEMS_FUNCTOOL_01",VR::SL,VM::VM1,"Store level of Functional Image",false }, {0x0051,0x000b,"GEMS_FUNCTOOL_01",VR::FL,VM::VM1,"Store B-Value with Functional Image",false }, {0x0051,0x000c,"GEMS_FUNCTOOL_01",VR::LO,VM::VM1,"Analysis Package",false }, + {0x0051,0x000e,"GEMS_FUNCTOOL_01",VR::SL,VM::VM1,"?",false }, {0x7fdf,0x0010,"GEMS_GDXE_ATHENAV2_INTERNAL_USE",VR::LT,VM::VM1,"PPS Stream",false }, {0x7fdf,0x0011,"GEMS_GDXE_ATHENAV2_INTERNAL_USE",VR::LT,VM::VM1,"Pixel Data References (temporary)",false }, {0x7fdf,0x0020,"GEMS_GDXE_ATHENAV2_INTERNAL_USE",VR::SS,VM::VM1,"Auto Push Tag",false }, @@ -3414,6 +4088,7 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0009,0x0043,"GEMS_GENIE_1",VR::TM,VM::VM1,"Patient Creation Time",false }, {0x0009,0x0044,"GEMS_GENIE_1",VR::SL,VM::VM1,"Num Views Acquired (retired)",false }, {0x0009,0x0045,"GEMS_GENIE_1",VR::LT,VM::VM1,"Dataset UID List",false }, + {0x0009,0x0046,"GEMS_GENIE_1",VR::UI,VM::VM1,"?DataSet UID?",false }, {0x0011,0x000a,"GEMS_GENIE_1",VR::SL,VM::VM1,"Series Type",false }, {0x0011,0x000b,"GEMS_GENIE_1",VR::SL,VM::VM1,"Effective Series Duration",false }, {0x0011,0x000c,"GEMS_GENIE_1",VR::SL,VM::VM1,"Num Beats",false }, @@ -3699,17 +4374,26 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0045,0x001f,"GEMS_HELIOS_01",VR::SS,VM::VM1,"Cross Talk Calibration Date",false }, {0x0045,0x0020,"GEMS_HELIOS_01",VR::SS,VM::VM1,"Cross Talk Calibration Time",false }, {0x0045,0x0021,"GEMS_HELIOS_01",VR::SS,VM::VM1,"Iterbone Flag",false }, - {0x0045,0x0022,"GEMS_HELIOS_01",VR::SS,VM::VM1,"Perisstaltic Flag",false }, + {0x0045,0x0022,"GEMS_HELIOS_01",VR::SS,VM::VM1,"Peristaltic Flag",false }, {0x0045,0x0030,"GEMS_HELIOS_01",VR::CS,VM::VM1,"CardiacReconAlgorithm",false }, {0x0045,0x0031,"GEMS_HELIOS_01",VR::CS,VM::VM1,"AvgHeartRateForImage",false }, - {0x0045,0x0032,"GEMS_HELIOS_01",VR::FL,VM::VM1,"TemporalResolution",false }, + {0x0045,0x0032,"GEMS_HELIOS_01",VR::FL,VM::VM1,"Temporal Resolution",false }, {0x0045,0x0033,"GEMS_HELIOS_01",VR::CS,VM::VM1,"PctRpeakDelay",false }, {0x0045,0x0034,"GEMS_HELIOS_01",VR::CS,VM::VM1,"ActualPctRpeakDelay",false }, {0x0045,0x0036,"GEMS_HELIOS_01",VR::CS,VM::VM1,"EkgFullMaStartPhase",false }, {0x0045,0x0037,"GEMS_HELIOS_01",VR::CS,VM::VM1,"EkgFullMaEndPhase",false }, {0x0045,0x0038,"GEMS_HELIOS_01",VR::CS,VM::VM1,"EkgModulationMaxMa",false }, {0x0045,0x0039,"GEMS_HELIOS_01",VR::CS,VM::VM1,"EkgModulationMinMa",false }, - {0x0045,0x003b,"GEMS_HELIOS_01",VR::LO,VM::VM1,"NoiseReductionImageFilterDesc",false }, + {0x0045,0x003b,"GEMS_HELIOS_01",VR::LO,VM::VM1,"Noise Reduction Image Filter Description",false }, + {0x0045,0x003f,"GEMS_HELIOS_01",VR::IS,VM::VM1,"RPeakTimeDelay",false }, + {0x0045,0x0044,"GEMS_HELIOS_01",VR::IS,VM::VM1,"ActualRPeakTimeDelay",false }, + {0x0045,0x0045,"GEMS_HELIOS_01",VR::ST,VM::VM1,"CardiacScanOptions",false }, + {0x0045,0x0050,"GEMS_HELIOS_01",VR::FD,VM::VM1,"Temporal Center View Angle",false }, + {0x0045,0x0051,"GEMS_HELIOS_01",VR::FD,VM::VM1,"Recon Center View Angle",false }, + {0x0045,0x0052,"GEMS_HELIOS_01",VR::CS,VM::VM1,"WideCone Masking",false }, + {0x0045,0x0053,"GEMS_HELIOS_01",VR::FD,VM::VM1,"WideCone Corner Blending Radius",false }, + {0x0045,0x0054,"GEMS_HELIOS_01",VR::FD,VM::VM1,"WideCone Corner Blending Radius Offset",false }, + {0x0045,0x0055,"GEMS_HELIOS_01",VR::CS,VM::VM1,"Internal Recon Algorithm",false }, {0x004b,0x0001,"GEMS_HINO_CT_01",VR::DS,VM::VM1_n,"Beam Thickness",false }, {0x004b,0x0002,"GEMS_HINO_CT_01",VR::DS,VM::VM1_n,"R Time",false }, {0x004b,0x0003,"GEMS_HINO_CT_01",VR::IS,VM::VM1,"HBC number",false }, @@ -3954,6 +4638,7 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0043,0x00a4,"GEMS_PARM_01",VR::LO,VM::VM1,"Detailed text for ASL labeling technique",false }, {0x0043,0x00a5,"GEMS_PARM_01",VR::IS,VM::VM1,"Duration of the label or control pulse",false }, {0x0043,0x00a8,"GEMS_PARM_01",VR::DS,VM::VM3,"Dual Drive Mode, Amplitude Attenuation and Phase Offset ",false }, + {0x0043,0x00a9,"GEMS_PARM_01",VR::LO,VM::VM1,"?",false }, {0x0043,0x00aa,"GEMS_PARM_01",VR::LO,VM::VM1_n,"Additional Filtering Parameters",false }, {0x0043,0x00ab,"GEMS_PARM_01",VR::DS,VM::VM1_n,"Silenz Data",false }, {0x0043,0x00ac,"GEMS_PARM_01",VR::DS,VM::VM1_n,"QMAP Delay Data (RESERVED for FUTURE USE)",false }, @@ -3964,6 +4649,7 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0043,0x00b1,"GEMS_PARM_01",VR::SS,VM::VM1,"Excitation Mode",false }, {0x0043,0x00b2,"GEMS_PARM_01",VR::LO,VM::VM1_n,"MR Table Position Information",false }, {0x0043,0x00b3,"GEMS_PARM_01",VR::DS,VM::VM1_n,"Advanced Eddy Correction",false }, + {0x0043,0x00b5,"GEMS_PARM_01",VR::LO,VM::VM1,"?",false }, {0x0043,0x00b6,"GEMS_PARM_01",VR::LO,VM::VM1_n,"Multiband Parameters",false }, {0x0043,0x00b7,"GEMS_PARM_01",VR::LO,VM::VM4,"Compressed Sensing Parameters",false }, {0x0043,0x00b8,"GEMS_PARM_01",VR::DS,VM::VM1_n,"Grad Comp Parameters",false }, @@ -3971,6 +4657,18 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0043,0x00ba,"GEMS_PARM_01",VR::DS,VM::VM1,"Echo Spacing",false }, {0x0043,0x00bb,"GEMS_PARM_01",VR::LO,VM::VM1_n,"Pixel Information",false }, {0x0043,0x00bc,"GEMS_PARM_01",VR::IS,VM::VM1,"Heart Beats pattern",false }, + {0x0043,0x00c0,"GEMS_PARM_01",VR::DS,VM::VM1_n,"?",false }, + {0x0043,0x00c1,"GEMS_PARM_01",VR::LO,VM::VM1,"?",false }, + {0x0043,0x00c2,"GEMS_PARM_01",VR::LO,VM::VM1,"?",false }, + {0x0043,0x00c3,"GEMS_PARM_01",VR::LO,VM::VM1,"?some kind of xml?",false }, + {0x0043,0x00c4,"GEMS_PARM_01",VR::LO,VM::VM1,"?some kind of xml?",false }, + {0x0043,0x00c5,"GEMS_PARM_01",VR::LO,VM::VM1,"?",false }, + {0x0043,0x00c6,"GEMS_PARM_01",VR::DS,VM::VM1_n,"?",false }, + {0x0043,0x00c7,"GEMS_PARM_01",VR::DS,VM::VM1_n,"?",false }, + {0x0043,0x00c8,"GEMS_PARM_01",VR::UL,VM::VM1,"?",false }, + {0x0043,0x00c9,"GEMS_PARM_01",VR::IS,VM::VM1,"?",false }, + {0x0043,0x00cc,"GEMS_PARM_01",VR::DS,VM::VM1,"?",false }, + {0x0043,0x00cd,"GEMS_PARM_01",VR::FL,VM::VM1,"?",false }, {0x0051,0x000a,"GEMS_PARM_01",VR::SL,VM::VM1,"Store level of Functional Image",false }, {0x0051,0x000b,"GEMS_PARM_01",VR::FL,VM::VM1,"Store B-Value with Functional Image",false }, {0x2001,0x0010,"GEMS_PARM_01",VR::UI,VM::VM1,"DICOM Implementation UID",false }, @@ -4005,6 +4703,7 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x2001,0x00b0,"GEMS_PARM_01",VR::OB,VM::VM1,"DTI Parameters",false }, {0x2001,0x00c0,"GEMS_PARM_01",VR::OB,VM::VM1,"Paradigm Info",false }, {0x0011,0x0010,"GEMS_PATI_01",VR::SS,VM::VM1,"Patient Status",false }, + {0x0011,0x0030,"GEMS_PATI_01",VR::DS,VM::VM1,"?",false }, {0x0009,0x0001,"GEMS_PETD_01",VR::LO,VM::VM2,"GE Discovery PET Implementation Version Name",false }, {0x0009,0x0002,"GEMS_PETD_01",VR::LO,VM::VM1,"PET patient_id",false }, {0x0009,0x0003,"GEMS_PETD_01",VR::SH,VM::VM1,"PET compatible_version",false }, @@ -4131,7 +4830,7 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0009,0x007c,"GEMS_PETD_01",VR::SL,VM::VM1,"PET is_source",false }, {0x0009,0x007d,"GEMS_PETD_01",VR::SL,VM::VM1,"PET is_contents",false }, {0x0009,0x007e,"GEMS_PETD_01",VR::SL,VM::VM1,"PET is_type",false }, - {0x0009,0x007f,"GEMS_PETD_01",VR::DS,VM::VM3,"PET is_reference",false }, + {0x0009,0x007f,"GEMS_PETD_01",VR::DS,VM::VM1_n,"PET is_reference",false }, {0x0009,0x0080,"GEMS_PETD_01",VR::SL,VM::VM1,"PET multi_patient",false }, {0x0009,0x0081,"GEMS_PETD_01",VR::SL,VM::VM1,"PET number_of_normals",false }, {0x0009,0x0082,"GEMS_PETD_01",VR::UI,VM::VM1,"PET color_map_id",false }, @@ -4179,6 +4878,7 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0009,0x00ac,"GEMS_PETD_01",VR::FL,VM::VM1,"PET bp_center_y",false }, {0x0009,0x00ad,"GEMS_PETD_01",VR::UI,VM::VM1,"PET trans_frame_id",false }, {0x0009,0x00ae,"GEMS_PETD_01",VR::UI,VM::VM1,"PET tpluse_frame_id",false }, + {0x0009,0x00b0,"GEMS_PETD_01",VR::US,VM::VM1,"?",false }, {0x0009,0x00b1,"GEMS_PETD_01",VR::FL,VM::VM1,"PET profile_spacing",false }, {0x0009,0x00b2,"GEMS_PETD_01",VR::SS,VM::VM1,"PET ir_num_iterations",false }, {0x0009,0x00b3,"GEMS_PETD_01",VR::SS,VM::VM1,"PET ir_num_subsets",false }, @@ -4249,6 +4949,9 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0009,0x00f5,"GEMS_PETD_01",VR::DA,VM::VM1,"Date of Last Treatment",false }, {0x0009,0x00f8,"GEMS_PETD_01",VR::FL,VM::VM1,"Regularized Recon Beta",false }, {0x0009,0x00f9,"GEMS_PETD_01",VR::FL,VM::VM1,"Regularized Recon Gamma",false }, + {0x0009,0x00fa,"GEMS_PETD_01",VR::SL,VM::VM1,"?",false }, + {0x0009,0x00fb,"GEMS_PETD_01",VR::SL,VM::VM1,"?",false }, + {0x0009,0x00fc,"GEMS_PETD_01",VR::SL,VM::VM1,"?",false }, {0x0011,0x0001,"GEMS_PETD_01",VR::SQ,VM::VM1,"GE Advance ROI Sequence",false }, {0x0011,0x0002,"GEMS_PETD_01",VR::UI,VM::VM1,"GE Advance ROI.roi_id",false }, {0x0011,0x0003,"GEMS_PETD_01",VR::UI,VM::VM1,"GE Advance ROI.image_id",false }, @@ -4365,6 +5068,23 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0021,0x0002,"GEMS_PETD_01",VR::UL,VM::VM1,"PET raw_data_size",false }, {0x0023,0x0001,"GEMS_PETD_01",VR::OB,VM::VM1,"raw_data_blob",false }, {0x0023,0x0002,"GEMS_PETD_01",VR::OB,VM::VM1,"PET raw_data_blob",false }, + {0x0023,0x0017,"GEMS_PETD_01",VR::SQ,VM::VM1,"?",false }, + {0x0023,0x0019,"GEMS_PETD_01",VR::FL,VM::VM1,"?",false }, + {0x0023,0x001a,"GEMS_PETD_01",VR::FL,VM::VM1,"?",false }, + {0x0023,0x001b,"GEMS_PETD_01",VR::SL,VM::VM1,"?",false }, + {0x0023,0x001c,"GEMS_PETD_01",VR::SQ,VM::VM1,"?",false }, + {0x0023,0x001d,"GEMS_PETD_01",VR::SL,VM::VM1,"?",false }, + {0x0023,0x001e,"GEMS_PETD_01",VR::FL,VM::VM1,"?",false }, + {0x0023,0x002c,"GEMS_PETD_01",VR::UL,VM::VM1,"?",false }, + {0x0023,0x002d,"GEMS_PETD_01",VR::LO,VM::VM1,"?",false }, + {0x0023,0x002e,"GEMS_PETD_01",VR::LO,VM::VM1,"?",false }, + {0x0023,0x0031,"GEMS_PETD_01",VR::CS,VM::VM1,"?",false }, + {0x0023,0x0040,"GEMS_PETD_01",VR::SQ,VM::VM1,"?",false }, + {0x0023,0x0041,"GEMS_PETD_01",VR::LO,VM::VM1,"?",false }, + {0x0023,0x0042,"GEMS_PETD_01",VR::LO,VM::VM1,"?",false }, + {0x0023,0x0058,"GEMS_PETD_01",VR::SQ,VM::VM1,"?",false }, + {0x0023,0x0059,"GEMS_PETD_01",VR::LO,VM::VM1,"?",false }, + {0x0023,0x005a,"GEMS_PETD_01",VR::LO,VM::VM1,"?",false }, {0x5001,0x0001,"GEMS_PETD_01",VR::UI,VM::VM1,"GE Advance Curve.curve_id",false }, {0x5001,0x0002,"GEMS_PETD_01",VR::SH,VM::VM1,"GE Advance Curve.compatible_version",false }, {0x5001,0x0003,"GEMS_PETD_01",VR::SH,VM::VM1,"GE Advance Curve.software_version",false }, @@ -4993,6 +5713,9 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x3f01,0x0010,"INTELERAD MEDICAL SYSTEMS",VR::LO,VM::VM1,"ImsPostFix to AccessionNumber",false }, {0x3f01,0x0011,"INTELERAD MEDICAL SYSTEMS",VR::US,VM::VM1,"Count of tags present when CTN wrote the file",false }, {0x3f01,0x0012,"INTELERAD MEDICAL SYSTEMS",VR::UL,VM::VM1,"Association Epoch In Seconds",false }, + {0x3f01,0x0013,"INTELERAD MEDICAL SYSTEMS",VR::LO,VM::VM1,"?",false }, + {0x3f01,0x0014,"INTELERAD MEDICAL SYSTEMS",VR::LO,VM::VM1,"?",false }, + {0x3f01,0x001d,"INTELERAD MEDICAL SYSTEMS",VR::LO,VM::VM1,"?",false }, {0x3f03,0x0001,"INTELERAD MEDICAL SYSTEMS",VR::SQ,VM::VM1,"Attribute History",false }, {0x3f03,0x0002,"INTELERAD MEDICAL SYSTEMS",VR::DT,VM::VM1,"Change Timestamp",false }, {0x3f03,0x0003,"INTELERAD MEDICAL SYSTEMS",VR::LO,VM::VM1,"Change initiator",false }, @@ -5179,132 +5902,391 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0029,0x0011,"MITRA PRESENTATION 1.0",VR::CS,VM::VM1,"Breast Box y0",false }, {0x0029,0x0012,"MITRA PRESENTATION 1.0",VR::CS,VM::VM1,"Breast Box x1",false }, {0x0029,0x0013,"MITRA PRESENTATION 1.0",VR::CS,VM::VM1,"Breast Box y1",false }, - {0x0009,0x0048,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0009,0x004e,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0009,0x004f,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0011,0x0001,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0011,0x0002,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0019,0x0001,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0019,0x0002,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0019,0x0003,"MMCPrivate",VR::SH,VM::VM1,"?",false }, - {0x0019,0x0004,"MMCPrivate",VR::DS,VM::VM1,"?",false }, - {0x0019,0x0005,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0019,0x0007,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0019,0x0008,"MMCPrivate",VR::DS,VM::VM1,"?",false }, - {0x0019,0x0009,"MMCPrivate",VR::DS,VM::VM1,"?",false }, - {0x0019,0x000a,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0019,0x000b,"MMCPrivate",VR::DS,VM::VM1,"?",false }, - {0x0019,0x000c,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0019,0x000f,"MMCPrivate",VR::IS,VM::VM1,"?",false }, - {0x0019,0x0010,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0019,0x0011,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0019,0x001a,"MMCPrivate",VR::UI,VM::VM1,"?",false }, - {0x0019,0x001b,"MMCPrivate",VR::IS,VM::VM1,"?",false }, - {0x0019,0x001c,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0019,0x001d,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0019,0x001e,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0029,0x0001,"MMCPrivate",VR::IS,VM::VM1,"?",false }, - {0x0029,0x0002,"MMCPrivate",VR::IS,VM::VM1,"?",false }, - {0x0029,0x0005,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0029,0x0006,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0029,0x0008,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0029,0x0009,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0029,0x000a,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0029,0x000b,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0029,0x000c,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0029,0x000d,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0029,0x000e,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0029,0x000f,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0029,0x0010,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0029,0x0011,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0029,0x0012,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0029,0x0013,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0029,0x0014,"MMCPrivate",VR::LO,VM::VM1,"?MTR True/False?",false }, - {0x0029,0x0015,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0029,0x0016,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0029,0x0017,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0029,0x0018,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0029,0x001c,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0029,0x0020,"MMCPrivate",VR::IS,VM::VM1,"?",false }, - {0x0029,0x0021,"MMCPrivate",VR::DS,VM::VM1,"?",false }, - {0x0029,0x0022,"MMCPrivate",VR::ST,VM::VM1,"?",false }, - {0x0029,0x0023,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0029,0x0024,"MMCPrivate",VR::DS,VM::VM1,"?",false }, - {0x0029,0x0025,"MMCPrivate",VR::DS,VM::VM1,"?",false }, - {0x0029,0x0026,"MMCPrivate",VR::DS,VM::VM1,"?",false }, - {0x0029,0x0027,"MMCPrivate",VR::DS,VM::VM1,"?",false }, - {0x0029,0x0028,"MMCPrivate",VR::DS,VM::VM1,"?",false }, - {0x0029,0x0029,"MMCPrivate",VR::DS,VM::VM1,"?",false }, - {0x0029,0x002a,"MMCPrivate",VR::DS,VM::VM1,"?",false }, - {0x0029,0x002b,"MMCPrivate",VR::DS,VM::VM1,"?",false }, - {0x0029,0x002c,"MMCPrivate",VR::DS,VM::VM1,"?",false }, - {0x0029,0x002d,"MMCPrivate",VR::DS,VM::VM1,"?",false }, - {0x0029,0x002e,"MMCPrivate",VR::DS,VM::VM1,"?",false }, - {0x0029,0x002f,"MMCPrivate",VR::OB_OW,VM::VM1,"?HitachiMedical.Dream.Cabinet.ApplicationObjects.ImageAppData?",false }, - {0x0029,0x0031,"MMCPrivate",VR::SQ,VM::VM1,"?",false }, - {0x0029,0x0032,"MMCPrivate",VR::SQ,VM::VM1,"?",false }, - {0x0029,0x0050,"MMCPrivate",VR::SQ,VM::VM1,"?",false }, - {0x0029,0x0055,"MMCPrivate",VR::SQ,VM::VM1,"?",false }, - {0x0029,0x0056,"MMCPrivate",VR::CS,VM::VM1,"?",false }, - {0x0029,0x0057,"MMCPrivate",VR::SQ,VM::VM1,"?",false }, - {0x0029,0x005c,"MMCPrivate",VR::SQ,VM::VM1,"?",false }, - {0x0029,0x005d,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0029,0x005e,"MMCPrivate",VR::SQ,VM::VM1,"?",false }, - {0x0029,0x005f,"MMCPrivate",VR::FD,VM::VM1,"?",false }, - {0x0029,0x0060,"MMCPrivate",VR::SQ,VM::VM1,"?",false }, - {0x0029,0x0063,"MMCPrivate",VR::SQ,VM::VM1,"?",false }, - {0x0029,0x0065,"MMCPrivate",VR::FD,VM::VM1,"?",false }, - {0x0029,0x0066,"MMCPrivate",VR::CS,VM::VM1,"?",false }, - {0x0029,0x0068,"MMCPrivate",VR::CS,VM::VM1,"?",false }, - {0x0029,0x006a,"MMCPrivate",VR::CS,VM::VM1,"?",false }, - {0x0029,0x006b,"MMCPrivate",VR::CS,VM::VM1,"?",false }, - {0x0029,0x0070,"MMCPrivate",VR::SQ,VM::VM1,"?",false }, - {0x0029,0x0073,"MMCPrivate",VR::CS,VM::VM1,"?",false }, - {0x0029,0x0082,"MMCPrivate",VR::SQ,VM::VM1,"?",false }, - {0x0029,0x0083,"MMCPrivate",VR::US,VM::VM1,"?",false }, - {0x0029,0x0084,"MMCPrivate",VR::US,VM::VM1,"?",false }, - {0x0029,0x0086,"MMCPrivate",VR::FD,VM::VM1,"?",false }, - {0x0029,0x0087,"MMCPrivate",VR::SQ,VM::VM1,"?",false }, - {0x0029,0x0088,"MMCPrivate",VR::US,VM::VM1,"?",false }, - {0x0029,0x0089,"MMCPrivate",VR::US,VM::VM1,"?",false }, - {0x0029,0x008a,"MMCPrivate",VR::US,VM::VM1,"?",false }, - {0x0029,0x008b,"MMCPrivate",VR::SQ,VM::VM1,"?",false }, - {0x0029,0x008f,"MMCPrivate",VR::SQ,VM::VM1,"?",false }, - {0x0029,0x0090,"MMCPrivate",VR::FD,VM::VM1,"?",false }, - {0x0029,0x0091,"MMCPrivate",VR::SQ,VM::VM1,"?",false }, - {0x0029,0x0093,"MMCPrivate",VR::SQ,VM::VM1,"?",false }, - {0x0029,0x0098,"MMCPrivate",VR::SQ,VM::VM1,"?",false }, - {0x0029,0x0099,"MMCPrivate",VR::CS,VM::VM1,"?",false }, - {0x0029,0x009a,"MMCPrivate",VR::CS,VM::VM1,"?",false }, - {0x0029,0x009b,"MMCPrivate",VR::CS,VM::VM1,"?",false }, - {0x0029,0x009c,"MMCPrivate",VR::FD,VM::VM1,"?",false }, - {0x0029,0x009d,"MMCPrivate",VR::FD,VM::VM1,"?",false }, - {0x0029,0x009e,"MMCPrivate",VR::FD,VM::VM1,"?",false }, - {0x0029,0x009f,"MMCPrivate",VR::SS,VM::VM1,"?",false }, - {0x0029,0x00a0,"MMCPrivate",VR::FD,VM::VM1,"?",false }, - {0x0029,0x00a1,"MMCPrivate",VR::FD,VM::VM1,"?",false }, - {0x0029,0x00a3,"MMCPrivate",VR::DS,VM::VM1,"?",false }, - {0x0029,0x00a4,"MMCPrivate",VR::SQ,VM::VM1,"?",false }, - {0x0029,0x00a6,"MMCPrivate",VR::FD,VM::VM1,"?",false }, - {0x0029,0x00a7,"MMCPrivate",VR::FD,VM::VM1,"?",false }, - {0x0029,0x00a8,"MMCPrivate",VR::SQ,VM::VM1,"?",false }, - {0x0029,0x003c,"MMCPrivate",VR::UL,VM::VM1,"?",false }, - {0x0029,0x003d,"MMCPrivate",VR::US,VM::VM1,"?",false }, - {0x0029,0x003f,"MMCPrivate",VR::US,VM::VM1,"?",false }, - {0x0029,0x0042,"MMCPrivate",VR::FD,VM::VM1,"?",false }, - {0x0029,0x0044,"MMCPrivate",VR::IS,VM::VM1,"?",false }, - {0x0029,0x0045,"MMCPrivate",VR::IS,VM::VM1,"?",false }, - {0x0029,0x0046,"MMCPrivate",VR::IS,VM::VM1,"?",false }, - {0x0029,0x0047,"MMCPrivate",VR::IS,VM::VM1,"?",false }, - {0x0029,0x0062,"MMCPrivate",VR::CS,VM::VM1,"?",false }, - {0x0029,0x0075,"MMCPrivate",VR::CS,VM::VM1,"?",false }, - {0x0029,0x0078,"MMCPrivate",VR::CS,VM::VM1,"?",false }, - {0x0029,0x0079,"MMCPrivate",VR::CS,VM::VM1,"?",false }, - {0x0029,0x007a,"MMCPrivate",VR::CS,VM::VM1,"?",false }, - {0x0029,0x007b,"MMCPrivate",VR::CS,VM::VM1,"?",false }, - {0x0029,0x007d,"MMCPrivate",VR::CS,VM::VM1,"?",false }, - {0x0029,0x00d0,"MMCPrivate",VR::LO,VM::VM1,"?",false }, - {0x0029,0x00d6,"MMCPrivate",VR::LO,VM::VM1,"?",false }, + {0x0009,0x0000,"MMCPrivate",VR::LO,VM::VM1,"Private Creator",false }, + {0x0009,0x0001,"MMCPrivate",VR::LO,VM::VM1,"Technologist",false }, + {0x0009,0x0002,"MMCPrivate",VR::LO,VM::VM1,"ScheduledStudyDateTime",false }, + {0x0009,0x0003,"MMCPrivate",VR::OB,VM::VM1,"StudyAppData",false }, + {0x0009,0x0004,"MMCPrivate",VR::UI,VM::VM1,"ProtocolObjectID",false }, + {0x0009,0x0005,"MMCPrivate",VR::LO,VM::VM1,"Name",false }, + {0x0009,0x0006,"MMCPrivate",VR::IS,VM::VM1,"Frequency",false }, + {0x0009,0x0007,"MMCPrivate",VR::SH,VM::VM1,"UpdateFlag",false }, + {0x0009,0x0008,"MMCPrivate",VR::SH,VM::VM1,"Directory",false }, + {0x0009,0x0009,"MMCPrivate",VR::LO,VM::VM1,"Comments",false }, + {0x0009,0x000a,"MMCPrivate",VR::LO,VM::VM1,"Region",false }, + {0x0009,0x000b,"MMCPrivate",VR::SH,VM::VM1,"Laterality",false }, + {0x0009,0x000c,"MMCPrivate",VR::TM,VM::VM1,"TotalScanTime",false }, + {0x0009,0x000d,"MMCPrivate",VR::LO,VM::VM1,"ContrastMedium",false }, + {0x0009,0x000e,"MMCPrivate",VR::LO,VM::VM1,"CreateDateTime",false }, + {0x0009,0x000f,"MMCPrivate",VR::LO,VM::VM1,"Creator",false }, + {0x0009,0x0010,"MMCPrivate",VR::LO,VM::VM1,"SiteName",false }, + {0x0009,0x0011,"MMCPrivate",VR::LO,VM::VM1,"ReferringPhysician",false }, + {0x0009,0x0012,"MMCPrivate",VR::LO,VM::VM1,"Radiologist",false }, + {0x0009,0x0013,"MMCPrivate",VR::LO,VM::VM1,"Technologist",false }, + {0x0009,0x0014,"MMCPrivate",VR::UI,VM::VM1,"ProtocolUid",false }, + {0x0009,0x0015,"MMCPrivate",VR::SH,VM::VM1,"IsInLibrary",false }, + {0x0009,0x0016,"MMCPrivate",VR::LO,VM::VM1,"Gating",false }, + {0x0009,0x0017,"MMCPrivate",VR::ST,VM::VM1,"Note",false }, + {0x0009,0x0018,"MMCPrivate",VR::IS,VM::VM1,"NumberOfTasks",false }, + {0x0009,0x0019,"MMCPrivate",VR::SH,VM::VM1,"IsFlagRaised",false }, + {0x0009,0x001a,"MMCPrivate",VR::SH,VM::VM1,"IsArchived",false }, + {0x0009,0x001b,"MMCPrivate",VR::SH,VM::VM1,"IsDefault",false }, + {0x0009,0x001c,"MMCPrivate",VR::OB,VM::VM1,"ProtocolAppData",false }, + {0x0009,0x001d,"MMCPrivate",VR::SH,VM::VM1,"IsAllowCascadeSave",false }, + {0x0009,0x001e,"MMCPrivate",VR::SH,VM::VM1,"IsAllowCascadeProtect",false }, + {0x0009,0x001f,"MMCPrivate",VR::SQ,VM::VM1,"TaskInfo",false }, + {0x0009,0x0020,"MMCPrivate",VR::UI,VM::VM1,"TaskInfoObjectID",false }, + {0x0009,0x0021,"MMCPrivate",VR::LO,VM::VM1,"Name",false }, + {0x0009,0x0022,"MMCPrivate",VR::SH,VM::VM1,"TaskStatus",false }, + {0x0009,0x0023,"MMCPrivate",VR::SH,VM::VM1,"TaskPriority",false }, + {0x0009,0x0024,"MMCPrivate",VR::SH,VM::VM1,"Leaf",false }, + {0x0009,0x0025,"MMCPrivate",VR::LO,VM::VM1,"TaskID",false }, + {0x0009,0x0026,"MMCPrivate",VR::IS,VM::VM1,"Frequency",false }, + {0x0009,0x0027,"MMCPrivate",VR::SH,VM::VM1,"UpdateFlag",false }, + {0x0009,0x0028,"MMCPrivate",VR::SH,VM::VM1,"Directory",false }, + {0x0009,0x0029,"MMCPrivate",VR::LO,VM::VM1,"Comments",false }, + {0x0009,0x002a,"MMCPrivate",VR::SH,VM::VM1,"Category",false }, + {0x0009,0x002b,"MMCPrivate",VR::LO,VM::VM1,"Region",false }, + {0x0009,0x002c,"MMCPrivate",VR::SH,VM::VM1,"Laterality",false }, + {0x0009,0x002d,"MMCPrivate",VR::TM,VM::VM1,"ScanTime",false }, + {0x0009,0x002e,"MMCPrivate",VR::LO,VM::VM1,"ContrastMedium",false }, + {0x0009,0x002f,"MMCPrivate",VR::LO,VM::VM1,"CreateDateTime",false }, + {0x0009,0x0030,"MMCPrivate",VR::LO,VM::VM1,"Creator",false }, + {0x0009,0x0031,"MMCPrivate",VR::LO,VM::VM1,"SiteName",false }, + {0x0009,0x0032,"MMCPrivate",VR::LO,VM::VM1,"ReferringPhysician",false }, + {0x0009,0x0033,"MMCPrivate",VR::LO,VM::VM1,"Radiologist",false }, + {0x0009,0x0034,"MMCPrivate",VR::LO,VM::VM1,"Technologist",false }, + {0x0009,0x0035,"MMCPrivate",VR::UI,VM::VM1,"TaskUid",false }, + {0x0009,0x0036,"MMCPrivate",VR::UI,VM::VM1,"TaskInfoUid",false }, + {0x0009,0x0037,"MMCPrivate",VR::SH,VM::VM1,"IsInLibrary",false }, + {0x0009,0x0038,"MMCPrivate",VR::IS,VM::VM1,"TaskOrder",false }, + {0x0009,0x0039,"MMCPrivate",VR::LO,VM::VM1,"Gating",false }, + {0x0009,0x003a,"MMCPrivate",VR::SH,VM::VM1,"Plane",false }, + {0x0009,0x003b,"MMCPrivate",VR::LO,VM::VM1,"SequenceType",false }, + {0x0009,0x003c,"MMCPrivate",VR::SH,VM::VM1,"IsExecutive",false }, + {0x0009,0x003d,"MMCPrivate",VR::ST,VM::VM1,"Note",false }, + {0x0009,0x003e,"MMCPrivate",VR::SH,VM::VM1,"AutoStart",false }, + {0x0009,0x003f,"MMCPrivate",VR::SH,VM::VM1,"AutoSave",false }, + {0x0009,0x0040,"MMCPrivate",VR::SH,VM::VM1,"AutoArchive",false }, + {0x0009,0x0041,"MMCPrivate",VR::IS,VM::VM1,"QueueGroupID",false }, + {0x0009,0x0042,"MMCPrivate",VR::SH,VM::VM1,"IsFlagRaised",false }, + {0x0009,0x0043,"MMCPrivate",VR::SH,VM::VM1,"IsArchived",false }, + {0x0009,0x0044,"MMCPrivate",VR::SH,VM::VM1,"IsDefault",false }, + {0x0009,0x0045,"MMCPrivate",VR::OB,VM::VM1,"TaskInfoAppData",false }, + {0x0009,0x0046,"MMCPrivate",VR::SH,VM::VM1,"IsAllowCascadeSave",false }, + {0x0009,0x0047,"MMCPrivate",VR::SH,VM::VM1,"IsAllowCascadeProtect",false }, + {0x0009,0x0048,"MMCPrivate",VR::LO,VM::VM1,"ProtocolName",false }, + {0x0009,0x004e,"MMCPrivate",VR::LO,VM::VM1,"Cms_BodyPartExamined",false }, + {0x0009,0x004f,"MMCPrivate",VR::LO,VM::VM1,"IsProtected",false }, + {0x0009,0x0050,"MMCPrivate",VR::OB,VM::VM1,"?StudyReservationInfo",false }, + {0x0009,0x0051,"MMCPrivate",VR::LO,VM::VM1,"Cmi_contrastBolusAgent",false }, + {0x0009,0x0052,"MMCPrivate",VR::LO,VM::VM1,"Cms_institutionName",false }, + {0x0009,0x0053,"MMCPrivate",VR::LO,VM::VM1,"Cms_institutionalDepartmentName",false }, + {0x0009,0x0054,"MMCPrivate",VR::LO,VM::VM1,"Cms_seriesDescription",false }, + {0x0009,0x0055,"MMCPrivate",VR::LO,VM::VM1,"Cms_operatorsName",false }, + {0x0009,0x0056,"MMCPrivate",VR::LO,VM::VM1,"Cms_PerformingPhysiciansName",false }, + {0x0009,0x0057,"MMCPrivate",VR::ST,VM::VM1,"Cms_institutionAddress",false }, + {0x0009,0x0058,"MMCPrivate",VR::LO,VM::VM1,"Cmi_imageComments",false }, + {0x0009,0x0059,"MMCPrivate",VR::LO,VM::VM1,"Cmi_instanceCreationDateTime",false }, + {0x0009,0x005a,"MMCPrivate",VR::LO,VM::VM1,"MppsStepStatus",false }, + {0x0009,0x005b,"MMCPrivate",VR::IS,VM::VM1,"FilmedCount",false }, + {0x0009,0x005c,"MMCPrivate",VR::LO,VM::VM1,"IsAllowCascadeSave",false }, + {0x0009,0x005d,"MMCPrivate",VR::LO,VM::VM1,"IsAllowCascadeProtect",false }, + {0x0009,0x005e,"MMCPrivate",VR::LO,VM::VM1,"IsDeleted",false }, + {0x0009,0x005f,"MMCPrivate",VR::UI,VM::VM1,"ProtocolObjectID",false }, + {0x0009,0x0060,"MMCPrivate",VR::OB,VM::VM1,"TaskInfoAppData",false }, + {0x0009,0x0072,"MMCPrivate",VR::UI,VM::VM1,"ProtocolTaskInfoObjectID",false }, + {0x0009,0x0073,"MMCPrivate",VR::IS,VM::VM1,"ProtocolTaskOrder",false }, + {0x0009,0x0074,"MMCPrivate",VR::UI,VM::VM1,"ProtocolTaskUid",false }, + {0x0009,0x0075,"MMCPrivate",VR::OB,VM::VM1,"ProtocolTaskAppData",false }, + {0x0009,0x0076,"MMCPrivate",VR::SH,VM::VM1,"ProtocolTaskIsAllowCascadeSave",false }, + {0x0009,0x0077,"MMCPrivate",VR::SH,VM::VM1,"ProtocolTaskIsAllowCascadeProtect",false }, + {0x0011,0x0000,"MMCPrivate",VR::LO,VM::VM1,"Private Creator",false }, + {0x0011,0x0001,"MMCPrivate",VR::LO,VM::VM1,"IsRapidRegistration",false }, + {0x0011,0x0002,"MMCPrivate",VR::LO,VM::VM1,"IsProtected",false }, + {0x0011,0x0003,"MMCPrivate",VR::IS,VM::VM1,"FilmedCount",false }, + {0x0011,0x0004,"MMCPrivate",VR::OB,VM::VM1,"ApplicationData",false }, + {0x0011,0x0005,"MMCPrivate",VR::LO,VM::VM1,"IsAllowCascadeSave",false }, + {0x0011,0x0006,"MMCPrivate",VR::LO,VM::VM1,"IsAllowCascadeProtect",false }, + {0x0011,0x0007,"MMCPrivate",VR::LO,VM::VM1,"IsDeleted",false }, + {0x0019,0x0000,"MMCPrivate",VR::LO,VM::VM1,"Private Creator",false }, + {0x0019,0x0001,"MMCPrivate",VR::LO,VM::VM1,"ProcType",false }, + {0x0019,0x0002,"MMCPrivate",VR::LO,VM::VM1,"Plane",false }, + {0x0019,0x0003,"MMCPrivate",VR::SH,VM::VM1,"IsSnapShotSeries",false }, + {0x0019,0x0004,"MMCPrivate",VR::DS,VM::VM1,"MaxFsColor",false }, + {0x0019,0x0005,"MMCPrivate",VR::LO,VM::VM1,"SeriesCategoryType",false }, + {0x0019,0x0007,"MMCPrivate",VR::LO,VM::VM1,"ImageContrastBolusAgent",false }, + {0x0019,0x0008,"MMCPrivate",VR::DS,VM::VM1,"ImageSliceThickness",false }, + {0x0019,0x0009,"MMCPrivate",VR::DS,VM::VM1,"ImageReconstructionDiameter",false }, + {0x0019,0x000a,"MMCPrivate",VR::LO,VM::VM1,"ImageEchoTime",false }, + {0x0019,0x000b,"MMCPrivate",VR::DS,VM::VM1,"ImageRepetitionTime",false }, + {0x0019,0x000c,"MMCPrivate",VR::LO,VM::VM1,"SequenceType",false }, + {0x0019,0x000d,"MMCPrivate",VR::LO,VM::VM1,"TaskUid",false }, + {0x0019,0x000e,"MMCPrivate",VR::OB,VM::VM1,"SeriesAppData",false }, + {0x0019,0x000f,"MMCPrivate",VR::IS,VM::VM1,"MultiSliceNumber",false }, + {0x0019,0x0010,"MMCPrivate",VR::LO,VM::VM1,"ImageScanTime",false }, + {0x0019,0x0011,"MMCPrivate",VR::LO,VM::VM1,"IsProtected",false }, + {0x0019,0x0012,"MMCPrivate",VR::IS,VM::VM1,"ImageIncrement",false }, + {0x0019,0x0013,"MMCPrivate",VR::LO,VM::VM1,"MppsStepStatus",false }, + {0x0019,0x0014,"MMCPrivate",VR::IS,VM::VM1,"StorageCommittedCount",false }, + {0x0019,0x0015,"MMCPrivate",VR::IS,VM::VM1,"ArchivedCount",false }, + {0x0019,0x0016,"MMCPrivate",VR::IS,VM::VM1,"TransferredCount",false }, + {0x0019,0x0017,"MMCPrivate",VR::LO,VM::VM1,"IsAllowCascadeSave",false }, + {0x0019,0x0018,"MMCPrivate",VR::LO,VM::VM1,"IsAllowCascadeProtect",false }, + {0x0019,0x0019,"MMCPrivate",VR::LO,VM::VM1,"IsDeleted",false }, + {0x0019,0x001a,"MMCPrivate",VR::UI,VM::VM1,"CharacterizedImageInstanceUid",false }, + {0x0019,0x001b,"MMCPrivate",VR::IS,VM::VM1,"CharacterizedImageCount",false }, + {0x0019,0x001c,"MMCPrivate",VR::LO,VM::VM1,"InternalWindowWidth",false }, + {0x0019,0x001d,"MMCPrivate",VR::LO,VM::VM1,"InternalWindowLevel",false }, + {0x0019,0x001e,"MMCPrivate",VR::LO,VM::VM1,"?FlipAngle?",false }, + {0x0019,0x001f,"MMCPrivate",VR::LO,VM::VM1,"?InversionTime?",false }, + {0x0019,0x0020,"MMCPrivate",VR::UI,VM::VM1,"MultiFrameSopInstanceUid",false }, + {0x0019,0x0021,"MMCPrivate",VR::OB,VM::VM1,"?ScanInterface.GroupParamArchive",false }, + {0x0029,0x0000,"MMCPrivate",VR::LO,VM::VM1,"Private Creator",false }, + {0x0029,0x0001,"MMCPrivate",VR::IS,VM::VM1,"SliceNumber",false }, + {0x0029,0x0002,"MMCPrivate",VR::IS,VM::VM1,"PhaseNumber",false }, + {0x0029,0x0003,"MMCPrivate",VR::LO,VM::VM1,"ProcType",false }, + {0x0029,0x0004,"MMCPrivate",VR::LO,VM::VM1,"StopwatchTime",false }, + {0x0029,0x0005,"MMCPrivate",VR::LO,VM::VM1,"Plane",false }, + {0x0029,0x0006,"MMCPrivate",VR::LO,VM::VM1,"ScanTime",false }, + {0x0029,0x0008,"MMCPrivate",VR::LO,VM::VM1,"DualSliceFlag",false }, + {0x0029,0x0009,"MMCPrivate",VR::LO,VM::VM1,"SspRatio",false }, + {0x0029,0x000a,"MMCPrivate",VR::LO,VM::VM1,"GatingSignalSource",false }, + {0x0029,0x000b,"MMCPrivate",VR::LO,VM::VM1,"Rephase",false }, + {0x0029,0x000c,"MMCPrivate",VR::LO,VM::VM1,"HalfEcho",false }, + {0x0029,0x000d,"MMCPrivate",VR::LO,VM::VM1,"RectFOVRatio",false }, + {0x0029,0x000e,"MMCPrivate",VR::LO,VM::VM1,"HalfScan",false }, + {0x0029,0x000f,"MMCPrivate",VR::LO,VM::VM1,"NumShots",false }, + {0x0029,0x0010,"MMCPrivate",VR::LO,VM::VM1,"ContrastAgent",false }, + {0x0029,0x0011,"MMCPrivate",VR::LO,VM::VM1,"EchoAllocation",false }, + {0x0029,0x0012,"MMCPrivate",VR::LO,VM::VM1,"NumEchoShift",false }, + {0x0029,0x0013,"MMCPrivate",VR::LO,VM::VM1,"FatSat",false }, + {0x0029,0x0014,"MMCPrivate",VR::LO,VM::VM1,"MTC",false }, + {0x0029,0x0015,"MMCPrivate",VR::LO,VM::VM1,"NumPreSat",false }, + {0x0029,0x0016,"MMCPrivate",VR::LO,VM::VM1,"TargetVelocity",false }, + {0x0029,0x0017,"MMCPrivate",VR::LO,VM::VM1,"VENCAxis",false }, + {0x0029,0x0018,"MMCPrivate",VR::LO,VM::VM1,"NumVENCDirection",false }, + {0x0029,0x001c,"MMCPrivate",VR::LO,VM::VM1,"IsScalableWindowLevel",false }, + {0x0029,0x001d,"MMCPrivate",VR::LO,VM::VM1,"ThreeDSettingLineAngle",false }, + {0x0029,0x001e,"MMCPrivate",VR::LO,VM::VM1,"MPGTotalAxis",false }, + {0x0029,0x001f,"MMCPrivate",VR::LO,VM::VM1,"MPGAxisNumber",false }, + {0x0029,0x0020,"MMCPrivate",VR::IS,VM::VM1,"MultiEchoNumber",false }, + {0x0029,0x0021,"MMCPrivate",VR::DS,VM::VM1,"NaviAverageGateWidth",false }, + {0x0029,0x0022,"MMCPrivate",VR::ST,VM::VM1,"ShimCompensateValue",false }, + {0x0029,0x0023,"MMCPrivate",VR::LO,VM::VM1,"GCOffset",false }, + {0x0029,0x0024,"MMCPrivate",VR::DS,VM::VM1,"NaviMaxGateWidth",false }, + {0x0029,0x0025,"MMCPrivate",VR::DS,VM::VM1,"NaviMinGateWidth",false }, + {0x0029,0x0026,"MMCPrivate",VR::DS,VM::VM1,"NaviMaxGatePosition",false }, + {0x0029,0x0027,"MMCPrivate",VR::DS,VM::VM1,"NaviMinGatePosition",false }, + {0x0029,0x0028,"MMCPrivate",VR::DS,VM::VM1,"TimeDuration",false }, + {0x0029,0x0029,"MMCPrivate",VR::DS,VM::VM1,"TablePosition",false }, + {0x0029,0x002a,"MMCPrivate",VR::DS,VM::VM1,"NaviInitialGateWidth",false }, + {0x0029,0x002b,"MMCPrivate",VR::DS,VM::VM1,"NaviFinalGateWidth",false }, + {0x0029,0x002c,"MMCPrivate",VR::DS,VM::VM1,"NaviInitialGatePosition",false }, + {0x0029,0x002d,"MMCPrivate",VR::DS,VM::VM1,"NaviFinalGatePosition",false }, + {0x0029,0x002e,"MMCPrivate",VR::DS,VM::VM1,"NaviAverageGatePosition",false }, + {0x0029,0x002f,"MMCPrivate",VR::OB,VM::VM1,"ImageAppData",false }, + {0x0029,0x0030,"MMCPrivate",VR::FD,VM::VM1,"DiffusionBValue",false }, + {0x0029,0x0031,"MMCPrivate",VR::SQ,VM::VM1,"SharedFunctionalGroupsSequence",false }, + {0x0029,0x0032,"MMCPrivate",VR::SQ,VM::VM1,"PerFrameFunctionalGroupsSequence",false }, + {0x0029,0x0033,"MMCPrivate",VR::DS,VM::VM1,"LossyImageCompressionRatio",false }, + {0x0029,0x0034,"MMCPrivate",VR::UI,VM::VM1,"InstanceCreatorUID",false }, + {0x0029,0x0035,"MMCPrivate",VR::UI,VM::VM1,"RelatedGeneralSOPClassUID",false }, + {0x0029,0x0036,"MMCPrivate",VR::UI,VM::VM1,"OriginalSpecializedSOPClassUID",false }, + {0x0029,0x0037,"MMCPrivate",VR::SH,VM::VM1,"TimezoneOffsetFromUTC",false }, + {0x0029,0x0038,"MMCPrivate",VR::CS,VM::VM1,"SOPInstanceStatus",false }, + {0x0029,0x0039,"MMCPrivate",VR::DT,VM::VM1,"SOPAuthorizationDateandTime",false }, + {0x0029,0x003a,"MMCPrivate",VR::LT,VM::VM1,"SOPAuthorizationComment",false }, + {0x0029,0x003b,"MMCPrivate",VR::LO,VM::VM1,"AuthorizationEquipmentCertificationNumber",false }, + {0x0029,0x003c,"MMCPrivate",VR::UL,VM::VM1,"ConcatenationFrameOffsetNumber",false }, + {0x0029,0x003d,"MMCPrivate",VR::US,VM::VM1,"RepresentativeFrameNumber",false }, + {0x0029,0x003e,"MMCPrivate",VR::UI,VM::VM1,"ConcatenationUID",false }, + {0x0029,0x003f,"MMCPrivate",VR::US,VM::VM1,"InConcatenationNumber",false }, + {0x0029,0x0040,"MMCPrivate",VR::CS,VM::VM1,"CardiacSynchronizationTechnique",false }, + {0x0029,0x0041,"MMCPrivate",VR::CS,VM::VM1,"CardiacSignalSource",false }, + {0x0029,0x0042,"MMCPrivate",VR::FD,VM::VM1,"CardiacRRIntervalSpecified",false }, + {0x0029,0x0043,"MMCPrivate",VR::CS,VM::VM1,"CardiacBeatRejectionTechnique",false }, + {0x0029,0x0044,"MMCPrivate",VR::IS,VM::VM1,"LowRRValue",false }, + {0x0029,0x0045,"MMCPrivate",VR::IS,VM::VM1,"HighRRValue",false }, + {0x0029,0x0046,"MMCPrivate",VR::IS,VM::VM1,"IntervalsAcquired",false }, + {0x0029,0x0047,"MMCPrivate",VR::IS,VM::VM1,"IntervalsRejected",false }, + {0x0029,0x0048,"MMCPrivate",VR::CS,VM::VM1,"RespiratoryMotionCompensationTechnique",false }, + {0x0029,0x0049,"MMCPrivate",VR::CS,VM::VM1,"RespiratorySignalSource",false }, + {0x0029,0x004a,"MMCPrivate",VR::CS,VM::VM1,"BulkMotionCompensationTechnique",false }, + {0x0029,0x004b,"MMCPrivate",VR::CS,VM::VM1,"BulkMotionSignalSource",false }, + {0x0029,0x004c,"MMCPrivate",VR::CS,VM::VM1,"PixelPresentation",false }, + {0x0029,0x004d,"MMCPrivate",VR::CS,VM::VM1,"VolumetricProperties",false }, + {0x0029,0x004e,"MMCPrivate",VR::CS,VM::VM1,"VolumeBasedCalculationTechnique",false }, + {0x0029,0x004f,"MMCPrivate",VR::ST,VM::VM1,"AcquisitionContextDescription",false }, + {0x0029,0x0050,"MMCPrivate",VR::SQ,VM::VM1,"ModalityLUTSequence",false }, + {0x0029,0x0051,"MMCPrivate",VR::LO,VM::VM1,"LUTDescriptor",false }, + {0x0029,0x0052,"MMCPrivate",VR::LO,VM::VM1,"LUTExplanation",false }, + {0x0029,0x0053,"MMCPrivate",VR::LO,VM::VM1,"LUTData",false }, + {0x0029,0x0054,"MMCPrivate",VR::CS,VM::VM1,"PresentationLUTShape",false }, + {0x0029,0x0055,"MMCPrivate",VR::SQ,VM::VM1,"FrameAnatomySequence",false }, + {0x0029,0x0056,"MMCPrivate",VR::CS,VM::VM1,"FrameLaterality",false }, + {0x0029,0x0057,"MMCPrivate",VR::SQ,VM::VM1,"AnatomicRegionSequence",false }, + {0x0029,0x0058,"MMCPrivate",VR::SH,VM::VM1,"AnatomicRegionCodeValue",false }, + {0x0029,0x0059,"MMCPrivate",VR::SH,VM::VM1,"AnatomicRegionCodingSchemeDesignator",false }, + {0x0029,0x005a,"MMCPrivate",VR::SH,VM::VM1,"AnatomicRegionCodingSchemeVersion",false }, + {0x0029,0x005b,"MMCPrivate",VR::LO,VM::VM1,"AnatomicRegionCodeMeaning",false }, + {0x0029,0x005c,"MMCPrivate",VR::SQ,VM::VM1,"PixelValueTransformationSequence",false }, + {0x0029,0x005d,"MMCPrivate",VR::LO,VM::VM1,"RescaleType",false }, + {0x0029,0x005e,"MMCPrivate",VR::SQ,VM::VM1,"CardiacTriggerSequence",false }, + {0x0029,0x005f,"MMCPrivate",VR::FD,VM::VM1,"TriggerDelayTime",false }, + {0x0029,0x0060,"MMCPrivate",VR::SQ,VM::VM1,"FrameVOILUTSequence",false }, + {0x0029,0x0061,"MMCPrivate",VR::LO,VM::VM1,"WindowCenterAndWidthExplanation",false }, + {0x0029,0x0062,"MMCPrivate",VR::CS,VM::VM1,"AcquisitionContrast",false }, + {0x0029,0x0063,"MMCPrivate",VR::SQ,VM::VM1,"MRModifierSequence",false }, + {0x0029,0x0064,"MMCPrivate",VR::CS,VM::VM1,"ParallelAcquisitionTechnic",false }, + {0x0029,0x0065,"MMCPrivate",VR::FD,VM::VM1,"ParallelReductionFactorSecIn",false }, + {0x0029,0x0066,"MMCPrivate",VR::CS,VM::VM1,"InversionRecovery",false }, + {0x0029,0x0067,"MMCPrivate",VR::CS,VM::VM1,"FlowCompensation",false }, + {0x0029,0x0068,"MMCPrivate",VR::CS,VM::VM1,"FlowCompensationDirection",false }, + {0x0029,0x0069,"MMCPrivate",VR::CS,VM::VM1,"SpatialPreSaturation",false }, + {0x0029,0x006a,"MMCPrivate",VR::CS,VM::VM1,"PartialFourier",false }, + {0x0029,0x006b,"MMCPrivate",VR::CS,VM::VM1,"PartialFourierDirection",false }, + {0x0029,0x006c,"MMCPrivate",VR::CS,VM::VM1,"ResonantNucleus",false }, + {0x0029,0x006d,"MMCPrivate",VR::CS,VM::VM1,"KSpaceFiltering",false }, + {0x0029,0x006e,"MMCPrivate",VR::CS,VM::VM1,"ApplicableSafetyStandardAgency",false }, + {0x0029,0x006f,"MMCPrivate",VR::LO,VM::VM1,"ApplicableSafetyStandardDescription",false }, + {0x0029,0x0070,"MMCPrivate",VR::SQ,VM::VM1,"MRReceiveCoilSequence",false }, + {0x0029,0x0071,"MMCPrivate",VR::LO,VM::VM1,"ReceiveCoilManufacturerName",false }, + {0x0029,0x0072,"MMCPrivate",VR::CS,VM::VM1,"ReceiveCoilType",false }, + {0x0029,0x0073,"MMCPrivate",VR::CS,VM::VM1,"QuadratureReceiveCoil",false }, + {0x0029,0x0074,"MMCPrivate",VR::LO,VM::VM1,"MultiCoilConfiguration",false }, + {0x0029,0x0075,"MMCPrivate",VR::CS,VM::VM1,"ComplexImageComponent",false }, + {0x0029,0x0076,"MMCPrivate",VR::SH,VM::VM1,"PulseSequenceName",false }, + {0x0029,0x0077,"MMCPrivate",VR::CS,VM::VM1,"EchoPulseSequence",false }, + {0x0029,0x0078,"MMCPrivate",VR::CS,VM::VM1,"MultipleSpinEcho",false }, + {0x0029,0x0079,"MMCPrivate",VR::CS,VM::VM1,"MultiPlanarExcitation",false }, + {0x0029,0x007a,"MMCPrivate",VR::CS,VM::VM1,"PhaseContrast",false }, + {0x0029,0x007b,"MMCPrivate",VR::CS,VM::VM1,"TimeOfFlightContrast",false }, + {0x0029,0x007c,"MMCPrivate",VR::CS,VM::VM1,"SteadyStatePulseSequence",false }, + {0x0029,0x007d,"MMCPrivate",VR::CS,VM::VM1,"EchoPlanarPulseSequence",false }, + {0x0029,0x007e,"MMCPrivate",VR::CS,VM::VM1,"SpectrallySelectedSuppression",false }, + {0x0029,0x007f,"MMCPrivate",VR::CS,VM::VM1,"OversamplingPhase",false }, + {0x0029,0x0080,"MMCPrivate",VR::CS,VM::VM1,"SegmentedKSpaceTraversal",false }, + {0x0029,0x0081,"MMCPrivate",VR::CS,VM::VM1,"CoverageOfKSpace",false }, + {0x0029,0x0082,"MMCPrivate",VR::SQ,VM::VM1,"MRTimingAndRelatedParametersSequence",false }, + {0x0029,0x0083,"MMCPrivate",VR::US,VM::VM1,"RFEchoTrainLength",false }, + {0x0029,0x0084,"MMCPrivate",VR::US,VM::VM1,"GradientEchoTrainLength",false }, + {0x0029,0x0085,"MMCPrivate",VR::CS,VM::VM1,"GradientOutputType",false }, + {0x0029,0x0086,"MMCPrivate",VR::FD,VM::VM1,"GradientOutput",false }, + {0x0029,0x0087,"MMCPrivate",VR::SQ,VM::VM1,"MRFOVGeometrySequence",false }, + {0x0029,0x0088,"MMCPrivate",VR::US,VM::VM1,"MRAcquisitionFrequencyEncodingSteps",false }, + {0x0029,0x0089,"MMCPrivate",VR::US,VM::VM1,"MRAcquisitionPhaseEncodingStepsInPlane",false }, + {0x0029,0x008a,"MMCPrivate",VR::US,VM::VM1,"MRAcquisitionPhaseEncodingStepsOutOfPlane",false }, + {0x0029,0x008b,"MMCPrivate",VR::SQ,VM::VM1,"MRTransmitCoilSequence",false }, + {0x0029,0x008c,"MMCPrivate",VR::SH,VM::VM1,"TransmitCoilName",false }, + {0x0029,0x008d,"MMCPrivate",VR::LO,VM::VM1,"TransmitCoilManufacturerName",false }, + {0x0029,0x008e,"MMCPrivate",VR::CS,VM::VM1,"TransmitCoilType",false }, + {0x0029,0x008f,"MMCPrivate",VR::SQ,VM::VM1,"MREchoSequence",false }, + {0x0029,0x0090,"MMCPrivate",VR::FD,VM::VM1,"EffectiveEchoTime",false }, + {0x0029,0x0091,"MMCPrivate",VR::SQ,VM::VM1,"MRMetaboliteMapSequence",false }, + {0x0029,0x0092,"MMCPrivate",VR::ST,VM::VM1,"MetaboliteMapDescription",false }, + {0x0029,0x0093,"MMCPrivate",VR::SQ,VM::VM1,"MetaboliteMapCodeSequence",false }, + {0x0029,0x0094,"MMCPrivate",VR::SH,VM::VM1,"MetaboliteMapCodeValue",false }, + {0x0029,0x0095,"MMCPrivate",VR::SH,VM::VM1,"MetaboliteMapCodingSchemeDesignator",false }, + {0x0029,0x0096,"MMCPrivate",VR::SH,VM::VM1,"MetaboliteMapCodingSchemeVersion",false }, + {0x0029,0x0097,"MMCPrivate",VR::LO,VM::VM1,"MetaboliteMapCodeMeaning",false }, + {0x0029,0x0098,"MMCPrivate",VR::SQ,VM::VM1,"MRImagingModifierSequence",false }, + {0x0029,0x0099,"MMCPrivate",VR::CS,VM::VM1,"MagnetizationTransfer",false }, + {0x0029,0x009a,"MMCPrivate",VR::CS,VM::VM1,"BloodSignalNulling",false }, + {0x0029,0x009b,"MMCPrivate",VR::CS,VM::VM1,"Tagging",false }, + {0x0029,0x009c,"MMCPrivate",VR::FD,VM::VM1,"TagSpacingFirstDimension",false }, + {0x0029,0x009d,"MMCPrivate",VR::FD,VM::VM1,"TagSpacingSecondDimension",false }, + {0x0029,0x009e,"MMCPrivate",VR::FD,VM::VM1,"TagAngleFirstAxis",false }, + {0x0029,0x009f,"MMCPrivate",VR::SS,VM::VM1,"TagAngleSecondAxis",false }, + {0x0029,0x00a0,"MMCPrivate",VR::FD,VM::VM1,"TagThickness",false }, + {0x0029,0x00a1,"MMCPrivate",VR::FD,VM::VM1,"TaggingDelay",false }, + {0x0029,0x00a2,"MMCPrivate",VR::FD,VM::VM1,"TransmitterFrequency",false }, + {0x0029,0x00a3,"MMCPrivate",VR::DS,VM::VM1,"PixelBandwidth",false }, + {0x0029,0x00a4,"MMCPrivate",VR::SQ,VM::VM1,"MRVelocityEncodingSequence",false }, + {0x0029,0x00a5,"MMCPrivate",VR::FD,VM::VM1,"VelocityEncodingDirection",false }, + {0x0029,0x00a6,"MMCPrivate",VR::FD,VM::VM1,"VelocityEncodingMinimumValue",false }, + {0x0029,0x00a7,"MMCPrivate",VR::FD,VM::VM1,"VelocityEncodingMaximumValue",false }, + {0x0029,0x00a8,"MMCPrivate",VR::SQ,VM::VM1,"MRImageFrameTypeSequence",false }, + {0x0029,0x00a9,"MMCPrivate",VR::CS,VM::VM1,"FrameType",false }, + {0x0029,0x00aa,"MMCPrivate",VR::CS,VM::VM1,"PixelPresentation",false }, + {0x0029,0x00ab,"MMCPrivate",VR::CS,VM::VM1,"VolumetricProperties",false }, + {0x0029,0x00ac,"MMCPrivate",VR::CS,VM::VM1,"VolumeBasedCalculationTechnique",false }, + {0x0029,0x00ad,"MMCPrivate",VR::IS,VM::VM1,"FilmedCount",false }, + {0x0029,0x00ae,"MMCPrivate",VR::LO,VM::VM1,"IsTransferred",false }, + {0x0029,0x00af,"MMCPrivate",VR::LO,VM::VM1,"IsArchived",false }, + {0x0029,0x00b0,"MMCPrivate",VR::LO,VM::VM1,"MppsStepStatus",false }, + {0x0029,0x00b1,"MMCPrivate",VR::LO,VM::VM1,"CommitmentStatus",false }, + {0x0029,0x00b2,"MMCPrivate",VR::LO,VM::VM1,"IsStorageCommitted",false }, + {0x0029,0x00b3,"MMCPrivate",VR::LO,VM::VM1,"IsDicom",false }, + {0x0029,0x00b4,"MMCPrivate",VR::LO,VM::VM1,"IsAllowCascadeSave",false }, + {0x0029,0x00b5,"MMCPrivate",VR::LO,VM::VM1,"IsAllowCascadeProtect",false }, + {0x0029,0x00b6,"MMCPrivate",VR::LO,VM::VM1,"IsDeleted",false }, + {0x0029,0x00b7,"MMCPrivate",VR::OB,VM::VM1,"ApplicationData",false }, + {0x0029,0x00b8,"MMCPrivate",VR::LO,VM::VM1,"IsAllowCascadeSave",false }, + {0x0029,0x00b9,"MMCPrivate",VR::LO,VM::VM1,"IsAllowCascadeProtect",false }, + {0x0029,0x00ba,"MMCPrivate",VR::LO,VM::VM1,"IsDeleted",false }, + {0x0029,0x00bb,"MMCPrivate",VR::IS,VM::VM1,"VOI1",false }, + {0x0029,0x00bc,"MMCPrivate",VR::IS,VM::VM1,"VOI2",false }, + {0x0029,0x00bd,"MMCPrivate",VR::UI,VM::VM1,"BackgroundImageInstanceUID",false }, + {0x0029,0x00be,"MMCPrivate",VR::LO,VM::VM1,"IsStoredToPortableMedia",false }, + {0x0029,0x00bf,"MMCPrivate",VR::DS,VM::VM1,"Voi1",false }, + {0x0029,0x00c0,"MMCPrivate",VR::FD,VM::VM1,"SelectiveIRColumn",false }, + {0x0029,0x00c1,"MMCPrivate",VR::DS,VM::VM1,"Voi2",false }, + {0x0029,0x00c2,"MMCPrivate",VR::DS,VM::VM1,"MixingTime",false }, + {0x0029,0x00c3,"MMCPrivate",VR::DS,VM::VM1,"SelectiveIRPosition",false }, + {0x0029,0x00c4,"MMCPrivate",VR::DS,VM::VM1,"SelectiveIRRow",false }, + {0x0029,0x00c5,"MMCPrivate",VR::DS,VM::VM1,"SelectiveIRColumn",false }, + {0x0029,0x00c6,"MMCPrivate",VR::DS,VM::VM1,"SelectiveIROrientation",false }, + {0x0029,0x00c7,"MMCPrivate",VR::LO,VM::VM1,"SelectiveIRThickness",false }, + {0x0029,0x00c8,"MMCPrivate",VR::SH,VM::VM1,"RephaseOrderSlice",false }, + {0x0029,0x00c9,"MMCPrivate",VR::SH,VM::VM1,"RephaseOrderPhase",false }, + {0x0029,0x00ca,"MMCPrivate",VR::SH,VM::VM1,"RephaseOrderFreq",false }, + {0x0029,0x00cb,"MMCPrivate",VR::ST,VM::VM1,"MetaboliteMapDescription",false }, + {0x0029,0x00cc,"MMCPrivate",VR::SQ,VM::VM1,"volumeLocalizationSeq",false }, + {0x0029,0x00cd,"MMCPrivate",VR::FD,VM::VM1,"SlabThickness",false }, + {0x0029,0x00ce,"MMCPrivate",VR::FD,VM::VM1,"SlabOrientation",false }, + {0x0029,0x00cf,"MMCPrivate",VR::FD,VM::VM1,"MidSlabPosition",false }, + {0x0029,0x00d0,"MMCPrivate",VR::LO,VM::VM1,"AcqModeSliceDir",false }, + {0x0029,0x00d1,"MMCPrivate",VR::LO,VM::VM1,"IRThicknessRatio",false }, + {0x0029,0x00d2,"MMCPrivate",VR::LO,VM::VM1,"BBIRThicknessRatio",false }, + {0x0029,0x00d3,"MMCPrivate",VR::LO,VM::VM1,"DeltaAngle",false }, + {0x0029,0x00d4,"MMCPrivate",VR::IS,VM::VM1,"MultiFrameFrameNumber",false }, + {0x0029,0x00d5,"MMCPrivate",VR::UI,VM::VM1,"EnhancedSopInstanceUid",false }, + {0x0029,0x00d6,"MMCPrivate",VR::LO,VM::VM1,"PolarityOfPhaseEncoding",false }, + {0x0029,0x00d7,"MMCPrivate",VR::OB,VM::VM1,"PresentationStates",false }, + {0x0029,0x00d9,"MMCPrivate",VR::DS,VM::VM3,"Magnetic Field Direction",false }, + {0x0041,0x0001,"MMCPrivate",VR::OB,VM::VM1,"RawDataAppData",false }, + {0x0041,0x0002,"MMCPrivate",VR::SQ,VM::VM1,"RawDataIndex",false }, + {0x0041,0x0003,"MMCPrivate",VR::LO,VM::VM1,"ChannelNumber",false }, + {0x0041,0x0004,"MMCPrivate",VR::LO,VM::VM1,"AxisDirection",false }, + {0x0041,0x0005,"MMCPrivate",VR::LO,VM::VM1,"SlabNumbe",false }, + {0x0041,0x0006,"MMCPrivate",VR::LO,VM::VM1,"CardiacPhaseNumbe",false }, + {0x0041,0x0007,"MMCPrivate",VR::LO,VM::VM1,"EchoNumber",false }, + {0x0041,0x0008,"MMCPrivate",VR::LO,VM::VM1,"SliceEncodeNumber",false }, + {0x0041,0x0009,"MMCPrivate",VR::LO,VM::VM1,"NsaNumber",false }, + {0x0041,0x000a,"MMCPrivate",VR::OB,VM::VM1,"RawData",false }, + {0x0041,0x000b,"MMCPrivate",VR::SS,VM::VM1,"RawDataMRInfo",false }, + {0x0041,0x000c,"MMCPrivate",VR::IS,VM::VM1,"NumberOfVoxels",false }, + {0x0041,0x000d,"MMCPrivate",VR::DS,VM::VM1,"MixingTime",false }, + {0x0041,0x000e,"MMCPrivate",VR::DS,VM::VM1,"ADDiff",false }, + {0x0041,0x000f,"MMCPrivate",VR::LO,VM::VM1,"ScanTime",false }, + {0x0041,0x0010,"MMCPrivate",VR::LO,VM::VM1,"NumPreSat",false }, + {0x0041,0x0011,"MMCPrivate",VR::LO,VM::VM1,"IsStoredToPortableMedia",false }, + {0x0041,0x0012,"MMCPrivate",VR::DS,VM::VM1,"Voi1",false }, + {0x0041,0x0013,"MMCPrivate",VR::DS,VM::VM1,"Voi2",false }, + {0x0041,0x0014,"MMCPrivate",VR::DS,VM::VM1,"VoxelSize",false }, + {0x0041,0x0015,"MMCPrivate",VR::IS,VM::VM1,"FreqPoint",false }, + {0x0041,0x0016,"MMCPrivate",VR::SH,VM::VM1,"LowOrderShim",false }, + {0x0041,0x0017,"MMCPrivate",VR::SH,VM::VM1,"EccLevel",false }, + {0x0041,0x0018,"MMCPrivate",VR::FL,VM::VM1,"FwhmHz",false }, + {0x0041,0x0019,"MMCPrivate",VR::FL,VM::VM1,"FwhmPpm",false }, + {0x0041,0x001a,"MMCPrivate",VR::FL,VM::VM1,"WaterSupRate",false }, + {0x0071,0x0001,"MMCPrivate",VR::FL,VM::VM1,"ForegroundTransparency",false }, + {0x0071,0x0002,"MMCPrivate",VR::LO,VM::VM1,"IsDisplayBackgroundImage",false }, + {0x0071,0x0003,"MMCPrivate",VR::FL,VM::VM1,"ForegroundHorizontalShift",false }, + {0x0071,0x0004,"MMCPrivate",VR::FL,VM::VM1,"ForegroundVerticalShift",false }, + {0x0071,0x0005,"MMCPrivate",VR::FL,VM::VM1,"ForegroundRotationAngle",false }, + {0x0071,0x0006,"MMCPrivate",VR::FL,VM::VM1,"ForegroundMagnification",false }, + {0x0071,0x0007,"MMCPrivate",VR::OB,VM::VM1,"ApplicationData",false }, {0x0021,0x0001,"Mayo/IBM Archive Project",VR::UN,VM::VM1,"?",false }, {0x0021,0x0010,"Mayo/IBM Archive Project",VR::UN,VM::VM1,"?",false }, {0x0021,0x0011,"Mayo/IBM Archive Project",VR::UN,VM::VM1,"?",false }, @@ -5759,7 +6741,7 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0029,0x0033,"PMTF INFORMATION DATA",VR::UL,VM::VM1,"PMTF Information 3",false }, {0x0029,0x0034,"PMTF INFORMATION DATA",VR::CS,VM::VM1,"PMTF Information 4",false }, {0x0029,0x0089,"PMTF INFORMATION DATA",VR::LO,VM::VM1,"?MRImage?",false }, - {0x0029,0x0090,"PMTF INFORMATION DATA",VR::OB,VM::VM1,"?reversed DTI DataSet?",false }, + {0x0029,0x0090,"PMTF INFORMATION DATA",VR::OB,VM::VM1,"Reversed EVRLE DataSet",false }, {0x7015,0x0073,"PMTF INFORMATION DATA",VR::SQ,VM::VM1,"?",false }, {0x0009,0x0002,"POLYTRON-SMS 2.5",VR::UN,VM::VM1,"Private Data 1",false }, {0x0009,0x0003,"POLYTRON-SMS 2.5",VR::UN,VM::VM1,"Private Data 2",false }, @@ -6068,6 +7050,7 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x2001,0x00c8,"Philips Imaging DD 001",VR::LO,VM::VM1,"?ExamCardName?",false }, {0x2001,0x00cc,"Philips Imaging DD 001",VR::ST,VM::VM1,"?SeriesDerivationDescription",false }, {0x2001,0x00da,"Philips Imaging DD 001",VR::CS,VM::VM1,"?",false }, + {0x2001,0x00de,"Philips Imaging DD 001",VR::UN,VM::VM1,"?",false }, {0x2001,0x00f1,"Philips Imaging DD 001",VR::FL,VM::VM1_n,"Prospective Motion Correction",false }, {0x2001,0x00f2,"Philips Imaging DD 001",VR::FL,VM::VM1_n,"Retrospective Motion Correction",false }, {0x2001,0x00f3,"Philips Imaging DD 001",VR::CS,VM::VM1,"Unknown Tag & Data",false }, @@ -6627,6 +7610,8 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x2005,0x004e,"Philips MR Imaging DD 005",VR::CS,VM::VM1,"IsB1Series", false }, {0x2005,0x004f,"Philips MR Imaging DD 005",VR::CS,VM::VM1,"VolumeSelect", false }, {0x2005,0x0050,"Philips MR Imaging DD 005",VR::SS,VM::VM1,"MRNrOfPatientOtherIDs", false }, + {0x2005,0x0051,"Philips MR Imaging DD 005",VR::IS,VM::VM1,"?", false }, + {0x2005,0x0052,"Philips MR Imaging DD 005",VR::UI,VM::VM1,"?", false }, {0x2005,0x0055,"Philips MR Imaging DD 005",VR::FD,VM::VM3,"ImageVelocityEncodingDirection", false }, {0x2005,0x0092,"Philips MR Imaging DD 005",VR::FL,VM::VM1,"Specific Energy Dose",false }, {0x2005,0x0053,"Philips MR Imaging DD 006",VR::FL,VM::VM1,"MRE Frequency",false }, @@ -6659,6 +7644,14 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x2005,0x0085,"Philips MR Imaging DD 006",VR::DS,VM::VM1,"PIIM_GRADIENT_SLEW_RATE",false }, {0x2005,0x0086,"Philips MR Imaging DD 006",VR::LT,VM::VM1,"?",false }, {0x2005,0x0087,"Philips MR Imaging DD 006",VR::DS,VM::VM1,"PIIM_MR_STUDY_B1RMS",false }, + {0x2005,0x0095,"Philips MR Imaging DD 006",VR::CS,VM::VM1,"?",false }, + {0x2005,0x0096,"Philips MR Imaging DD 006",VR::IS,VM::VM1,"?",false }, + {0x2005,0x0097,"Philips MR Imaging DD 006",VR::CS,VM::VM1,"?",false }, + {0x2005,0x0099,"Philips MR Imaging DD 006",VR::SL,VM::VM1,"?",false }, + {0x2005,0x0000,"Philips MR Imaging DD 007",VR::CS,VM::VM1,"?",false }, + {0x2005,0x0001,"Philips MR Imaging DD 007",VR::FL,VM::VM1,"?",false }, + {0x2005,0x0002,"Philips MR Imaging DD 007",VR::FL,VM::VM1,"?",false }, + {0x2005,0x0003,"Philips MR Imaging DD 007",VR::FL,VM::VM1,"?",false }, /* new group */ {0x7043,0x0000,"Philips NM Private Group",VR::SH,VM::VM1,"?",false }, {0x0511,0x0000,"Philips PET Private Group",VR::US,VM::VM1,"?",false }, @@ -6677,6 +7670,10 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x7053,0x0007,"Philips PET Private Group",VR::SQ,VM::VM1,"Acquisition File Sequence",false }, {0x7053,0x0008,"Philips PET Private Group",VR::SQ,VM::VM1,"?",false }, {0x7053,0x0009,"Philips PET Private Group",VR::DS,VM::VM1,"Activity Concentration Scale Factor",false }, + {0x7053,0x000b,"Philips PET Private Group",VR::DS,VM::VM1,"?",false }, + {0x7053,0x000c,"Philips PET Private Group",VR::DS,VM::VM1,"?",false }, + {0x7053,0x000d,"Philips PET Private Group",VR::SS,VM::VM1,"?",false }, + {0x7053,0x000e,"Philips PET Private Group",VR::DS,VM::VM1,"?",false }, {0x7053,0x000f,"Philips PET Private Group",VR::UL,VM::VM1,"Segment Size",false }, {0x7053,0x0010,"Philips PET Private Group",VR::US,VM::VM1,"Segment Number",false }, {0x7053,0x0011,"Philips PET Private Group",VR::US,VM::VM1,"Number of Segments",false }, @@ -6687,7 +7684,57 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x7053,0x0016,"Philips PET Private Group",VR::SS,VM::VM1,"Private",false }, {0x7053,0x0017,"Philips PET Private Group",VR::SS,VM::VM1,"Private",false }, {0x7053,0x0018,"Philips PET Private Group",VR::SS,VM::VM1,"Private",false }, + {0x7053,0x0050,"Philips PET Private Group",VR::SS,VM::VM1,"?",false }, + {0x7053,0x0051,"Philips PET Private Group",VR::SS,VM::VM1,"?",false }, + {0x7053,0x0052,"Philips PET Private Group",VR::SS,VM::VM1,"?",false }, + {0x7053,0x0053,"Philips PET Private Group",VR::SS,VM::VM1,"?",false }, + {0x7053,0x0054,"Philips PET Private Group",VR::SS,VM::VM1,"?",false }, + {0x7053,0x0055,"Philips PET Private Group",VR::SS,VM::VM1,"?",false }, + {0x7053,0x0056,"Philips PET Private Group",VR::SS,VM::VM1,"?",false }, + {0x7053,0x0057,"Philips PET Private Group",VR::SS,VM::VM1,"?",false }, + {0x7053,0x0058,"Philips PET Private Group",VR::SS,VM::VM1,"?",false }, + {0x7053,0x0059,"Philips PET Private Group",VR::SS,VM::VM1,"?",false }, + {0x7053,0x005a,"Philips PET Private Group",VR::SS,VM::VM1,"?",false }, + {0x7053,0x005b,"Philips PET Private Group",VR::SS,VM::VM1,"?",false }, + {0x7053,0x005c,"Philips PET Private Group",VR::SS,VM::VM1,"?",false }, + {0x7053,0x005d,"Philips PET Private Group",VR::SS,VM::VM1,"?",false }, + {0x7053,0x005e,"Philips PET Private Group",VR::SS,VM::VM1,"?",false }, + {0x7053,0x005f,"Philips PET Private Group",VR::LO,VM::VM1,"?",false }, + {0x7053,0x0060,"Philips PET Private Group",VR::SS,VM::VM1,"?",false }, + {0x7053,0x0061,"Philips PET Private Group",VR::SS,VM::VM1,"?",false }, + {0x7053,0x0062,"Philips PET Private Group",VR::SS,VM::VM1,"?",false }, + {0x7053,0x0063,"Philips PET Private Group",VR::SS,VM::VM1,"?",false }, + {0x7053,0x0064,"Philips PET Private Group",VR::SS,VM::VM1,"?",false }, + {0x7053,0x0065,"Philips PET Private Group",VR::SS,VM::VM1,"?",false }, + {0x7053,0x0066,"Philips PET Private Group",VR::SS,VM::VM1,"?",false }, + {0x7053,0x0067,"Philips PET Private Group",VR::LO,VM::VM1,"?",false }, + {0x7053,0x0068,"Philips PET Private Group",VR::LO,VM::VM1,"?",false }, + {0x7053,0x0069,"Philips PET Private Group",VR::LO,VM::VM1,"?",false }, + {0x7053,0x006a,"Philips PET Private Group",VR::LT,VM::VM1,"?",false }, + {0x7053,0x006b,"Philips PET Private Group",VR::SH,VM::VM1,"?",false }, + {0x7053,0x006c,"Philips PET Private Group",VR::LO,VM::VM1,"?",false }, + {0x7053,0x006d,"Philips PET Private Group",VR::FL,VM::VM1,"?",false }, + {0x7053,0x006e,"Philips PET Private Group",VR::FL,VM::VM1,"?",false }, + {0x7053,0x006f,"Philips PET Private Group",VR::FL,VM::VM1,"?",false }, + {0x7053,0x0070,"Philips PET Private Group",VR::SS,VM::VM1,"?",false }, + {0x7053,0x0071,"Philips PET Private Group",VR::SS,VM::VM1,"?",false }, + {0x7053,0x0072,"Philips PET Private Group",VR::SS,VM::VM1,"?",false }, + {0x7053,0x0073,"Philips PET Private Group",VR::SH,VM::VM1,"?",false }, + {0x7053,0x0074,"Philips PET Private Group",VR::SH,VM::VM1,"?",false }, + {0x7053,0x0075,"Philips PET Private Group",VR::SH,VM::VM1,"?",false }, + {0x7053,0x0076,"Philips PET Private Group",VR::SH,VM::VM1,"?",false }, + {0x7053,0x0077,"Philips PET Private Group",VR::FL,VM::VM1,"?",false }, + {0x7053,0x0078,"Philips PET Private Group",VR::FL,VM::VM1,"?",false }, {0x7053,0x00c2,"Philips PET Private Group",VR::UI,VM::VM1,"PET-CT Multi Modality Name",false }, + {0x7053,0x00d0,"Philips PET Private Group",VR::SS,VM::VM1,"?",false }, + {0x7053,0x00d1,"Philips PET Private Group",VR::FL,VM::VM1,"?",false }, + {0x7053,0x00d2,"Philips PET Private Group",VR::DT,VM::VM1,"?",false }, + {0x7053,0x00d3,"Philips PET Private Group",VR::DT,VM::VM1,"?",false }, + {0x7053,0x00d5,"Philips PET Private Group",VR::FL,VM::VM1,"?",false }, + {0x7053,0x00d6,"Philips PET Private Group",VR::FL,VM::VM1,"?",false }, + {0x7053,0x00d7,"Philips PET Private Group",VR::FL,VM::VM1,"?",false }, + {0x7053,0x00d8,"Philips PET Private Group",VR::FL,VM::VM1,"?",false }, + {0x7053,0x00d9,"Philips PET Private Group",VR::FL,VM::VM1,"?",false }, {0x200b,0x0000,"Philips RAD Imaging DD 001",VR::PN,VM::VM1,"?",false }, {0x200b,0x0001,"Philips RAD Imaging DD 001",VR::US,VM::VM1,"?",false }, {0x200b,0x0002,"Philips RAD Imaging DD 001",VR::US,VM::VM1,"?",false }, @@ -6755,9 +7802,11 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0031,0x0031,"Philips US Imaging 60",VR::UL,VM::VM1,"Private data",false }, {0x0031,0x0032,"Philips US Imaging 60",VR::UL,VM::VM1,"Private data",false }, {0x200d,0x0005,"Philips US Imaging DD 017",VR::LO,VM::VM1,"?",false }, + {0x200d,0x0007,"Philips US Imaging DD 021",VR::LO,VM::VM1,"?CUSTOM_SELECTION_13?",false }, {0x200d,0x0037,"Philips US Imaging DD 023",VR::DA,VM::VM1,"?",false }, {0x200d,0x0038,"Philips US Imaging DD 023",VR::TM,VM::VM1,"?",false }, {0x200d,0x0045,"Philips US Imaging DD 023",VR::IS,VM::VM1,"?",false }, + {0x200d,0x0059,"Philips US Imaging DD 023",VR::IS,VM::VM1,"?",false }, {0x200d,0x0000,"Philips US Imaging DD 033",VR::OB,VM::VM1,"Philips Confidential v.1",false }, {0x200d,0x0001,"Philips US Imaging DD 033",VR::LO,VM::VM1,"?",false }, {0x200d,0x0002,"Philips US Imaging DD 033",VR::LO,VM::VM1,"?",false }, @@ -6776,6 +7825,7 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x200d,0x0011,"Philips US Imaging DD 033",VR::IS,VM::VM1,"Max Alloc Buffer (Zlib)",false }, {0x200d,0x0014,"Philips US Imaging DD 033",VR::IS,VM::VM1,"?",false }, {0x200d,0x0021,"Philips US Imaging DD 033",VR::IS,VM::VM1,"?Zero?",false }, + {0x200d,0x0022,"Philips US Imaging DD 033",VR::IS,VM::VM1,"?Zero?",false }, {0x200d,0x0001,"Philips US Imaging DD 034",VR::LO,VM::VM1,"?",false }, {0x200d,0x0002,"Philips US Imaging DD 034",VR::LO,VM::VM1,"?",false }, {0x200d,0x0003,"Philips US Imaging DD 034",VR::LO,VM::VM1,"?",false }, @@ -6861,6 +7911,7 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x200d,0x0076,"Philips US Imaging DD 042",VR::LO,VM::VM1,"?",false }, {0x200d,0x0077,"Philips US Imaging DD 042",VR::LO,VM::VM1,"?",false }, {0x200d,0x0005,"Philips US Imaging DD 043",VR::SH,VM::VM1,"?",false }, + {0x200d,0x0006,"Philips US Imaging DD 043",VR::IS,VM::VM1,"?",false }, {0x200d,0x00f1,"Philips US Imaging DD 045",VR::SQ,VM::VM1,"Private DataType Image Sequence",false }, {0x200d,0x00f3,"Philips US Imaging DD 045",VR::OB,VM::VM1,"image buffer (Zlib/none compressed)",false }, {0x200d,0x00f8,"Philips US Imaging DD 045",VR::SQ,VM::VM1,"Private DataType Image Groups Sequence",false }, @@ -7179,8 +8230,9 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0029,0x0002,"SECTRA_ImageInfo_01",VR::CS,VM::VM1,"Marking",false }, {0x0029,0x0003,"SECTRA_ImageInfo_01",VR::LO,VM::VM1,"No Decompression",false }, {0x0029,0x0004,"SECTRA_ImageInfo_01",VR::OB,VM::VM1,"Image Info new",false }, + {0x0029,0x0005,"SECTRA_ImageInfo_01",VR::SS,VM::VM1,"?",false }, {0x6001,0x0001,"SECTRA_OverlayInfo_01",VR::LO,VM::VM1,"Sectra Overlay",false }, - {0x0031,0x0098,"SEGAMI MIML",VR::OW,VM::VM1,"?",false }, + {0x0031,0x0098,"SEGAMI MIML",VR::OW,VM::VM1,"?Binary XML with PHI?",false }, {0x0035,0x0097,"SEGAMI__MEMO",VR::SH,VM::VM1,"?",false }, {0x0035,0x0098,"SEGAMI__MEMO",VR::LT,VM::VM1,"?",false }, {0x0019,0x0000,"SET WINDOW",VR::UN,VM::VM1,"Set Window Image Filter",false }, @@ -7350,6 +8402,7 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0019,0x00ae,"SIEMENS CT VA0 COAD",VR::IS,VM::VM1,"Number of Readings per Rotation",false }, {0x0019,0x00af,"SIEMENS CT VA0 COAD",VR::DS,VM::VM1,"Correction Table Reference Time",false }, {0x0019,0x00b0,"SIEMENS CT VA0 COAD",VR::DS,VM::VM1,"Feed per Rotation",false }, + {0x0019,0x00b1,"SIEMENS CT VA0 COAD",VR::SH,VM::VM1,"Admin Data Version",true}, {0x0019,0x00bd,"SIEMENS CT VA0 COAD",VR::IS,VM::VM1,"Pulmo Trigger Level",false }, {0x0019,0x00be,"SIEMENS CT VA0 COAD",VR::DS,VM::VM1,"Expiratoric Reserve",false }, {0x0019,0x00bf,"SIEMENS CT VA0 COAD",VR::DS,VM::VM1,"Vital Capacity",false }, @@ -8352,7 +9405,7 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0055,0x0093,"SIEMENS MED NM",VR::FL,VM::VM1,"Filter Cutoff Frequency",false }, {0x0055,0x0094,"SIEMENS MED NM",VR::FL,VM::VM1,"Filter Alpha Coefficient",false }, {0x0055,0x0095,"SIEMENS MED NM",VR::FL,VM::VM1,"Filter Order",false }, - {0x0055,0x0096,"SIEMENS MED NM",VR::FL,VM::VM1,"Attenuation Cooefficient",false }, + {0x0055,0x0096,"SIEMENS MED NM",VR::FL,VM::VM1,"Attenuation Coefficient",false }, {0x0055,0x0097,"SIEMENS MED NM",VR::SS,VM::VM1,"Percent Ray",false }, {0x0055,0x0098,"SIEMENS MED NM",VR::SS,VM::VM1,"Astigmatic Collimator 1 Neuro 2 Cardiac",false }, {0x0055,0x0099,"SIEMENS MED NM",VR::SS,VM::VM1,"XP0",false }, @@ -8745,6 +9798,7 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0019,0x0017,"SIEMENS MR HEADER",VR::DS,VM::VM1,"SliceResolution",false }, {0x0019,0x0018,"SIEMENS MR HEADER",VR::IS,VM::VM1,"RealDwellTime",false }, {0x0019,0x0023,"SIEMENS MR HEADER",VR::IS,VM::VM1,"FMRIStimulInfo",false }, + {0x0019,0x0024,"SIEMENS MR HEADER",VR::FD,VM::VM2,"?",false }, {0x0019,0x0025,"SIEMENS MR HEADER",VR::FD,VM::VM3,"RBMoCoTrans",false }, {0x0019,0x0026,"SIEMENS MR HEADER",VR::FD,VM::VM3,"RBMoCoRot",false }, {0x0019,0x0027,"SIEMENS MR HEADER",VR::FD,VM::VM6,"B_matrix",false }, @@ -8752,14 +9806,14 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0019,0x0029,"SIEMENS MR HEADER",VR::FD,VM::VM1_n,"MosaicRefAcqTimes",false }, {0x0051,0x0008,"SIEMENS MR HEADER",VR::CS,VM::VM1,"CSA Image Header Type",false }, {0x0051,0x0009,"SIEMENS MR HEADER",VR::LO,VM::VM1,"CSA Image Header Version ??",false }, - {0x0051,0x000a,"SIEMENS MR HEADER",VR::SH,VM::VM1,"TimeOfAcquisition",false }, - {0x0051,0x000b,"SIEMENS MR HEADER",VR::SH,VM::VM1,"Acquisition Matrix",false }, - {0x0051,0x000c,"SIEMENS MR HEADER",VR::SH,VM::VM1,"Field of View",false }, + {0x0051,0x000a,"SIEMENS MR HEADER",VR::LO,VM::VM1,"Meas Duration",false }, + {0x0051,0x000b,"SIEMENS MR HEADER",VR::LO,VM::VM1,"Acquisition Matrix (Reconstruction Matrix if Interpolated)",false }, + {0x0051,0x000c,"SIEMENS MR HEADER",VR::LO,VM::VM1,"Field of View",false }, {0x0051,0x000d,"SIEMENS MR HEADER",VR::SH,VM::VM1,"Slice Position",false }, - {0x0051,0x000e,"SIEMENS MR HEADER",VR::SH,VM::VM1,"Slice Orientation",false }, + {0x0051,0x000e,"SIEMENS MR HEADER",VR::LO,VM::VM1,"Slice Orientation",false }, {0x0051,0x000f,"SIEMENS MR HEADER",VR::LO,VM::VM1,"Coil String",false }, {0x0051,0x0011,"SIEMENS MR HEADER",VR::LO,VM::VM1,"PAT Mode (Ima PAT Mode)",false }, - {0x0051,0x0012,"SIEMENS MR HEADER",VR::SH,VM::VM1,"?Table Position?",false }, + {0x0051,0x0012,"SIEMENS MR HEADER",VR::SH,VM::VM1,"Rel Table Position",false }, {0x0051,0x0013,"SIEMENS MR HEADER",VR::SH,VM::VM1,"Positive PCS Directions",false }, {0x0051,0x0014,"SIEMENS MR HEADER",VR::SH,VM::VM1,"?v150_through?",false }, {0x0051,0x0015,"SIEMENS MR HEADER",VR::SH,VM::VM1,"?Data Filter?",false }, @@ -9370,11 +10424,12 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x0009,0x0075,"SIENET",VR::LO,VM::VM1,"?",false }, {0x0091,0x0020,"SIENET",VR::PN,VM::VM1_n,"Patient Name",false }, {0x0095,0x0001,"SIENET",VR::LO,VM::VM1,"Examination Folder ID",false }, - {0x0095,0x0004,"SIENET",VR::UL,VM::VM1,"Folder Reported Status",false }, + {0x0095,0x0004,"SIENET",VR::SL,VM::VM1,"Folder Reported Status",false }, {0x0095,0x0005,"SIENET",VR::LO,VM::VM1,"Folder Reporting Radiologist",false }, {0x0095,0x0007,"SIENET",VR::LO,VM::VM1,"SIENET ISA PLA",false }, - {0x0095,0x000c,"SIENET",VR::UL,VM::VM1,"Folder Rebuild Status",false }, + {0x0095,0x000c,"SIENET",VR::SL,VM::VM1,"Folder Rebuild Status",false }, {0x0095,0x0020,"SIENET",VR::UN,VM::VM1,"?",false }, + {0x0095,0x00fb,"SIENET",VR::ST,VM::VM1,"?",false }, {0x0099,0x0002,"SIENET",VR::UL,VM::VM1,"Key Images",false }, {0x0099,0x0005,"SIENET",VR::SL,VM::VM1,"Image Number",false }, {0x0009,0x0010,"SPI",VR::LO,VM::VM1,"Comments",false }, @@ -10563,6 +11618,9 @@ static const DICT_ENTRY DICOMV3DataDict [] = { {0x700d,0x0090,"TOSHIBA_MEC_MR3",VR::OF,VM::VM1,"MRS Ref Raw Data",false }, {0x700d,0x0091,"TOSHIBA_MEC_MR3",VR::FL,VM::VM1,"Receiver gain of prescan",false }, {0x0009,0x0000,"TOSHIBA_MEC_OT3",VR::LO,VM::VM1,"HIS/RIS Study ID",false }, + {0x7019,0x0045,"TOSHIBA_MEC_OT3",VR::SQ,VM::VM1,"?",false }, + {0x7019,0x0046,"TOSHIBA_MEC_OT3",VR::DA,VM::VM1,"?",false }, + {0x7019,0x0047,"TOSHIBA_MEC_OT3",VR::TM,VM::VM1,"?",false }, {0x7019,0x0071,"TOSHIBA_MEC_OT3",VR::CS,VM::VM1,"Indicator of creator",false }, {0x7019,0x0072,"TOSHIBA_MEC_OT3",VR::LO,VM::VM1,"ID of quality assurance reviewer",false }, {0x7019,0x0073,"TOSHIBA_MEC_OT3",VR::PN,VM::VM1,"Name of quality assurance reviewer",false }, diff --git a/Source/DataDictionary/gdcmUIDs.cxx b/Source/DataDictionary/gdcmUIDs.cxx index 96ed18d7bed..c43e24d6af1 100644 --- a/Source/DataDictionary/gdcmUIDs.cxx +++ b/Source/DataDictionary/gdcmUIDs.cxx @@ -16,7 +16,7 @@ =========================================================================*/ #include "gdcmUIDs.h" -#include // strcmp +#include // strcmp namespace gdcm { diff --git a/Source/DataDictionary/privatedicts.xml b/Source/DataDictionary/privatedicts.xml index c009bd92739..5e6141ccee6 100644 --- a/Source/DataDictionary/privatedicts.xml +++ b/Source/DataDictionary/privatedicts.xml @@ -11,14 +11,576 @@ PURPOSE. See the above copyright notice for more information. --> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -76,6 +638,7 @@ + @@ -84,13 +647,25 @@ + + + + + + + + + + + + @@ -99,6 +674,9 @@ + @@ -159,6 +737,7 @@ + @@ -204,14 +783,17 @@ + + + @@ -227,6 +809,7 @@ + @@ -241,8 +824,11 @@ + + + @@ -260,6 +846,7 @@ + @@ -295,6 +882,7 @@ + @@ -316,6 +904,7 @@ + @@ -421,11 +1010,13 @@ + + @@ -449,9 +1040,11 @@ + + @@ -486,6 +1079,7 @@ + @@ -510,6 +1104,7 @@ + @@ -522,14 +1117,14 @@ - + - + - + @@ -565,13 +1160,22 @@ + + + + + + + + + @@ -579,13 +1183,12 @@ - - + + + @@ -601,7 +1204,7 @@ - + @@ -615,12 +1218,14 @@ - + + + @@ -637,24 +1242,26 @@ - + - + - + + + @@ -667,13 +1274,17 @@ + + + + @@ -684,12 +1295,15 @@ - + + - - + + + + @@ -706,7 +1320,7 @@ - + @@ -716,13 +1330,15 @@ - - + + - + + + @@ -733,18 +1349,24 @@ - + + - + + - - + + + + - + @@ -754,9 +1376,11 @@ + + @@ -766,19 +1390,22 @@ - + - + + + + @@ -786,16 +1413,18 @@ + - + + @@ -803,9 +1432,14 @@ + + - + + + + @@ -820,14 +1454,17 @@ - + - + + + + @@ -839,26 +1476,26 @@ - - - + + + - + - + - + - + - + @@ -866,17 +1503,20 @@ - + - + + + - + + - + @@ -896,23 +1536,26 @@ + + + - - - - - - + + + + + + - + @@ -933,6 +1576,7 @@ + @@ -942,6 +1586,7 @@ + @@ -1730,6 +2375,7 @@ + @@ -1741,12 +2387,15 @@ + + + @@ -1760,6 +2409,7 @@ + @@ -1830,6 +2480,9 @@ + + + @@ -1864,6 +2517,7 @@ + @@ -2008,66 +2662,68 @@ - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2098,7 +2754,7 @@ - + @@ -2807,7 +3463,7 @@ - + @@ -2823,6 +3479,7 @@ + @@ -3183,17 +3840,26 @@ - + - + - + + + + + + + + + + @@ -4503,59 +5169,404 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -5535,6 +6546,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -5552,6 +6601,10 @@ + + + + @@ -5562,7 +6615,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -6024,7 +7127,7 @@ - + @@ -6190,6 +7293,7 @@ + @@ -7191,7 +8295,7 @@ - + @@ -8183,11 +9287,12 @@ - + - + + diff --git a/Source/DataStructureAndEncodingDefinition/gdcmBasicOffsetTable.h b/Source/DataStructureAndEncodingDefinition/gdcmBasicOffsetTable.h index dd031a18df0..51d3514b7c3 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmBasicOffsetTable.h +++ b/Source/DataStructureAndEncodingDefinition/gdcmBasicOffsetTable.h @@ -44,7 +44,6 @@ class GDCM_EXPORT BasicOffsetTable : public Fragment std::istream &Read(std::istream &is) { // Superclass const Tag itemStart(0xfffe, 0xe000); - const Tag seqDelItem(0xfffe,0xe0dd); if( !TagField.Read(is) ) { assert(0 && "Should not happen"); diff --git a/Source/DataStructureAndEncodingDefinition/gdcmByteSwapFilter.cxx b/Source/DataStructureAndEncodingDefinition/gdcmByteSwapFilter.cxx index 9a5267ea50b..7b1508f7f83 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmByteSwapFilter.cxx +++ b/Source/DataStructureAndEncodingDefinition/gdcmByteSwapFilter.cxx @@ -27,8 +27,6 @@ namespace gdcm //{ //} //----------------------------------------------------------------------------- -ByteSwapFilter::~ByteSwapFilter() -= default; bool ByteSwapFilter::ByteSwap() { diff --git a/Source/DataStructureAndEncodingDefinition/gdcmByteSwapFilter.h b/Source/DataStructureAndEncodingDefinition/gdcmByteSwapFilter.h index ef50ef09d09..cd7c84d6ede 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmByteSwapFilter.h +++ b/Source/DataStructureAndEncodingDefinition/gdcmByteSwapFilter.h @@ -28,7 +28,7 @@ class GDCM_EXPORT ByteSwapFilter { public: ByteSwapFilter(DataSet& ds):DS(ds),ByteSwapTag(false) {} - ~ByteSwapFilter(); + ~ByteSwapFilter() = default; ByteSwapFilter(const ByteSwapFilter &) = delete; ByteSwapFilter& operator=(const ByteSwapFilter &) = delete; diff --git a/Source/DataStructureAndEncodingDefinition/gdcmByteValue.cxx b/Source/DataStructureAndEncodingDefinition/gdcmByteValue.cxx index b48f6de8b03..432cdde99e6 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmByteValue.cxx +++ b/Source/DataStructureAndEncodingDefinition/gdcmByteValue.cxx @@ -95,7 +95,7 @@ namespace gdcm_ns // so we need an inequality if( length <= Internal.size() ) { - if(!Internal.empty()) memcpy(buffer, &Internal[0], length); + if(!Internal.empty()) memcpy(buffer, Internal.data(), length); return true; } gdcmDebugMacro( "Could not handle length= " << length ); diff --git a/Source/DataStructureAndEncodingDefinition/gdcmByteValue.h b/Source/DataStructureAndEncodingDefinition/gdcmByteValue.h index 03fabe34c1b..de945161aae 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmByteValue.h +++ b/Source/DataStructureAndEncodingDefinition/gdcmByteValue.h @@ -30,7 +30,6 @@ using namespace gdcm; #endif /** * \brief Class to represent binary value (array of bytes) - * \note */ class GDCM_EXPORT ByteValue : public Value { diff --git a/Source/DataStructureAndEncodingDefinition/gdcmCP246ExplicitDataElement.h b/Source/DataStructureAndEncodingDefinition/gdcmCP246ExplicitDataElement.h index a0397403562..340fc3f3e50 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmCP246ExplicitDataElement.h +++ b/Source/DataStructureAndEncodingDefinition/gdcmCP246ExplicitDataElement.h @@ -21,7 +21,6 @@ namespace gdcm // Data Element (CP246Explicit) /** * \brief Class to read/write a DataElement as CP246Explicit Data Element - * \details * \note Some system are producing SQ, declare them as UN, but encode the SQ as 'Explicit' * instead of Implicit */ diff --git a/Source/DataStructureAndEncodingDefinition/gdcmCSAHeader.cxx b/Source/DataStructureAndEncodingDefinition/gdcmCSAHeader.cxx index ee9a1f1647d..ad944ac6462 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmCSAHeader.cxx +++ b/Source/DataStructureAndEncodingDefinition/gdcmCSAHeader.cxx @@ -993,7 +993,7 @@ bool CSAHeader::LoadFromDataElement(DataElement const &de) // Some silly software consider the tag to be OW, therefore they byteswap it !!! sigh if( strcmp( signature, "VS01" ) == 0 ) { - SwapperDoOp::SwapArray( (unsigned short*)(void*)&s[0], (s.size() + 1) / 2 ); + SwapperDoOp::SwapArray( (unsigned short*)(void*)s.data(), (s.size() + 1) / 2 ); ss.str( s ); ss.read(signature, 4); } @@ -1116,6 +1116,7 @@ bool CSAHeader::LoadFromDataElement(DataElement const &de) ss.read((char*)&nitems, sizeof(nitems)); SwapperNoOp::SwapArray(&nitems,1); csael.SetNoOfItems( nitems ); + if( InternalType == SV10) { assert( nitems % 6 == 0 );} //std::cout << "NoOfItems " << nitems << ", "; uint32_t xx; ss.read((char*)&xx, sizeof(xx)); @@ -1167,7 +1168,7 @@ bool CSAHeader::LoadFromDataElement(DataElement const &de) } std::string str = os.str(); if( !str.empty() ) - csael.SetByteValue( &str[0], (uint32_t)str.size()); + csael.SetByteValue( str.data(), (uint32_t)str.size()); //std::cout << std::endl; InternalCSADataSet.insert( csael ); } @@ -1194,7 +1195,7 @@ void CSAHeader::Print(std::ostream &os) const for(; it != InternalCSADataSet.end(); ++it) { - std::cout << *it << std::endl; + os << *it << std::endl; } } @@ -1236,15 +1237,15 @@ bool CSAHeader::FindCSAElementByName(const char *name) } static const char csaheader[] = "SIEMENS CSA HEADER"; -static const gdcm::PrivateTag t1(0x0029,0x0010,csaheader); // CSA Image Header Info -static const gdcm::PrivateTag t2(0x0029,0x0020,csaheader); // CSA Series Header Info +static const gdcm::PrivateTag t1(0x0029,0x10,csaheader); // CSA Image Header Info +static const gdcm::PrivateTag t2(0x0029,0x20,csaheader); // CSA Series Header Info //static const char csaheader2[] = "SIEMENS MEDCOM HEADER2"; //static const gdcm::PrivateTag t4(0x0029,0x0010,csaheader2); // CSA Image Header Info //static const gdcm::PrivateTag t5(0x0029,0x0020,csaheader2); // CSA Series Header Info static const char csanonimage[] = "SIEMENS CSA NON-IMAGE"; -static const gdcm::PrivateTag t3(0x0029,0x0010,csanonimage); // CSA Data Info +static const gdcm::PrivateTag t3(0x0029,0x10,csanonimage); // CSA Data Info const PrivateTag & CSAHeader::GetCSAImageHeaderInfoTag() { diff --git a/Source/DataStructureAndEncodingDefinition/gdcmCSAHeader.h b/Source/DataStructureAndEncodingDefinition/gdcmCSAHeader.h index 6d2123d2fa9..f10a401cca9 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmCSAHeader.h +++ b/Source/DataStructureAndEncodingDefinition/gdcmCSAHeader.h @@ -64,10 +64,10 @@ class GDCM_EXPORT CSAHeader { friend std::ostream& operator<<(std::ostream &_os, const CSAHeader &d); public : - CSAHeader():InternalDataSet(),InternalType(UNKNOWN),InterfileData(nullptr) {}; + CSAHeader():InternalDataSet(),InternalType(UNKNOWN),InterfileData(nullptr) {} ~CSAHeader() = default; - /// Divers format of CSAHeader as found 'in the wild' + /// Diverse format of CSAHeader as found 'in the wild' typedef enum { UNKNOWN = 0, SV10, @@ -94,15 +94,15 @@ public : CSAHeaderType GetFormat() const; /// Return the private tag used by SIEMENS to store the CSA Image Header - /// This is: PrivateTag(0x0029,0x0010,"SIEMENS CSA HEADER"); + /// This is: PrivateTag(0x0029,0x10,"SIEMENS CSA HEADER"); static const PrivateTag & GetCSAImageHeaderInfoTag(); /// Return the private tag used by SIEMENS to store the CSA Series Header - /// This is: PrivateTag(0x0029,0x0020,"SIEMENS CSA HEADER"); + /// This is: PrivateTag(0x0029,0x20,"SIEMENS CSA HEADER"); static const PrivateTag & GetCSASeriesHeaderInfoTag(); /// Return the private tag used by SIEMENS to store the CSA Data Info - /// This is: PrivateTag(0x0029,0x0010,"SIEMENS CSA NON-IMAGE"); + /// This is: PrivateTag(0x0029,0x10,"SIEMENS CSA NON-IMAGE"); static const PrivateTag & GetCSADataInfo(); /// Return the CSAElement corresponding to name 'name' diff --git a/Source/DataStructureAndEncodingDefinition/gdcmDataElement.cxx b/Source/DataStructureAndEncodingDefinition/gdcmDataElement.cxx index 94d915f1838..5012ed41154 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmDataElement.cxx +++ b/Source/DataStructureAndEncodingDefinition/gdcmDataElement.cxx @@ -156,6 +156,34 @@ namespace gdcm_ns return nullptr; } } + catch ( ... ) + { + gdcmErrorMacro( "Could not read SQ, unknown exception" ); + delete sqi; + return nullptr; + } + } + return sqi; + } + else if ( GetVR() & VR::OB_OW ) // pre-dicom 1993 ? + { + const ByteValue *bv = GetByteValue(); + assert( bv ); + SequenceOfItems *sqi = new SequenceOfItems; + sqi->SetLength( bv->GetLength() ); + std::string s( bv->GetPointer(), bv->GetLength() ); + try + { + std::stringstream ss; + ss.str( s ); + sqi->Read( ss, true ); + } + catch ( Exception &ex0 ) + { + gdcmErrorMacro( "Could not read SQ as OB. Giving up" ); + gdcmErrorMacro(ex0.what()); (void)ex0; + delete sqi; + return nullptr; } return sqi; } diff --git a/Source/DataStructureAndEncodingDefinition/gdcmDataSet.cxx b/Source/DataStructureAndEncodingDefinition/gdcmDataSet.cxx index 40f8a69cb8a..657ff111e04 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmDataSet.cxx +++ b/Source/DataStructureAndEncodingDefinition/gdcmDataSet.cxx @@ -25,10 +25,10 @@ const DataElement& DataSet::GetDEEnd() const std::string DataSet::GetPrivateCreator(const Tag &t) const { - if( t.IsPrivate() && !t.IsPrivateCreator() ) + if( t.IsPrivate() && !t.IsGroupLength() && !t.IsPrivateCreator() && !t.IsIllegal() ) { Tag pc = t.GetPrivateCreator(); - if( pc.GetElement() ) + assert( pc.GetElement() ); { const DataElement r(pc); ConstIterator it = DES.find(r); @@ -41,7 +41,7 @@ std::string DataSet::GetPrivateCreator(const Tag &t) const if( de.IsEmpty() ) return ""; const ByteValue *bv = de.GetByteValue(); assert( bv ); - std::string owner = std::string(bv->GetPointer(),bv->GetLength()); + std::string owner = std::string(bv->GetPointer(),bv->GetLength()).c_str(); // There should not be any trailing space character... // TODO: tmp.erase(tmp.find_last_not_of(' ') + 1); while( !owner.empty() && owner[owner.size()-1] == ' ' ) @@ -49,16 +49,24 @@ std::string DataSet::GetPrivateCreator(const Tag &t) const // osirix/AbdominalCT/36382443 owner.erase(owner.size()-1,1); } - assert( owner.size() == 0 || owner[owner.size()-1] != ' ' ); + assert( owner.empty() || owner[owner.size()-1] != ' ' ); return owner; } } return ""; } +PrivateTag DataSet::GetPrivateTag(const Tag &t) const +{ + const std::string str = this->GetPrivateCreator(t); + PrivateTag pt(t); + pt.SetOwner(str.c_str()); + return pt; +} + Tag DataSet::ComputeDataElement(const PrivateTag & t) const { - gdcmDebugMacro( "Entering ComputeDataElement" ); + //gdcmDebugMacro( "Entering ComputeDataElement" ); //assert( t.IsPrivateCreator() ); // No this is wrong to do the assert: eg. (0x07a1,0x000a,"ELSCINT1") // is valid because we have not yet done the mapping, so 0xa < 0x10 fails but might not later on const Tag start(t.GetGroup(), 0x0010 ); // First possible private creator (0x0 -> 0x9 are reserved...) @@ -77,7 +85,7 @@ Tag DataSet::ComputeDataElement(const PrivateTag & t) const std::string tmp(bv->GetPointer(),bv->GetLength()); // trim trailing whitespaces: tmp.erase(tmp.find_last_not_of(' ') + 1); - assert( tmp.size() == 0 || tmp[ tmp.size() - 1 ] != ' ' ); // FIXME + assert( tmp.empty() || tmp[ tmp.size() - 1 ] != ' ' ); // FIXME if( System::StrCaseCmp( tmp.c_str(), refowner ) == 0 ) { // found ! @@ -87,7 +95,7 @@ Tag DataSet::ComputeDataElement(const PrivateTag & t) const } ++it; } - gdcmDebugMacro( "In compute found is:" << found ); + //gdcmDebugMacro( "In compute found is:" << found ); if (!found) return GetDEEnd().GetTag(); // else // ok we found the Private Creator Data Element, let's construct the proper data element diff --git a/Source/DataStructureAndEncodingDefinition/gdcmDataSet.h b/Source/DataStructureAndEncodingDefinition/gdcmDataSet.h index 4528539e282..5f26a3dd449 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmDataSet.h +++ b/Source/DataStructureAndEncodingDefinition/gdcmDataSet.h @@ -196,8 +196,12 @@ class GDCM_EXPORT DataSet const DataElement& operator() (uint16_t group, uint16_t element) const { return GetDataElement( Tag(group,element) ); } /// Return the private creator of the private tag 't': + /// or an empty string when not found std::string GetPrivateCreator(const Tag &t) const; + /// Return the private tag of the private tag 't', private creator will be set to empty if not found + PrivateTag GetPrivateTag(const Tag &t) const; + /// Look up if private tag 't' is present in the dataset: bool FindDataElement(const PrivateTag &t) const; /// Return the dataelement @@ -225,24 +229,11 @@ class GDCM_EXPORT DataSet } /// Returns if the dataset is empty - bool IsEmpty() const { return DES.empty(); }; + bool IsEmpty() const { return DES.empty(); } DataSet& operator=(DataSet const &) = default; -/* - template - void ExecuteOperation(TOperation & operation) { - assert( !DES.empty() ); - DataElementSet::iterator it = Begin(); - for( ; it != End(); ++it) - { - DataElement &de = (DataElement&)*it; - operation( de ); - } - } -*/ - template std::istream &ReadNested(std::istream &is); diff --git a/Source/DataStructureAndEncodingDefinition/gdcmDataSetEvent.h b/Source/DataStructureAndEncodingDefinition/gdcmDataSetEvent.h index a9bd4395ffd..044697851c1 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmDataSetEvent.h +++ b/Source/DataStructureAndEncodingDefinition/gdcmDataSetEvent.h @@ -23,8 +23,6 @@ namespace gdcm /** * \brief DataSetEvent * \details Special type of event triggered during the DataSet store/move process - * - * \see */ class DataSetEvent : public AnyEvent { @@ -40,7 +38,7 @@ class DataSetEvent : public AnyEvent { return (dynamic_cast(e) == nullptr ? false : true) ; } ::gdcm::Event* MakeObject() const override { return new Self; } - DataSetEvent(const Self&s) : AnyEvent(s){}; + DataSetEvent(const Self&s) : AnyEvent(s){} DataSet const & GetDataSet() const { return *m_DataSet; } }; diff --git a/Source/DataStructureAndEncodingDefinition/gdcmElement.h b/Source/DataStructureAndEncodingDefinition/gdcmElement.h index 3dc7f84c5cf..b49b093dcbd 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmElement.h +++ b/Source/DataStructureAndEncodingDefinition/gdcmElement.h @@ -314,7 +314,11 @@ static int doround(char *buf, unsigned int n) { return 0; } -static int roundat(char *buf, unsigned int i, int iexp) { +#if defined(_MSC_VER) && (_MSC_VER < 1900) +#define snprintf _snprintf +#endif + +static int roundat(char *buf, size_t bufLen, unsigned int i, int iexp) { if (doround(buf, i) != 0) { iexp += 1; switch(iexp) { @@ -334,7 +338,7 @@ static int roundat(char *buf, unsigned int i, int iexp) { strcpy(buf, "100"); break; default: - sprintf(buf, "1e%d", iexp); + snprintf(buf, bufLen, "1e%d", iexp); } return 1; } @@ -353,20 +357,20 @@ static void x16printf(char *buf, int size, Float f) { size -= 1; *buf++ = '-'; } - sprintf(line, "%1.16e", f); + snprintf(line, sizeof(line), "%1.16e", f); if (line[0] == '-') { f = -f; size -= 1; *buf++ = '-'; - sprintf(line, "%1.16e", f); + snprintf(line, sizeof(line), "%1.16e", f); } *mant = line[0]; i = (int)strcspn(mant, "eE"); mant[i] = '\0'; iexp = (int)strtol(mant + i + 1, nullptr, 10); - lexp = sprintf(exp, "e%d", iexp); + lexp = snprintf(exp, sizeof(exp), "e%d", iexp); if ((iexp >= size) || (iexp < -3)) { - i = roundat(mant, size - 1 -lexp, iexp); + i = roundat(mant, sizeof(line) - 1, size - 1 -lexp, iexp); if(i == 1) { strcpy(buf, mant); return; @@ -379,11 +383,11 @@ static void x16printf(char *buf, int size, Float f) { strcat(buf, exp); } else if (iexp >= size - 2) { - roundat(mant, iexp + 1, iexp); + roundat(mant, sizeof(line) - 1, iexp + 1, iexp); strcpy(buf, mant); } else if (iexp >= 0) { - i = roundat(mant, size - 1, iexp); + i = roundat(mant, sizeof(line) - 1, size - 1, iexp); if (i == 1) { strcpy(buf, mant); return; @@ -396,7 +400,7 @@ static void x16printf(char *buf, int size, Float f) { } else { int j; - i = roundat(mant, size + 1 + iexp, iexp); + i = roundat(mant, sizeof(line) - 1, size + 1 + iexp, iexp); if (i == 1) { strcpy(buf, mant); return; @@ -405,15 +409,15 @@ static void x16printf(char *buf, int size, Float f) { for(j=0; j< -1 - iexp; j++) { buf[j+1] = '0'; } - if ((i == 1) && (iexp != -1)) { - buf[-iexp] = '1'; - buf++; - } strncpy(buf - iexp, mant, size + 1 + iexp); buf[size] = 0; clean(buf); } } +#if defined(_MSC_VER) && (_MSC_VER < 1900) +#undef snprintf +#endif + #endif template<> inline void EncodingImplementation::Write(const double* data, unsigned long length, std::ostream &_os) { diff --git a/Source/DataStructureAndEncodingDefinition/gdcmExplicitDataElement.txx b/Source/DataStructureAndEncodingDefinition/gdcmExplicitDataElement.txx index f92a5c1e8d6..47633b9f042 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmExplicitDataElement.txx +++ b/Source/DataStructureAndEncodingDefinition/gdcmExplicitDataElement.txx @@ -405,20 +405,31 @@ const std::ostream &ExplicitDataElement::Write(std::ostream &os) const } return os; } - bool vr16bitsimpossible = (VRField & VR::VL16) && (ValueLengthField > (uint32_t)VL::GetVL16Max()); - if( VRField == VR::INVALID || vr16bitsimpossible ) + const bool vr16bitsimpossible = (VRField & VR::VL16) && (ValueLengthField > (uint32_t)VL::GetVL16Max()); + const bool vrOWpixeldata = (VRField == VR::OW) && ValueLengthField.IsUndefined(); + const bool vrUNbutSpecial = (VRField == VR::UN && (TagField.IsPrivateCreator() || TagField.IsGroupLength())); + if( VRField == VR::INVALID || vr16bitsimpossible || vrOWpixeldata || vrUNbutSpecial) { if ( TagField.IsPrivateCreator() ) { gdcmAssertAlwaysMacro( !vr16bitsimpossible ); VR lo = VR::LO; - if( TagField.IsGroupLength() ) - { - lo = VR::UL; - } lo.Write(os); ValueLengthField.Write16(os); } + else if ( TagField.IsGroupLength() ) + { + gdcmAssertAlwaysMacro( !vr16bitsimpossible ); + VR ul = VR::UL; + ul.Write(os); + ValueLengthField.Write16(os); + } + else if ( TagField == Tag(0x7fe0,0x0010) ) + { + const VR ob = VR::OB; + ob.Write(os); + ValueLengthField.Write(os); + } else { const VR un = VR::UN; diff --git a/Source/DataStructureAndEncodingDefinition/gdcmFileMetaInformation.cxx b/Source/DataStructureAndEncodingDefinition/gdcmFileMetaInformation.cxx index 17668e334a0..ad127026466 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmFileMetaInformation.cxx +++ b/Source/DataStructureAndEncodingDefinition/gdcmFileMetaInformation.cxx @@ -71,9 +71,10 @@ void FileMetaInformation::AppendImplementationClassUID(const char * imp) { if( imp ) { - ImplementationClassUID = GetGDCMImplementationClassUID(); - ImplementationClassUID += "."; - ImplementationClassUID += imp; + std::string tmp = GetGDCMImplementationClassUID(); + tmp += "."; + tmp += imp; + if( tmp.size() <= 64 ) { ImplementationClassUID = tmp; } } } @@ -517,7 +518,7 @@ bool ReadImplicitDataElement(std::istream &is, ImplicitDataElement &de) * Note: PS 3.5 specifies that Elements with Tags (0001,xxxx), (0003,xxxx), * (0005,xxxx), and (0007,xxxx) shall not be used. */ -/// \TODO FIXME +/// \todo FIXME /// For now I do a Seek back of 6 bytes. It would be better to finish reading /// the first element of the FMI so that I can read the group length and /// therefore compare it against the actual value we found... diff --git a/Source/DataStructureAndEncodingDefinition/gdcmFileMetaInformation.h b/Source/DataStructureAndEncodingDefinition/gdcmFileMetaInformation.h index 4209396a0dd..f5525b9da7f 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmFileMetaInformation.h +++ b/Source/DataStructureAndEncodingDefinition/gdcmFileMetaInformation.h @@ -94,20 +94,9 @@ class GDCM_EXPORT FileMetaInformation : public DataSet static void SetSourceApplicationEntityTitle(const char * title); static const char *GetSourceApplicationEntityTitle(); - FileMetaInformation(FileMetaInformation const &fmi):DataSet(fmi) - { - DataSetTS = fmi.DataSetTS; - MetaInformationTS = fmi.MetaInformationTS; - DataSetMS = fmi.DataSetMS; - } - FileMetaInformation& operator=(const FileMetaInformation& fmi) - { - DataSetTS = fmi.DataSetTS; - MetaInformationTS = fmi.MetaInformationTS; - DataSetMS = fmi.DataSetMS; - return *this; - } - + FileMetaInformation(FileMetaInformation const& fmi) = default; + FileMetaInformation& operator=(const FileMetaInformation& fmi) = default; + VL GetFullLength() const { return P.GetLength() + DataSet::GetLength(); } diff --git a/Source/DataStructureAndEncodingDefinition/gdcmFileSet.h b/Source/DataStructureAndEncodingDefinition/gdcmFileSet.h index 0c580f69dbc..23f4dca5d0f 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmFileSet.h +++ b/Source/DataStructureAndEncodingDefinition/gdcmFileSet.h @@ -20,7 +20,6 @@ namespace gdcm { /** - * \brief * \details File-set: A File-set is a collection of DICOM Files (and possibly non-DICOM Files) * that share a common naming space within which File IDs are unique. */ diff --git a/Source/DataStructureAndEncodingDefinition/gdcmFragment.h b/Source/DataStructureAndEncodingDefinition/gdcmFragment.h index 576585f9c17..8c0fdceb939 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmFragment.h +++ b/Source/DataStructureAndEncodingDefinition/gdcmFragment.h @@ -62,9 +62,6 @@ class GDCM_EXPORT Fragment : public DataElement template std::istream &ReadPreValue(std::istream &is) { - const Tag itemStart(0xfffe, 0xe000); - const Tag seqDelItem(0xfffe,0xe0dd); - TagField.Read(is); if( !is ) { @@ -79,6 +76,8 @@ class GDCM_EXPORT Fragment : public DataElement throw Exception( "Problem #2" ); } #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION + const Tag itemStart(0xfffe, 0xe000); + const Tag seqDelItem(0xfffe,0xe0dd); if( TagField != itemStart && TagField != seqDelItem ) { throw Exception( "Problem #3" ); @@ -90,9 +89,6 @@ class GDCM_EXPORT Fragment : public DataElement template std::istream &ReadValue(std::istream &is) { - // Superclass - const Tag itemStart(0xfffe, 0xe000); - const Tag seqDelItem(0xfffe,0xe0dd); // Self SmartPointer bv = new ByteValue; bv->SetLength(ValueLengthField); diff --git a/Source/DataStructureAndEncodingDefinition/gdcmItem.cxx b/Source/DataStructureAndEncodingDefinition/gdcmItem.cxx index a282ed2d26d..f05865f4df2 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmItem.cxx +++ b/Source/DataStructureAndEncodingDefinition/gdcmItem.cxx @@ -13,7 +13,7 @@ =========================================================================*/ #include "gdcmItem.h" -#include +#include namespace gdcm_ns { diff --git a/Source/DataStructureAndEncodingDefinition/gdcmItem.h b/Source/DataStructureAndEncodingDefinition/gdcmItem.h index f6415cd6f70..6638aa33e53 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmItem.h +++ b/Source/DataStructureAndEncodingDefinition/gdcmItem.h @@ -251,7 +251,7 @@ class GDCM_EXPORT Item : public DataElement // Not sure how this happen if( TagField == Tag(0xfffe, 0xe0dd) ) { - gdcmWarningMacro( "SegDelItem found in defined length Sequence" ); + gdcmWarningMacro( "SeqDelItem found in defined length Sequence" ); assert( ValueLengthField == 0 ); assert( NestedDataSet.Size() == 0 ); } diff --git a/Source/DataStructureAndEncodingDefinition/gdcmMrProtocol.cxx b/Source/DataStructureAndEncodingDefinition/gdcmMrProtocol.cxx index 07211f8581b..046ca32bdf0 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmMrProtocol.cxx +++ b/Source/DataStructureAndEncodingDefinition/gdcmMrProtocol.cxx @@ -16,6 +16,11 @@ #include #include +#if defined(_MSC_VER) && (_MSC_VER < 1900) +#define snprintf _snprintf +#endif + + namespace gdcm { @@ -55,14 +60,19 @@ bool MrProtocol::Load( const ByteValue * bv, const char * csastr, int version ) // ### ASCCONV BEGIN ### // as well as: // ### ASCCONV BEGIN object=MrProtDataImpl@MrProtocolData version=41310008 converter=%MEASCONST%/ConverterList/Prot_Converter.txt ### + // and + // "### ASCCONV BEGIN object=MrProtDataImpl@MrProtocolData version=51130001 converter=%MEASCONST%/ConverterList/Prot_Converter.txt ### static const char begin[] = "### ASCCONV BEGIN "; + static const char begin2[] = "\"### ASCCONV BEGIN "; static const char end[] = "### ASCCONV END ###"; bool hasstarted = false; while( std::getline(is, s ) ) { if( !hasstarted ) { - hasstarted = starts_with(s, begin); + // syngo E11C does not write on begin of line anymore + s.erase(0, s.find_first_not_of(' ')); + hasstarted = starts_with(s, begin) || starts_with(s, begin2); if( hasstarted ) { if( version == -1 ) { // find version if not specified: @@ -186,7 +196,7 @@ bool MrProtocol::GetSliceArray( MrProtocol::SliceArray & sa ) const double v[3]; for( int j = 0; j < 3; ++j ) { - sprintf( buf, templ1, i, dir[j] ); + snprintf( buf, sizeof(buf), templ1, i, dir[j] ); const char * valstr = GetMrProtocolByName(buf); // when not present this means 0.0 double val = 0.0; @@ -202,7 +212,7 @@ bool MrProtocol::GetSliceArray( MrProtocol::SliceArray & sa ) const double v[3]; for( int j = 0; j < 3; ++j ) { - sprintf( buf, templ2, i, dir[j] ); + snprintf( buf, sizeof(buf), templ2, i, dir[j] ); const char * valstr = GetMrProtocolByName(buf); // when not present this means 0.0 double val = 0.0; diff --git a/Source/DataStructureAndEncodingDefinition/gdcmPDBHeader.cxx b/Source/DataStructureAndEncodingDefinition/gdcmPDBHeader.cxx index eed1fd5749d..0436b8d4667 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmPDBHeader.cxx +++ b/Source/DataStructureAndEncodingDefinition/gdcmPDBHeader.cxx @@ -162,6 +162,7 @@ int PDBHeader::readprotocoldatablock(const char *input, size_t inputlen, bool ve uint32_t len; // = *(const uint32_t*)input; memcpy(&len, input, sizeof len); SwapperNoOp::SwapArray(&len,1); + uint32_t offset = 4; //if( verbose ) // std::cout << len << "," << inputlen << std::endl; if( len + 4 + 1 == inputlen ) @@ -177,11 +178,20 @@ int PDBHeader::readprotocoldatablock(const char *input, size_t inputlen, bool ve else { //std::cerr << "Found the Protocol Data Block but could not read length..." << std::endl; - return 1; + if( len == 0x8088b1f ) + { + offset = 0; + len = (uint32_t)inputlen; + } + else + { + gdcmWarningMacro("Unhandled Protocol Data Block magic value: " << len ); + return 1; + } } // Alright we need to check if the binary blob was padded, if padded we need to // discard the trailing \0 to please gzip: - std::string str( input + 4, input + len ); + std::string str( input + offset, input + len ); std::istringstream is( str ); zlib_stream::zip_istream gzis( is ); diff --git a/Source/DataStructureAndEncodingDefinition/gdcmPDBHeader.h b/Source/DataStructureAndEncodingDefinition/gdcmPDBHeader.h index 5f552c16ded..5d266848000 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmPDBHeader.h +++ b/Source/DataStructureAndEncodingDefinition/gdcmPDBHeader.h @@ -46,6 +46,8 @@ class PrivateTag; * * \warning: the API of this class might change. * + * \warning: SEDESC is not always pure ASCII it can contains latin1 + * * \see CSAHeader */ class GDCM_EXPORT PDBHeader diff --git a/Source/DataStructureAndEncodingDefinition/gdcmParseException.h b/Source/DataStructureAndEncodingDefinition/gdcmParseException.h index ffdc43e7b28..4093dc53c86 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmParseException.h +++ b/Source/DataStructureAndEncodingDefinition/gdcmParseException.h @@ -37,7 +37,7 @@ class ParseException : public Exception { public: ParseException() = default; - ~ParseException() throw() override {}; + ~ParseException() throw() override {} /** Assignment operator. */ ParseException &operator= ( const ParseException &orig ) diff --git a/Source/DataStructureAndEncodingDefinition/gdcmPreamble.cxx b/Source/DataStructureAndEncodingDefinition/gdcmPreamble.cxx index 213e3e9bead..12b48983f53 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmPreamble.cxx +++ b/Source/DataStructureAndEncodingDefinition/gdcmPreamble.cxx @@ -12,7 +12,7 @@ =========================================================================*/ #include "gdcmPreamble.h" -#include // memset +#include // memset namespace gdcm { diff --git a/Source/DataStructureAndEncodingDefinition/gdcmPreamble.h b/Source/DataStructureAndEncodingDefinition/gdcmPreamble.h index b4f0edcbfc8..b4a8fcd2e1c 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmPreamble.h +++ b/Source/DataStructureAndEncodingDefinition/gdcmPreamble.h @@ -57,12 +57,13 @@ class GDCM_EXPORT Preamble /// Return size of Preamble VL GetLength() const { return 128 + 4; } - Preamble(Preamble const &) + Preamble(Preamble const &):Internal(nullptr) { Create(); } Preamble& operator=(Preamble const &) { + Internal = nullptr; Create(); return *this; } diff --git a/Source/DataStructureAndEncodingDefinition/gdcmPrivateTag.cxx b/Source/DataStructureAndEncodingDefinition/gdcmPrivateTag.cxx index 44917f61a63..052b4f2cc81 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmPrivateTag.cxx +++ b/Source/DataStructureAndEncodingDefinition/gdcmPrivateTag.cxx @@ -15,7 +15,7 @@ #include "gdcmTrace.h" #include "gdcmSystem.h" // FIXME -#include // sscanf +#include // sscanf #include // numeric_limits namespace gdcm_ns @@ -24,22 +24,27 @@ namespace gdcm_ns { if( !str ) return false; unsigned int group = 0, element = 0; - std::string owner; - owner.resize( strlen(str) ); // str != NULL - if( sscanf(str, "%04x,%04x,%[^\"]", &group , &element, &owner[0] ) != 3 + int nchar = -1; + if( sscanf(str, "%04x,%04x,%n", &group , &element, &nchar ) != 2 + || nchar == -1 || group > std::numeric_limits::max() || element > std::numeric_limits::max() + || group % 2 == 0 /*|| strlen(owner.c_str()) == 0*/ ) // can't use owner.empty() { - gdcmDebugMacro( "Problem reading Private Tag: " << str ); + // comment out the following since too verbose + //gdcmDebugMacro( "Problem reading Private Tag: " << str ); return false; } SetGroup( (uint16_t)group ); // This is not considered an error to specify element as 1010 for example. // just keep the lower bits of element: SetElement( (uint8_t)element ); - SetOwner( owner.c_str() ); - if( !*GetOwner() ) + const char *owner = str + nchar; + SetOwner( owner ); + const bool hasBackslash = strchr(owner,'\\') != nullptr; + const char * creator = GetOwner(); + if( !*creator || hasBackslash ) { gdcmDebugMacro( ": " << str ); return false; diff --git a/Source/DataStructureAndEncodingDefinition/gdcmPrivateTag.h b/Source/DataStructureAndEncodingDefinition/gdcmPrivateTag.h index 6194373072a..84b6fea866c 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmPrivateTag.h +++ b/Source/DataStructureAndEncodingDefinition/gdcmPrivateTag.h @@ -51,6 +51,30 @@ class GDCM_EXPORT PrivateTag : public Tag const char *GetOwner() const { return Owner.c_str(); } void SetOwner(const char *owner) { if(owner) Owner = LOComp::Trim(owner); } + PrivateTag &operator=(const PrivateTag &_val) + { + SetElementTag( _val.GetElementTag() ); + Owner = _val.Owner; + return *this; + } + + bool operator==(const Tag &_val) const + { + return GetElementTag() == _val.GetElementTag(); + } + bool operator==(const PrivateTag &_val) const + { + return GetElementTag() == _val.GetElementTag() && Owner == _val.Owner; + } + bool operator!=(const Tag &_val) const + { + return GetElementTag() != _val.GetElementTag(); + } + bool operator!=(const PrivateTag &_val) const + { + return GetElementTag() != _val.GetElementTag() || Owner != _val.Owner; + } + bool operator<(const PrivateTag &_val) const; /// Read PrivateTag from a string. Element number will be truncated diff --git a/Source/DataStructureAndEncodingDefinition/gdcmReader.cxx b/Source/DataStructureAndEncodingDefinition/gdcmReader.cxx index 6b9d5843913..454b0bf6192 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmReader.cxx +++ b/Source/DataStructureAndEncodingDefinition/gdcmReader.cxx @@ -60,8 +60,8 @@ Reader::~Reader() /// (i.e. the file is a 'true dicom' one) /// If not found then seek back at beginning of file (could be Mallinckrodt /// or old ACRNEMA with no preamble) -/// \precondition we are at the beginning of file -/// \postcondition we are at the beginning of the DataSet or +/// \pre we are at the beginning of file +/// \post we are at the beginning of the DataSet or /// Meta Information Header bool Reader::ReadPreamble() { @@ -70,8 +70,8 @@ bool Reader::ReadPreamble() /// \brief read the DICOM Meta Information Header /// Find out the TransferSyntax used (default: Little Endian Explicit) -/// \precondition we are at the start of group 0x0002 (well after preamble) -/// \postcondition we are at the beginning of the DataSet +/// \pre we are at the start of group 0x0002 (well after preamble) +/// \post we are at the beginning of the DataSet bool Reader::ReadMetaInformation() { return true; @@ -831,7 +831,7 @@ bool Reader::CanRead() const void Reader::SetFileName(const char *utf8path) { - if(Ifstream) delete Ifstream; + delete Ifstream; Ifstream = new std::ifstream(); if (utf8path && *utf8path) { #ifdef _MSC_VER diff --git a/Source/DataStructureAndEncodingDefinition/gdcmSequenceOfFragments.cxx b/Source/DataStructureAndEncodingDefinition/gdcmSequenceOfFragments.cxx index d756ed57451..943596bd6a5 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmSequenceOfFragments.cxx +++ b/Source/DataStructureAndEncodingDefinition/gdcmSequenceOfFragments.cxx @@ -128,6 +128,8 @@ bool SequenceOfFragments::WriteBuffer(std::ostream &os) const // assert(0); // return false; // } + (void)total; + return true; } @@ -142,7 +144,7 @@ bool SequenceOfFragments::FillFragmentWithJPEG( Fragment & frag, std::istream & if( byte == 0xd9 && jfif[ jfif.size() - 2 ] == 0xff ) break; } const uint32_t len = static_cast(jfif.size()); - frag.SetByteValue( (char*)&jfif[0], len ); + frag.SetByteValue( (char*)jfif.data(), len ); return true; } diff --git a/Source/DataStructureAndEncodingDefinition/gdcmSequenceOfFragments.h b/Source/DataStructureAndEncodingDefinition/gdcmSequenceOfFragments.h index 8868d405b32..791a77e4dfc 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmSequenceOfFragments.h +++ b/Source/DataStructureAndEncodingDefinition/gdcmSequenceOfFragments.h @@ -60,7 +60,7 @@ class GDCM_EXPORT SequenceOfFragments : public Value /// \brief Appends a Fragment to the already added ones void AddFragment(Fragment const &item); - // Compute the length of all fragments (and framents only!). + // Compute the length of all fragments (and fragments only!). // Basically the size of the PixelData as stored (in bytes). unsigned long ComputeByteLength() const; diff --git a/Source/DataStructureAndEncodingDefinition/gdcmSequenceOfItems.h b/Source/DataStructureAndEncodingDefinition/gdcmSequenceOfItems.h index 140f0e8fc87..56fa684cd98 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmSequenceOfItems.h +++ b/Source/DataStructureAndEncodingDefinition/gdcmSequenceOfItems.h @@ -82,7 +82,7 @@ class GDCM_EXPORT SequenceOfItems : public Value /// Index starts at 1 not 0 bool RemoveItemByIndex( const SizeType index ); - bool IsEmpty() const { return Items.empty(); }; + bool IsEmpty() const { return Items.empty(); } SizeType GetNumberOfItems() const { return Items.size(); } void SetNumberOfItems(SizeType n) { Items.resize(n); } @@ -148,7 +148,7 @@ class GDCM_EXPORT SequenceOfItems : public Value #ifdef GDCM_SUPPORT_BROKEN_IMPLEMENTATION if( item.GetTag() == seqDelItem ) { - gdcmWarningMacro( "SegDelItem found in defined length Sequence. Skipping" ); + gdcmWarningMacro( "SeqDelItem found in defined length Sequence. Skipping" ); assert( item.GetVL() == 0 ); assert( item.GetNestedDataSet().Size() == 0 ); // we need to pay attention that the length of the Sequence of Items will be wrong diff --git a/Source/DataStructureAndEncodingDefinition/gdcmTag.cxx b/Source/DataStructureAndEncodingDefinition/gdcmTag.cxx index b55879fd9a3..2089a8b88e7 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmTag.cxx +++ b/Source/DataStructureAndEncodingDefinition/gdcmTag.cxx @@ -14,7 +14,7 @@ #include "gdcmTag.h" #include "gdcmTrace.h" -#include // sscanf +#include // sscanf namespace gdcm { @@ -23,7 +23,7 @@ namespace gdcm unsigned int group = 0, element = 0; if( !str || sscanf(str, "%04x,%04x", &group , &element) != 2 ) { - gdcmDebugMacro( "Problem reading Tag: " << str ); + //gdcmDebugMacro( "Problem reading Tag: " << str ); return false; } SetGroup( (uint16_t)group ); diff --git a/Source/DataStructureAndEncodingDefinition/gdcmTransferSyntax.cxx b/Source/DataStructureAndEncodingDefinition/gdcmTransferSyntax.cxx index 437504c28f3..57a3abceb47 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmTransferSyntax.cxx +++ b/Source/DataStructureAndEncodingDefinition/gdcmTransferSyntax.cxx @@ -14,8 +14,8 @@ #include "gdcmTransferSyntax.h" #include "gdcmTrace.h" -#include -#include +#include +#include #include #include @@ -90,7 +90,7 @@ TransferSyntax::TSType TransferSyntax::GetTSType(const char *cstr) { // trim trailing whitespace std::string str = cstr; - std::string::size_type notspace = str.find_last_not_of(" ") + 1; + std::string::size_type notspace = str.find_last_not_of(' ') + 1; if( notspace != str.size() ) { gdcmDebugMacro( "BUGGY HEADER: TS contains " << diff --git a/Source/DataStructureAndEncodingDefinition/gdcmVM.cxx b/Source/DataStructureAndEncodingDefinition/gdcmVM.cxx index e449a0904f1..705bdc71e85 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmVM.cxx +++ b/Source/DataStructureAndEncodingDefinition/gdcmVM.cxx @@ -12,9 +12,9 @@ =========================================================================*/ #include "gdcmVM.h" -#include -#include // abort -#include // strcmp +#include +#include // abort +#include // strcmp namespace gdcm { diff --git a/Source/DataStructureAndEncodingDefinition/gdcmVR.cxx b/Source/DataStructureAndEncodingDefinition/gdcmVR.cxx index 3bc0326693d..a08b8402f04 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmVR.cxx +++ b/Source/DataStructureAndEncodingDefinition/gdcmVR.cxx @@ -13,8 +13,8 @@ =========================================================================*/ #include "gdcmVR.h" #include // for std::lower_bound -#include -#include +#include +#include namespace gdcm { diff --git a/Source/DataStructureAndEncodingDefinition/gdcmWriter.cxx b/Source/DataStructureAndEncodingDefinition/gdcmWriter.cxx index bf15837ee2e..515f23ed9f6 100644 --- a/Source/DataStructureAndEncodingDefinition/gdcmWriter.cxx +++ b/Source/DataStructureAndEncodingDefinition/gdcmWriter.cxx @@ -16,13 +16,11 @@ #include "gdcmDataSet.h" #include "gdcmTrace.h" -#include "gdcmSwapper.h" -#include "gdcmDataSet.h" #include "gdcmExplicitDataElement.h" #include "gdcmImplicitDataElement.h" +#include "gdcmSwapper.h" #include "gdcmValue.h" -#include "gdcmValue.h" #include "gdcmItem.h" #include "gdcmSequenceOfItems.h" #include "gdcmParseException.h" diff --git a/Source/InformationObjectDefinition/Part3.xml b/Source/InformationObjectDefinition/Part3.xml index 802c69d9f1a..6e6d9b7f47e 100644 --- a/Source/InformationObjectDefinition/Part3.xml +++ b/Source/InformationObjectDefinition/Part3.xml @@ -13161,7 +13161,7 @@ SOURCE_SIDE = the block is mounted on the side of the Block Tray that is towards Defined Terms: ION_SQUARE = square ion applicator -ION_RECT = rectangluar ion applicator +ION_RECT = rectangular ion applicator ION_CIRC = circular ion applicator ION_SHORT = short ion applicator ION_OPEN = open (dummy) ion applicator @@ -13736,7 +13736,7 @@ Only a single item shall be permitted in this sequence. Defined Terms: ION_SQUARE = square ion applicator -ION_RECT = rectangluar ion applicator +ION_RECT = rectangular ion applicator ION_CIRC = circular ion applicator ION_SHORT = short ion applicator ION_OPEN = open (dummy) ion applicator @@ -14992,7 +14992,7 @@ The application of the Window Center (0028,1050) and Window Width (0028,1051) sh Note: If the Presentation LUT Shape (2050,0020) is IDENTITY, then the result of applying the Window Center (0028,1050) and Window Width (0028,1051) is P-Values. If multiple values are present, both Attributes shall have the same number of values and shall be considered as pairs. Multiple values indicate that multiple alternative views should be presented. -The VOI LUT Sequence specifes a (potentially non-linear) conversion from the output of the (conceptual) Modality LUT values to the input to the (conceptual) Presentation LUT. +The VOI LUT Sequence specifies a (potentially non-linear) conversion from the output of the (conceptual) Modality LUT values to the input to the (conceptual) Presentation LUT. If multiple items are present in VOI LUT Sequence (0028,3010), only one shall be applied. Multiple items indicate that multiple alternative views should be presented. If any VOI LUT Attributes are included by an Image, a Window Width and Window Center or the VOI LUT Table, but not both, shall be applied to the Image for display. Inclusion of both indicates that multiple alternative views should be presented. The three values of the LUT Descriptor (0028,3002) describe the format of the LUT Data (0028,3006). @@ -15015,7 +15015,7 @@ The application of the Window Center (0028,1050) and Window Width (0028,1051) sh Note: If the Presentation LUT Shape (2050,0020) is IDENTITY, then the result of applying the Window Center (0028,1050) and Window Width (0028,1051) is P-Values. If multiple values are present, both Attributes shall have the same number of values and shall be considered as pairs. Multiple values indicate that multiple alternative views should be presented. -The VOI LUT Sequence specifes a (potentially non-linear) conversion from the output of the (conceptual) Modality LUT values to the input to the (conceptual) Presentation LUT. +The VOI LUT Sequence specifies a (potentially non-linear) conversion from the output of the (conceptual) Modality LUT values to the input to the (conceptual) Presentation LUT. If multiple items are present in VOI LUT Sequence (0028,3010), only one shall be applied. Multiple items indicate that multiple alternative views should be presented. If any VOI LUT Attributes are included by an Image, a Window Width and Window Center or the VOI LUT Table, but not both, shall be applied to the Image for display. Inclusion of both indicates that multiple alternative views should be presented. The three values of the LUT Descriptor (0028,3002) describe the format of the LUT Data (0028,3006). @@ -15045,7 +15045,7 @@ The application of the Window Center (0028,1050) and Window Width (0028,1051) sh Note: If the Presentation LUT Shape (2050,0020) is IDENTITY, then the result of applying the Window Center (0028,1050) and Window Width (0028,1051) is P-Values. If multiple values are present, both Attributes shall have the same number of values and shall be considered as pairs. Multiple values indicate that multiple alternative views should be presented. -The VOI LUT Sequence specifes a (potentially non-linear) conversion from the output of the (conceptual) Modality LUT values to the input to the (conceptual) Presentation LUT. +The VOI LUT Sequence specifies a (potentially non-linear) conversion from the output of the (conceptual) Modality LUT values to the input to the (conceptual) Presentation LUT. If multiple items are present in VOI LUT Sequence (0028,3010), only one shall be applied. Multiple items indicate that multiple alternative views should be presented. If any VOI LUT Attributes are included by an Image, a Window Width and Window Center or the VOI LUT Table, but not both, shall be applied to the Image for display. Inclusion of both indicates that multiple alternative views should be presented. The three values of the LUT Descriptor (0028,3002) describe the format of the LUT Data (0028,3006). @@ -15067,7 +15067,7 @@ The application of the Window Center (0028,1050) and Window Width (0028,1051) sh Note: If the Presentation LUT Shape (2050,0020) is IDENTITY, then the result of applying the Window Center (0028,1050) and Window Width (0028,1051) is P-Values. If multiple values are present, both Attributes shall have the same number of values and shall be considered as pairs. Multiple values indicate that multiple alternative views should be presented. -The VOI LUT Sequence specifes a (potentially non-linear) conversion from the output of the (conceptual) Modality LUT values to the input to the (conceptual) Presentation LUT. +The VOI LUT Sequence specifies a (potentially non-linear) conversion from the output of the (conceptual) Modality LUT values to the input to the (conceptual) Presentation LUT. If multiple items are present in VOI LUT Sequence (0028,3010), only one shall be applied. Multiple items indicate that multiple alternative views should be presented. If any VOI LUT Attributes are included by an Image, a Window Width and Window Center or the VOI LUT Table, but not both, shall be applied to the Image for display. Inclusion of both indicates that multiple alternative views should be presented. The three values of the LUT Descriptor (0028,3002) describe the format of the LUT Data (0028,3006). @@ -20052,7 +20052,7 @@ Required if present and have an equal value in the contributing SOP Instances. - + A Sequence that identifies the set of Images that constitute this acquisition context. Required if the reconstruction is created from DICOM SOP Instances. diff --git a/Source/InformationObjectDefinition/Template.xml.in b/Source/InformationObjectDefinition/Template.xml.in index 176fed81c26..3c5e0cace03 100644 --- a/Source/InformationObjectDefinition/Template.xml.in +++ b/Source/InformationObjectDefinition/Template.xml.in @@ -2,7 +2,7 @@ - + diff --git a/Source/InformationObjectDefinition/gdcmDefs.cxx b/Source/InformationObjectDefinition/gdcmDefs.cxx index 956a2c5014f..93eb04d277a 100644 --- a/Source/InformationObjectDefinition/gdcmDefs.cxx +++ b/Source/InformationObjectDefinition/gdcmDefs.cxx @@ -18,7 +18,7 @@ #include "gdcmTrace.h" #include "gdcmFile.h" -#include +#include namespace gdcm { diff --git a/Source/InformationObjectDefinition/gdcmDefs.h b/Source/InformationObjectDefinition/gdcmDefs.h index cc54c966ef5..d80d646cba4 100644 --- a/Source/InformationObjectDefinition/gdcmDefs.h +++ b/Source/InformationObjectDefinition/gdcmDefs.h @@ -41,7 +41,7 @@ class GDCM_EXPORT Defs Modules &GetModules() { return Part3Modules; } /// Users should not directly use Macro. Macro are simply a way for DICOM WG to re-use Tables. - /// Macros are conviently wrapped within Modules. See gdcm::Module API directly + /// Macros are conveniently wrapped within Modules. See gdcm::Module API directly const Macros &GetMacros() const { return Part3Macros; } Macros &GetMacros() { return Part3Macros; } diff --git a/Source/InformationObjectDefinition/gdcmIODEntry.cxx b/Source/InformationObjectDefinition/gdcmIODEntry.cxx index a5acb703a7b..fb53238ba5b 100644 --- a/Source/InformationObjectDefinition/gdcmIODEntry.cxx +++ b/Source/InformationObjectDefinition/gdcmIODEntry.cxx @@ -13,7 +13,7 @@ =========================================================================*/ #include "gdcmIODEntry.h" -#include // abort +#include // abort namespace gdcm { diff --git a/Source/InformationObjectDefinition/gdcmTableReader.cxx b/Source/InformationObjectDefinition/gdcmTableReader.cxx index fb08e679598..869ba183493 100644 --- a/Source/InformationObjectDefinition/gdcmTableReader.cxx +++ b/Source/InformationObjectDefinition/gdcmTableReader.cxx @@ -18,8 +18,8 @@ #include #include "gdcm_expat.h" -#include // for stderr -#include +#include // for stderr +#include namespace gdcm { @@ -73,7 +73,7 @@ void TableReader::HandleMacroEntryDescription(const char **atts) assert( ParsingMacroEntryDescription == false ); ParsingMacroEntryDescription = true; assert( *atts == nullptr ); - assert( Description == "" ); + assert( Description.empty() ); } void TableReader::HandleModuleInclude(const char **atts) @@ -92,7 +92,7 @@ void TableReader::HandleModuleEntryDescription(const char **atts) assert( ParsingModuleEntryDescription == false ); ParsingModuleEntryDescription = true; assert( *atts == nullptr ); - assert( Description == "" ); + assert( Description.empty() ); } void TableReader::HandleMacroEntry(const char **atts) diff --git a/Source/InformationObjectDefinition/gdcmType.cxx b/Source/InformationObjectDefinition/gdcmType.cxx index 18a68b353a2..d811a7c7a72 100644 --- a/Source/InformationObjectDefinition/gdcmType.cxx +++ b/Source/InformationObjectDefinition/gdcmType.cxx @@ -12,7 +12,7 @@ =========================================================================*/ #include "gdcmType.h" -#include +#include namespace gdcm { diff --git a/Source/InformationObjectDefinition/gdcmUsage.cxx b/Source/InformationObjectDefinition/gdcmUsage.cxx index 9aab5576101..558f0bfb417 100644 --- a/Source/InformationObjectDefinition/gdcmUsage.cxx +++ b/Source/InformationObjectDefinition/gdcmUsage.cxx @@ -12,7 +12,7 @@ =========================================================================*/ #include "gdcmUsage.h" -#include +#include namespace gdcm { diff --git a/Source/InformationObjectDefinition/gdcmXMLDictReader.cxx b/Source/InformationObjectDefinition/gdcmXMLDictReader.cxx index 4cd18db0bed..aab3c113f10 100644 --- a/Source/InformationObjectDefinition/gdcmXMLDictReader.cxx +++ b/Source/InformationObjectDefinition/gdcmXMLDictReader.cxx @@ -61,7 +61,7 @@ void XMLDictReader::HandleEntry(const char **atts) assert( v <= 0xFFFF ); char sv[4+1]; - r = sprintf(sv, "%04x", v); + r = snprintf(sv, sizeof(sv), "%04x", v); assert( r == 4 ); if( strncmp(raw, sv, 4) == 0 ) // GroupXX { @@ -84,7 +84,7 @@ void XMLDictReader::HandleEntry(const char **atts) assert( v <= 0xFFFF ); char sv[4+1]; - r = sprintf(sv, "%04x", v); + r = snprintf(sv, sizeof(sv), "%04x", v); assert( r == 4 ); if( strncmp(raw, sv, 4) == 0 ) { diff --git a/Source/InformationObjectDefinition/gdcmXMLPrivateDictReader.cxx b/Source/InformationObjectDefinition/gdcmXMLPrivateDictReader.cxx index 2f249ffa49a..cb42c1d7f44 100644 --- a/Source/InformationObjectDefinition/gdcmXMLPrivateDictReader.cxx +++ b/Source/InformationObjectDefinition/gdcmXMLPrivateDictReader.cxx @@ -62,7 +62,7 @@ void XMLPrivateDictReader::HandleEntry(const char **atts) assert( v <= 0xFFFF ); char sv[4+1]; - r = sprintf(sv, "%04x", v); + r = snprintf(sv, sizeof(sv), "%04x", v); assert( r == 4 ); if( strncmp(raw, sv, 4) == 0 ) // GroupXX { @@ -109,7 +109,7 @@ void XMLPrivateDictReader::HandleEntry(const char **atts) assert( v <= 0xFF ); char sv[4+1]; - r = sprintf(sv, "xx%02x", v); + r = snprintf(sv, sizeof(sv), "xx%02x", v); assert( r == 4 ); if( strncmp(raw, sv, 4) == 0 ) { diff --git a/Source/MediaStorageAndFileFormat/CMakeLists.txt b/Source/MediaStorageAndFileFormat/CMakeLists.txt index dbdd752a513..51a3ff629e4 100644 --- a/Source/MediaStorageAndFileFormat/CMakeLists.txt +++ b/Source/MediaStorageAndFileFormat/CMakeLists.txt @@ -2,8 +2,10 @@ # MSFF set(MSFF_SRCS gdcmEmptyMaskGenerator.cxx + gdcmMEC_MR3.cxx gdcmEquipmentManufacturer.cxx gdcmFileStreamer.cxx + gdcmCleaner.cxx gdcmJSON.cxx gdcmFileChangeTransferSyntax.cxx gdcmAnonymizer.cxx @@ -16,6 +18,7 @@ set(MSFF_SRCS gdcmFileDerivation.cxx gdcmImageFragmentSplitter.cxx gdcmTagPath.cxx + gdcmDPath.cxx gdcmSimpleSubjectWatcher.cxx gdcmAnonymizeEvent.cxx gdcmPixmap.cxx @@ -50,7 +53,9 @@ set(MSFF_SRCS gdcmDictPrinter.cxx gdcmXMLPrinter.cxx gdcmScanner.cxx + gdcmScanner2.cxx gdcmStrictScanner.cxx + gdcmStrictScanner2.cxx gdcmPixmapReader.cxx gdcmImageReader.cxx gdcmPixmapWriter.cxx @@ -103,6 +108,13 @@ set(MSFF_SRCS ${GDCM_SOURCE_DIR}/Utilities/gdcmrle/io.cxx ) + list(APPEND MSFF_SRCS + ${GDCM_SOURCE_DIR}/Utilities/gdcmext/csa.c + ${GDCM_SOURCE_DIR}/Utilities/gdcmext/mec_mr3.c + ${GDCM_SOURCE_DIR}/Utilities/gdcmext/mec_mr3_io.c + ${GDCM_SOURCE_DIR}/Utilities/gdcmext/mec_mr3_dict.c + ) + # Do the proper thing when building static...if only there was configured # headers or def files instead if(NOT BUILD_SHARED_LIBS) @@ -216,6 +228,10 @@ endif() if(GDCM_USE_SYSTEM_JSON) target_link_libraries(gdcmMSFF LINK_PRIVATE ${JSON_LIBRARIES}) endif() +if(UNIX) + find_package(Iconv) + target_link_libraries(gdcmMSFF LINK_PRIVATE ${Iconv_LIBRARIES}) +endif() # handling of static lib within shared is a mess: #target_link_libraries(gdcmMSFF gdcmrle) set_target_properties(gdcmMSFF PROPERTIES ${GDCM_LIBRARY_PROPERTIES}) diff --git a/Source/MediaStorageAndFileFormat/gdcmAnonymizeEvent.h b/Source/MediaStorageAndFileFormat/gdcmAnonymizeEvent.h index b24e126167e..492beed3e2b 100644 --- a/Source/MediaStorageAndFileFormat/gdcmAnonymizeEvent.h +++ b/Source/MediaStorageAndFileFormat/gdcmAnonymizeEvent.h @@ -33,7 +33,7 @@ class AnonymizeEvent : public AnyEvent typedef AnyEvent Superclass; AnonymizeEvent(Tag const &tag = 0):m_Tag(tag) {} ~AnonymizeEvent() override = default; - AnonymizeEvent(const Self&s) : AnyEvent(s){}; + AnonymizeEvent(const Self&s) : AnyEvent(s){} void operator=(const Self&) = delete; const char * GetEventName() const override { return "AnonymizeEvent"; } diff --git a/Source/MediaStorageAndFileFormat/gdcmAnonymizer.cxx b/Source/MediaStorageAndFileFormat/gdcmAnonymizer.cxx index 4ecc8807597..85982095c90 100644 --- a/Source/MediaStorageAndFileFormat/gdcmAnonymizer.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmAnonymizer.cxx @@ -95,6 +95,28 @@ bool Anonymizer::Empty( Tag const &t) return Replace(t, "", 0); } +bool Anonymizer::Empty( PrivateTag const &pt) +{ + // There is a secret code path to make it work for VR::SQ since operation is just 'make empty' + return Replace(pt, "", 0); +} + +bool Anonymizer::Clear( Tag const &t) +{ + DataSet &ds = F->GetDataSet(); + if(ds.FindDataElement(t)) + this->Empty(t); + return true; +} + +bool Anonymizer::Clear( PrivateTag const &pt) +{ + DataSet &ds = F->GetDataSet(); + if(ds.FindDataElement(pt)) + this->Empty(pt); + return true; +} + bool Anonymizer::Remove( Tag const &t ) { DataSet &ds = F->GetDataSet(); @@ -104,6 +126,18 @@ bool Anonymizer::Remove( Tag const &t ) return true; } +bool Anonymizer::Remove( PrivateTag const &pt ) +{ + DataSet &ds = F->GetDataSet(); + if(ds.FindDataElement(pt)) + { + const DataElement &de = ds.GetDataElement(pt); + return ds.Remove( de.GetTag() ) == 1; + } + else + return true; +} + bool Anonymizer::Replace( Tag const &t, const char *value ) { VL::Type len = 0; //to avoid the size_t warning on 64 bit windows @@ -115,6 +149,17 @@ bool Anonymizer::Replace( Tag const &t, const char *value ) return Replace( t, value, len ); } +bool Anonymizer::Replace( PrivateTag const &pt, const char *value ) +{ + VL::Type len = 0; //to avoid the size_t warning on 64 bit windows + if( value ) + { + len = (VL::Type)strlen( value );//strlen returns size_t, but it should be VL::Type + //strlen shouldn't be more than 4gb anyway + } + return Replace( pt, value, len ); +} + bool Anonymizer::Replace( Tag const &t, const char *value, VL const & vl ) { if( t.GetGroup() < 0x0008 ) return false; @@ -147,16 +192,20 @@ bool Anonymizer::Replace( Tag const &t, const char *value, VL const & vl ) } } de.SetByteValue( "", vl ); - ds.Insert( de ); + ds.Replace( de ); ret = true; } else { // TODO - assert( 0 && "TODO" ); + gdcmErrorMacro( "Cannot make empty private attribute that does not exist" ); ret = false; } } + else + { + gdcmErrorMacro( "Cannot replace private attribute." ); + } } else { @@ -263,6 +312,71 @@ bool Anonymizer::Replace( Tag const &t, const char *value, VL const & vl ) return ret; } +bool Anonymizer::Replace( PrivateTag const &pt, const char *value, VL const & vl ) +{ + DataSet &ds = F->GetDataSet(); + if(ds.FindDataElement(pt)) + { + const DataElement &de = ds.GetDataElement(pt); + return Replace( de.GetTag(), value, vl ); + } + else + { + Tag start = pt; + start.SetElement( 0x0010 ); + bool needcreator = false; + bool found = false; + Tag maxCreator = pt; + maxCreator.SetElement(0x00ff); + do { + const DataElement& de = ds.FindNextDataElement( start ); + const ByteValue* bv = de.GetByteValue(); + std::string creator_str; + if(bv) { + creator_str = std::string(bv->GetPointer(),bv->GetLength()); + creator_str = LOComp::Trim(creator_str.c_str()); + } + if( maxCreator < de.GetTag() ) { + needcreator = true; + found = true; + } else if ( System::StrCaseCmp(creator_str.c_str(), pt.GetOwner()) == 0 ) { + needcreator = false; + found = true; + } else { + assert( start.GetElement() != 0xff ); + start.SetElement( start.GetElement() + 1 ); + } + } while ( !found ); + assert( start.GetGroup() == pt.GetGroup() ); + if(needcreator) + { + // add private creator: + Element priv_creator; + priv_creator.SetValue( pt.GetOwner() ); + DataElement creator = priv_creator.GetAsDataElement(); + assert( start.GetElement() <= 0xff ); + start.SetElement( start.GetElement() ); + creator.SetTag( start ); + ds.Insert(creator); + } + // add empty element: + static const Global &g = GlobalInstance; + static const Dicts &dicts = g.GetDicts(); + const DictEntry &dictentry = dicts.GetDictEntry(pt); + DataElement fake; + Tag privateLocation(pt); + assert( pt.GetElement() <= 0xff ); + privateLocation.SetElement( start.GetElement() << 8 | pt.GetElement() ); + assert( start == privateLocation.GetPrivateCreator() ); + fake.SetTag( privateLocation ); + fake.SetVR( dictentry.GetVR() ); + ds.Insert( fake ); + + assert(ds.FindDataElement(pt)); + return Replace( privateLocation, value, vl ); + } +} + static bool Anonymizer_RemoveRetired(File const &file, DataSet &ds) { static const Global &g = GlobalInstance; @@ -502,8 +616,17 @@ bool Anonymizer::BasicApplicationLevelConfidentialityProfile1() //p7.SetCertificate( this->x509 ); DataSet &ds = F->GetDataSet(); + if( ds.FindDataElement( Tag(0x0012,0x0062) ) ) + { + gdcm::Attribute<0x0012,0x0062> patientIdentityRemoved = {}; + patientIdentityRemoved.SetFromDataSet( ds ); + const std::string value = patientIdentityRemoved.GetValue().Trim(); + if( value != "NO" ) { + gdcmErrorMacro( "EncryptedContentTransferSyntax Attribute Patient is set !" ); + return false; + } + } if( ds.FindDataElement( Tag(0x0400,0x0500) ) - || ds.FindDataElement( Tag(0x0012,0x0062) ) || ds.FindDataElement( Tag(0x0012,0x0063) ) ) { gdcmErrorMacro( "EncryptedContentTransferSyntax Attribute is present !" ); @@ -848,7 +971,7 @@ bool Anonymizer::BALCPProtect(DataSet &ds, Tag const & tag, IOD const & iod) if ( IsVRUI( tag ) ) { - std::string UIDToAnonymize = ""; + std::string UIDToAnonymize; UIDGenerator uid; if( !copy.IsEmpty() ) @@ -859,7 +982,7 @@ bool Anonymizer::BALCPProtect(DataSet &ds, Tag const & tag, IOD const & iod) } } - std::string anonymizedUID = ""; + std::string anonymizedUID; if( !UIDToAnonymize.empty() ) { if ( dummyMapUIDTags.count( UIDToAnonymize ) == 0 ) @@ -925,6 +1048,11 @@ void Anonymizer::RecurseDataSet( DataSet & ds ) static const Global &g = Global::GetInstance(); static const Defs &defs = g.GetDefs(); + if( defs.IsEmpty() ) + { + gdcmWarningMacro( "Missing Definitions, see Global.LoadResourcesFiles()" ); + return; + } const IOD& iod = defs.GetIODFromFile(*F); for(const Tag *ptr = start ; ptr != end ; ++ptr) @@ -952,6 +1080,8 @@ void Anonymizer::RecurseDataSet( DataSet & ds ) if( sqi ) { de.SetValue( *sqi ); // EXTREMELY IMPORTANT #2912092 + // Legacy behavior has been to create CP-246 / undefined length SQ as VR:UN... + if( de.GetVR() == VR::OB ) de.SetVR( VR::UN ); de.SetVLToUndefined(); assert( sqi->IsUndefinedLength() ); //de.GetVL().SetToUndefined(); diff --git a/Source/MediaStorageAndFileFormat/gdcmAnonymizer.h b/Source/MediaStorageAndFileFormat/gdcmAnonymizer.h index e2df415d786..752cc488e9e 100644 --- a/Source/MediaStorageAndFileFormat/gdcmAnonymizer.h +++ b/Source/MediaStorageAndFileFormat/gdcmAnonymizer.h @@ -81,26 +81,37 @@ class GDCM_EXPORT Anonymizer : public Subject ~Anonymizer() override; /// Make Tag t empty (if not found tag will be created) - /// Warning: does not handle SQ element bool Empty( Tag const &t ); - //bool Empty( PrivateTag const &t ); - //bool Empty( TagPath const &t ); + + /// Make PrivateTag pt empty (if not found tag will be created) + /// Pay special attention that this code must be done before any call to + /// Empty/Remove of the associated Private Creator, but before any call to + /// Replace. + bool Empty( PrivateTag const &pt ); + + /// Identical to 'Empty' except no action is done when tag is not present + bool Clear( Tag const &t ); + bool Clear( PrivateTag const &pt ); /// remove a tag (even a SQ can be removed) - /// Return code is false when tag t cannot be found bool Remove( Tag const &t ); - //bool Remove( PrivateTag const &t ); - //bool Remove( TagPath const &t ); + + /// remove a private tag (even a SQ can be removed) + /// Pay special attention that this code must be done before any call to + /// Empty/Remove of the associated Private Creator, but before any call to + /// Replace. When the private reservation becomes empty, no check is done to + /// automatically remove the private creator + bool Remove( PrivateTag const &pt ); /// Replace tag with another value, if tag is not found it will be created: /// WARNING: this function can only execute if tag is a VRASCII bool Replace( Tag const &t, const char *value ); + bool Replace( PrivateTag const &t, const char *value ); /// when the value contains \0, it is a good idea to specify the length. This function /// is required when dealing with VRBINARY tag bool Replace( Tag const &t, const char *value, VL const & vl ); - //bool Replace( PrivateTag const &t, const char *value, VL const & vl ); - //bool Replace( TagPath const &t, const char *value, VL const & vl ); + bool Replace( PrivateTag const &t, const char *value, VL const & vl ); /// Main function that loop over all elements and remove private tags bool RemovePrivateTags(); @@ -111,9 +122,6 @@ class GDCM_EXPORT Anonymizer : public Subject /// Main function that loop over all elements and remove retired element bool RemoveRetired(); - // TODO: - // bool Remove( PRIVATE_TAGS | GROUP_LENGTH | RETIRED ); - /// Set/Get File void SetFile(const File& f) { F = f; } //const File &GetFile() const { return *F; } diff --git a/Source/MediaStorageAndFileFormat/gdcmBitmap.cxx b/Source/MediaStorageAndFileFormat/gdcmBitmap.cxx index f8a8ba4724d..f92a1132306 100644 --- a/Source/MediaStorageAndFileFormat/gdcmBitmap.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmBitmap.cxx @@ -83,7 +83,7 @@ void Bitmap::SetNumberOfDimensions(unsigned int dim) const unsigned int *Bitmap::GetDimensions() const { assert( NumberOfDimensions ); - return &Dimensions[0]; + return Dimensions.data(); } unsigned int Bitmap::GetDimension(unsigned int idx) const @@ -400,6 +400,7 @@ bool Bitmap::TryJPEGCodec(char *buffer, bool &lossyflag) const const SequenceOfFragments *sf = PixelData.GetSequenceOfFragments(); if( !sf ) return false; const Fragment &frag = sf->GetFragment(0); + if( frag.IsEmpty() ) return false; const ByteValue &bv2 = dynamic_cast(frag.GetValue()); PixelFormat pf = GetPixelFormat(); // PixelFormat::UINT8; codec.SetPixelFormat( pf ); @@ -434,13 +435,6 @@ bool Bitmap::TryJPEGCodec(char *buffer, bool &lossyflag) const i->GetPixelFormat().SetBitsAllocated( cpf.GetBitsAllocated() ); i->GetPixelFormat().SetBitsStored( cpf.GetBitsStored() ); } - else if( cpf.GetBitsStored() > pf.GetBitsStored() ) - { - Bitmap *i = const_cast(this); - gdcmWarningMacro( "Encapsulated stream has more bits actually stored on disk. correcting." ); - i->GetPixelFormat().SetBitsAllocated( cpf.GetBitsAllocated() ); - i->GetPixelFormat().SetBitsStored( cpf.GetBitsStored() ); - } } } } @@ -684,6 +678,7 @@ bool Bitmap::TryJPEGLSCodec(char *buffer, bool &lossyflag) const const SequenceOfFragments *sf = PixelData.GetSequenceOfFragments(); if( !sf ) return false; const Fragment &frag = sf->GetFragment(0); + if( frag.IsEmpty() ) return false; const ByteValue &bv2 = dynamic_cast(frag.GetValue()); std::stringstream ss; @@ -812,6 +807,7 @@ bool Bitmap::TryJPEG2000Codec(char *buffer, bool &lossyflag) const const SequenceOfFragments *sf = PixelData.GetSequenceOfFragments(); if( !sf ) return false; const Fragment &frag = sf->GetFragment(0); + if( frag.IsEmpty() ) return false; const ByteValue &bv2 = dynamic_cast(frag.GetValue()); bool b = codec.GetHeaderInfo( bv2.GetPointer(), bv2.GetLength() , ts2 ); @@ -846,6 +842,7 @@ bool Bitmap::TryJPEG2000Codec(char *buffer, bool &lossyflag) const } else if( cpf.GetBitsStored() > pf.GetBitsStored() ) { + // Osirix10vs8BitsStored.dcm Bitmap *i = const_cast(this); gdcmWarningMacro( "Encapsulated stream has more bits actually stored on disk. correcting." ); i->GetPixelFormat().SetBitsAllocated( cpf.GetBitsAllocated() ); @@ -1009,7 +1006,6 @@ bool Bitmap::GetBufferInternal(char *buffer, bool &lossyflag) const //if( !success ) success = TryDeltaEncodingCodec(buffer); if( !success ) { - buffer = nullptr; //throw Exception( "No codec found for this image"); } @@ -1026,7 +1022,6 @@ bool Bitmap::GetBuffer2(std::ostream &os) const //if( !success ) success = TryRLECodec2(buffer); if( !success ) { - //buffer = 0; throw Exception( "No codec found for this image"); } @@ -1055,7 +1050,7 @@ void Bitmap::Print(std::ostream &os) const if( !IsEmpty() ) { os << "NumberOfDimensions: " << NumberOfDimensions << "\n"; - assert( Dimensions.size() ); + assert( !Dimensions.empty() ); os << "Dimensions: ("; std::vector::const_iterator it = Dimensions.begin(); os << *it; diff --git a/Source/MediaStorageAndFileFormat/gdcmBitmapToBitmapFilter.cxx b/Source/MediaStorageAndFileFormat/gdcmBitmapToBitmapFilter.cxx index 44b31b8c176..d0f8d06293a 100644 --- a/Source/MediaStorageAndFileFormat/gdcmBitmapToBitmapFilter.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmBitmapToBitmapFilter.cxx @@ -15,9 +15,9 @@ #include "gdcmImage.h" +#include // abort +#include // memcpy #include -#include // abort -#include // memcpy namespace gdcm { diff --git a/Source/MediaStorageAndFileFormat/gdcmCleaner.cxx b/Source/MediaStorageAndFileFormat/gdcmCleaner.cxx new file mode 100644 index 00000000000..e1600152608 --- /dev/null +++ b/Source/MediaStorageAndFileFormat/gdcmCleaner.cxx @@ -0,0 +1,1314 @@ +/*========================================================================= + + Program: GDCM (Grassroots DICOM). A DICOM library + + Copyright (c) 2006-2011 Mathieu Malaterre + All rights reserved. + See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "gdcmCleaner.h" +#include "gdcmAnonymizeEvent.h" +#include "gdcmAttribute.h" +#include "gdcmCSAHeader.h" +#include "gdcmDataSetHelper.h" +#include "gdcmDicts.h" +#include "gdcmEvent.h" +#include "gdcmGlobal.h" +#include "gdcmMEC_MR3.h" + +#include "gdcmext/csa.h" +#include "gdcmext/mec_mr3.h" + +namespace gdcm { + +static const PrivateTag part15_table_E_1_1[] = { + PrivateTag(0x0019, 0x0C, "SIEMENS MR HEADER"), + PrivateTag(0x0019, 0x0D, "SIEMENS MR HEADER"), + PrivateTag(0x0019, 0x0E, "SIEMENS MR HEADER"), + PrivateTag(0x0019, 0x23, "GEMS_ACQU_01"), + PrivateTag(0x0019, 0x24, "GEMS_ACQU_01"), + PrivateTag(0x0019, 0x27, "GEMS_ACQU_01"), + PrivateTag(0x0019, 0x27, "SIEMENS MR HEADER"), + PrivateTag(0x0019, 0x9E, "GEMS_ACQU_01"), + PrivateTag(0x0025, 0x01, "Philips ST80i"), + PrivateTag(0x0025, 0x07, "GEMS_SERS_01"), + PrivateTag(0x0043, 0x27, "GEMS_PARM_01"), + PrivateTag(0x0043, 0x39, "GEMS_PARM_01"), + PrivateTag(0x0043, 0x6F, "GEMS_PARM_01"), + PrivateTag(0x0045, 0x01, "GEMS_HELIOS_01"), + PrivateTag(0x0045, 0x02, "GEMS_HELIOS_01"), + PrivateTag(0x0099, 0x01, "NQHeader"), + PrivateTag(0x0099, 0x02, "NQHeader"), + PrivateTag(0x0099, 0x04, "NQHeader"), + PrivateTag(0x0099, 0x05, "NQHeader"), + PrivateTag(0x0099, 0x10, "NQHeader"), + PrivateTag(0x0099, 0x20, "NQHeader"), + PrivateTag(0x0099, 0x21, "NQHeader"), + PrivateTag(0x00E1, 0x21, "ELSCINT1"), + PrivateTag(0x00E1, 0x50, "ELSCINT1"), + PrivateTag(0x0119, 0x00, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0119, 0x01, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0119, 0x02, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0119, 0x03, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0119, 0x04, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0119, 0x05, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0119, 0x06, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0119, 0x07, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0119, 0x08, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0119, 0x09, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0119, 0x10, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0119, 0x11, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0119, 0x12, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0119, 0x13, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0119, 0x21, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0129, 0x00, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0129, 0x02, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0129, 0x03, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0129, 0x04, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0129, 0x05, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0129, 0x06, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0129, 0x07, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0129, 0x08, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0129, 0x09, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0129, 0x10, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0129, 0x11, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0129, 0x12, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0129, 0x20, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0129, 0x21, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0129, 0x22, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0129, 0x29, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0129, 0x30, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0139, 0x01, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0149, 0x01, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0149, 0x02, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0149, 0x03, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x0199, 0x01, "NQLeft"), + PrivateTag(0x0199, 0x02, "NQLeft"), + PrivateTag(0x0199, 0x03, "NQLeft"), + PrivateTag(0x0199, 0x04, "NQLeft"), + PrivateTag(0x0199, 0x05, "NQLeft"), + PrivateTag(0x0199, 0x06, "NQLeft"), + PrivateTag(0x0199, 0x07, "NQLeft"), + PrivateTag(0x0199, 0x08, "NQLeft"), + PrivateTag(0x0199, 0x09, "NQLeft"), + PrivateTag(0x0199, 0x0A, "NQLeft"), + PrivateTag(0x0199, 0x0B, "NQLeft"), + PrivateTag(0x0199, 0x0C, "NQLeft"), + PrivateTag(0x0199, 0x0D, "NQLeft"), + PrivateTag(0x0199, 0x0E, "NQLeft"), + PrivateTag(0x0199, 0x0F, "NQLeft"), + PrivateTag(0x0199, 0x10, "NQLeft"), + PrivateTag(0x0199, 0x11, "NQLeft"), + PrivateTag(0x0199, 0x12, "NQLeft"), + PrivateTag(0x0199, 0x13, "NQLeft"), + PrivateTag(0x0199, 0x14, "NQLeft"), + PrivateTag(0x0199, 0x15, "NQLeft"), + PrivateTag(0x0199, 0x16, "NQLeft"), + PrivateTag(0x01E1, 0x26, "ELSCINT1"), + PrivateTag(0x01F1, 0x01, "ELSCINT1"), + PrivateTag(0x01F1, 0x07, "ELSCINT1"), + PrivateTag(0x01F1, 0x26, "ELSCINT1"), + PrivateTag(0x01F1, 0x27, "ELSCINT1"), + PrivateTag(0x0299, 0x01, "NQRight"), + PrivateTag(0x0299, 0x02, "NQRight"), + PrivateTag(0x0299, 0x03, "NQRight"), + PrivateTag(0x0299, 0x04, "NQRight"), + PrivateTag(0x0299, 0x05, "NQRight"), + PrivateTag(0x0299, 0x06, "NQRight"), + PrivateTag(0x0299, 0x07, "NQRight"), + PrivateTag(0x0299, 0x08, "NQRight"), + PrivateTag(0x0299, 0x09, "NQRight"), + PrivateTag(0x0299, 0x0A, "NQRight"), + PrivateTag(0x0299, 0x0B, "NQRight"), + PrivateTag(0x0299, 0x0C, "NQRight"), + PrivateTag(0x0299, 0x0D, "NQRight"), + PrivateTag(0x0299, 0x0E, "NQRight"), + PrivateTag(0x0299, 0x0F, "NQRight"), + PrivateTag(0x0299, 0x10, "NQRight"), + PrivateTag(0x0299, 0x11, "NQRight"), + PrivateTag(0x0299, 0x12, "NQRight"), + PrivateTag(0x0299, 0x13, "NQRight"), + PrivateTag(0x0299, 0x14, "NQRight"), + PrivateTag(0x0299, 0x15, "NQRight"), + PrivateTag(0x0299, 0x16, "NQRight"), + PrivateTag(0x0903, 0x10, "GEIIS PACS"), + PrivateTag(0x0903, 0x11, "GEIIS PACS"), + PrivateTag(0x0903, 0x12, "GEIIS PACS"), + PrivateTag(0x2001, 0x00, "Philips Imaging DD 129"), + PrivateTag(0x2001, 0x01, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x01, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x01, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x01, "Philips Imaging DD 129"), + PrivateTag(0x2001, 0x02, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x02, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x02, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x02, "Philips Imaging DD 129"), + PrivateTag(0x2001, 0x03, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x03, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x03, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x03, "Philips Imaging DD 129"), + PrivateTag(0x2001, 0x04, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x04, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x04, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x04, "Philips Imaging DD 129"), + PrivateTag(0x2001, 0x05, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x05, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x05, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x05, "Philips Imaging DD 129"), + PrivateTag(0x2001, 0x06, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x06, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x06, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x06, "Philips Imaging DD 129"), + PrivateTag(0x2001, 0x07, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x07, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x07, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x07, "Philips Imaging DD 129"), + PrivateTag(0x2001, 0x08, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x08, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x08, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x08, "Philips Imaging DD 129"), + PrivateTag(0x2001, 0x09, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x09, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x09, "Philips Imaging DD 129"), + PrivateTag(0x2001, 0x0A, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x0A, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x0A, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x0B, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x0B, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x0B, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x0C, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x0C, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x0D, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x0D, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x0E, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x0E, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x0E, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x0F, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x0F, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x0F, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x10, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x10, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x11, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x11, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x12, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x12, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x12, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x13, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x13, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x14, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x14, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x15, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x15, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x16, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x16, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x17, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x17, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x17, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x18, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x18, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x18, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x19, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x19, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x19, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x1A, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x1A, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x1A, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x1B, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x1B, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x1B, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x1C, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x1C, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x1C, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x1D, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x1D, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x1D, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x1E, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x1E, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x1E, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x1F, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x1F, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x1F, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x20, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x21, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x21, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x21, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x22, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x22, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x22, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x23, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x23, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x23, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x24, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x24, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x24, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x25, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x25, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x25, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x26, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x26, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x26, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x27, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x27, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x27, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x28, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x28, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x28, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x29, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x29, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x2A, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x2A, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x2A, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x2B, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x2B, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x2B, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x2C, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x2C, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x2C, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x2D, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x2D, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x2D, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x2E, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x2E, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x2E, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x2F, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x2F, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x2F, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x30, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x30, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x30, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x31, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x31, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x31, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x32, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x32, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x32, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x33, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x33, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x34, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x34, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x35, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x35, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x36, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x36, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x36, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x37, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x37, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x37, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x38, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x38, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x38, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x39, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x39, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x39, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x3A, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x3A, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x3A, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x3B, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x3B, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x3B, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x3C, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x3C, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x3C, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x3D, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x3D, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x3D, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x3E, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x3E, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x3E, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x3F, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x3F, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x40, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x40, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x40, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x41, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x41, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x42, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x42, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x43, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x44, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x44, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x45, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x45, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x46, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x46, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x47, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x47, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x48, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x49, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x49, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x4A, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x4A, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x4B, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x4B, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x4C, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x4C, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0x4D, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x4E, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x4F, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x50, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x50, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x51, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x52, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x53, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x53, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x54, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x55, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x56, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x57, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x57, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x58, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x58, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x59, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x5A, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x5A, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x5C, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x5D, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x5D, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x5E, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x5E, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x5F, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x5F, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x60, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x61, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x62, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x63, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x63, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x64, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x64, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x65, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x65, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x66, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x66, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x67, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x67, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x68, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x68, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x69, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x6A, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x6B, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x6B, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x6D, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x6E, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x6F, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x71, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x71, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x72, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x72, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x73, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x73, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x74, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x74, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x75, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x75, "Philips Imaging DD 002"), + PrivateTag(0x2001, 0x76, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x77, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x79, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x7A, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x7B, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x7C, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x7D, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x7E, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x7F, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x80, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x81, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x82, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x83, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x84, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x85, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x86, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x87, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x88, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x89, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x8A, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x8B, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x8C, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x90, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x91, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x92, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x93, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x94, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x9A, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x9B, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x9D, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0x9F, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xA1, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xA1, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0xA2, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xA2, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0xA3, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xA3, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0xA4, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xA4, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0xA5, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xA5, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0xA6, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0xA8, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0xA9, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0xAA, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0xAB, "Philips Imaging DD 097"), + PrivateTag(0x2001, 0xC0, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xC1, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xC2, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xC3, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xC5, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xC6, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xC7, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xCA, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xCB, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xD0, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xD1, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xD2, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xD3, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xD4, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xD5, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xD6, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xD7, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xD8, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xD9, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xDA, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xDB, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xDC, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xDD, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xDE, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xDF, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xE9, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xF1, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xF2, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xF3, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xF4, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xF5, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xF6, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xF7, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xF9, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xFB, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xFC, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xFD, "Philips Imaging DD 001"), + PrivateTag(0x2001, 0xFF, "Philips Imaging DD 001"), + PrivateTag(0x2005, 0x0D, "Philips MR Imaging DD 001"), + PrivateTag(0x2005, 0x0E, "Philips MR Imaging DD 001"), + PrivateTag(0x7053, 0x00, "Philips PET Private Group"), + PrivateTag(0x7053, 0x09, "Philips PET Private Group"), + PrivateTag(0x7E01, 0x01, "HOLOGIC, Inc."), + PrivateTag(0x7E01, 0x02, "HOLOGIC, Inc."), + PrivateTag(0x7E01, 0x10, "HOLOGIC, Inc."), + PrivateTag(0x7E01, 0x11, "HOLOGIC, Inc."), + PrivateTag(0x7E01, 0x12, "HOLOGIC, Inc."), + PrivateTag(0x7FD1, 0x01, "SIEMENS SYNGO ULTRA-SOUND TOYON DATA STREAMING"), + PrivateTag(0x7FD1, 0x01, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x7FD1, 0x09, "SIEMENS SYNGO ULTRA-SOUND TOYON DATA STREAMING"), + PrivateTag(0x7FD1, 0x09, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x7FD1, 0x10, "SIEMENS SYNGO ULTRA-SOUND TOYON DATA STREAMING"), + PrivateTag(0x7FD1, 0x10, "SIEMENS Ultrasound SC2000"), + PrivateTag(0x7FD1, 0x11, "SIEMENS SYNGO ULTRA-SOUND TOYON DATA STREAMING"), + PrivateTag(0x7FD1, 0x11, "SIEMENS Ultrasound SC2000"), +}; + +static inline bool in_part15(const PrivateTag &pt) { + static const size_t len = + sizeof(part15_table_E_1_1) / sizeof *part15_table_E_1_1; + for (size_t i = 0; i < len; ++i) { + if (part15_table_E_1_1[i] == pt) { + return true; + } + } + return false; +} + +typedef std::set DataElementSet; +typedef DataElementSet::const_iterator ConstIterator; + +struct Cleaner::impl { + std::set preserve_dpaths; + std::set empty_dpaths; + std::set remove_dpaths; + std::set scrub_dpaths; + std::set empty_tags; + std::set empty_privatetags; + std::set remove_tags; + std::set remove_privatetags; + std::set scrub_tags; + std::set scrub_privatetags; + std::set empty_vrs; + std::set remove_vrs; + bool AllMissingPrivateCreator; + bool AllGroupLength; + bool AllIllegal; + impl() + : AllMissingPrivateCreator(true), + AllGroupLength(true), + AllIllegal(true) {} + + enum ACTION { NONE, EMPTY, REMOVE, SCRUB }; + enum ACTION ComputeAction(File const &file, DataSet &ds, + const DataElement &de, VR const &ref_dict_vr, + const std::string &tag_path); + + bool ProcessDataSet(Subject &s, File &file, DataSet &ds, + const std::string &tag_path); + + template + bool CheckVRBeforeInsert(std::set &empty_or_remove_vrs, T const &t, + std::set &set) { + if (empty_or_remove_vrs.empty()) { + set.insert(t); + return true; + } else { + // Let's check if VR of tag is already contained in VR + static const Global &g = GlobalInstance; + static const Dicts &dicts = g.GetDicts(); + const DictEntry &entry = dicts.GetDictEntry(t); + const VR &refvr = entry.GetVR(); + if (empty_or_remove_vrs.find(refvr) != empty_or_remove_vrs.end()) { + gdcmWarningMacro( + "Tag: " << t << " is also cleanup with VR cleaning. skipping"); + } else if (refvr == VR::INVALID) { + gdcmWarningMacro("inserting unknown tag " + << t << ". no check on VR is done"); + set.insert(t); + } else { + set.insert(t); + } + return true; + } + } + bool Empty(Tag const &t) { + if (t.IsPublic() && !t.IsGroupLength()) { + return CheckVRBeforeInsert(empty_vrs, t, empty_tags); + } + return false; + } + bool Empty(PrivateTag const &pt) { + const char *owner = pt.GetOwner(); + if (pt.IsPrivate() && *owner) { + if (in_part15(pt)) { + gdcmErrorMacro("Cannot add Part 15 attribute for now"); + return false; + } + return CheckVRBeforeInsert(empty_vrs, pt, empty_privatetags); + } + return false; + } + bool Empty(DPath const &dpath) { + empty_dpaths.insert(dpath); + return true; + } + bool Empty(VR const &vr) { + if (vr == VR::PN) { + empty_vrs.insert(vr); + return true; + } + return false; + } + + bool Remove(Tag const &t) { + if (t.IsPublic() && !t.IsGroupLength()) { + return CheckVRBeforeInsert(remove_vrs, t, remove_tags); + } + return false; + } + bool Remove(PrivateTag const &pt) { + const char *owner = pt.GetOwner(); + if (pt.IsPrivate() && *owner) { + if (in_part15(pt)) { + gdcmErrorMacro("Cannot add Part 15 attribute for now"); + return false; + } + return CheckVRBeforeInsert(remove_vrs, pt, remove_privatetags); + } + return false; + } + bool Remove(DPath const &dpath) { + remove_dpaths.insert(dpath); + return true; + } + bool Remove(VR const &vr) { + if (vr == VR::PN) { + remove_vrs.insert(vr); + return true; + } + return false; + } + + bool Scrub(Tag const & /*t*/) { return false; } + bool Scrub(PrivateTag const &pt) { + static const PrivateTag &csa1 = CSAHeader::GetCSAImageHeaderInfoTag(); + static const PrivateTag &csa2 = CSAHeader::GetCSASeriesHeaderInfoTag(); + const PrivateTag mec_mr3(0x700d, 0x08, "TOSHIBA_MEC_MR3"); + static const PrivateTag &pmtf1 = gdcm::MEC_MR3::GetPMTFInformationDataTag(); + static const PrivateTag &pmtf2 = gdcm::MEC_MR3::GetToshibaMECMR3Tag(); + static const PrivateTag &pmtf3 = gdcm::MEC_MR3::GetCanonMECMR3Tag(); + + if (pt == csa1 || pt == csa2 || pt == mec_mr3 || pt == pmtf1 || + pt == pmtf2 || pt == pmtf3) { + scrub_privatetags.insert(pt); + return true; + } + return false; + } + bool Scrub(DPath const &dpath) { + scrub_dpaths.insert(dpath); + return true; + } + + bool Scrub(VR const & /*vr*/) { return false; } + + bool Preserve(DPath const &dpath) { + preserve_dpaths.insert(dpath); + return true; + } + + void RemoveAllMissingPrivateCreator(bool remove) { + AllMissingPrivateCreator = remove; + } + bool RemoveMissingPrivateCreator(Tag const & /*t*/) { return false; } + void RemoveAllGroupLength(bool remove) { AllGroupLength = remove; } + void RemoveAllIllegal(bool remove) { AllIllegal = remove; } +}; + +static VR ComputeDictVR(File &file, DataSet &ds, DataElement const &de) { + VR dict_vr = de.GetVR(); + const Tag &tag = de.GetTag(); + bool compute_dict_vr = true; + if (tag.IsPublic() || tag.IsGroupLength() || tag.IsPrivateCreator()) { + } else { + const PrivateTag pt = ds.GetPrivateTag(tag); + const char *owner = pt.GetOwner(); + assert(owner); + compute_dict_vr = *owner != 0; + } + if (compute_dict_vr) dict_vr = DataSetHelper::ComputeVR(file, ds, tag); + + if (de.GetVR() == VR::SQ) { + assert(dict_vr != VR::UN); + if (!dict_vr.Compatible(de.GetVR())) { + gdcmErrorMacro("Impossible. Dict states VR is: " + << dict_vr << " which is impossible for SQ"); + dict_vr = VR::SQ; + } + } + if (dict_vr != VR::SQ) { + if (de.GetVL().IsUndefined()) { + Tag pixelData(0x7fe0, 0x0010); + assert(dict_vr == VR::OB); + if (tag != pixelData) { + gdcmErrorMacro("Impossible happen: " << de); + return VR::SQ; + } + } + } + return dict_vr; +} + +static inline std::string tostring(uint16_t const val, int const width = 4) { + std::ostringstream oss; + oss.setf(std::ios::right); + oss << std::hex << std::setw(width) << std::setfill('0') << val; + return oss.str(); +} + +static std::vector tag2strings(DataSet const &ds, Tag const &tag) { + std::vector ret; + if (tag.IsPublic() || tag.IsPrivateCreator() || tag.IsGroupLength()) { + ret.push_back(tostring(tag.GetGroup())); + ret.push_back(tostring(tag.GetElement())); + } else { + const PrivateTag pt = ds.GetPrivateTag(tag); + ret.push_back(tostring(pt.GetGroup())); + ret.push_back(tostring(pt.GetElement(), 2)); + ret.push_back(pt.GetOwner()); + } + return ret; +} + +template +static void print_contents(std::ostream &oss, const std::vector &v, + const char *const separator = ",") { + if (!v.empty()) { + std::copy(v.begin(), --v.end(), std::ostream_iterator(oss, separator)); + oss << v.back(); + } +} + +static bool isAllZero(const char *buffer, size_t len) { + while (len-- > 0) { + if (buffer[len] != 0) return false; + } + return true; +} + +enum CSAImageHeaderType { + IMAGE_UNK = -1, + HG_IRECORD = 0, // label:=Standard, no PHI + IMAGE_NUM_4, // SV10 + IMAGE_MR, // SV10 + NONIMAGE_NUM_4, // SV10 + NUC_FLOOD, // binary data, no PHI + PET_NUM_4, // SV10 + SOM_5, // Explicit LE, "END! ", no PHI +}; + +static const char *CSAImageHeaderTypeStrings[]{ + "HG IRECORD", // + "IMAGE NUM 4", // + "MR", // + "NONIMAGE NUM 4", // + "NUC FLOOD", // + "PET NUM 4", // + "SOM 5" // +}; + +enum CSASeriesHeaderType { + SERIES_UNK = -1, + HG_RECORD_SERIES = + 0, // => 0029,xx40 contains a sequence with "HG RECORD", no PHI + SERIES_MR, // SV10 + ParameterBlock, // , no PHI + PET_REPLAY_PARAM, // , no PHI + PT, // SV10 + SOM_7_DEV, // ORIGINALSERIES=, no PHI +}; + +static const char *CSASeriesHeaderTypeStrings[]{ + "HG RECORD SERIES", // HG_RECORD_SERIES + "MR", // SERIES_MR + "ParameterBlock", // ParameterBlock + "PET_REPLAY_PARAM", // + "PT", // + "SOM 7 DEV" // SOM_7_DEV +}; + +template +static T GetCSAType(std::string &ref, const DataSet &ds, const PrivateTag &pt, + const char *(&array)[N]) { + T series_type = (T)-1; // UNK + ref = ""; + if (ds.FindDataElement(pt)) { + const gdcm::DataElement &de1 = ds.GetDataElement(pt); + Element el = {}; + el.SetFromDataElement(de1); + ref = el.GetValue().Trim(); + for (int i = 0; i < N; i++) { + if (strcmp(array[i], ref.c_str()) == 0) { + series_type = (T)(i); + } + } + } + return series_type; +} + +// byte-swapped memcmp implementation: +static inline int bs_memcmp(const void *s1, const void *s2, size_t n) { + size_t i; + const unsigned char *us1 = (const unsigned char *)s1; + const unsigned char *us2 = (const unsigned char *)s2; + assert(n % 2 == 0); + + for (i = 0; i < n; i += 2, us1 += 2, us2 += 2) { + if (*us1 < *(us2 + 1)) { + return -1; + } else if (*us1 > *(us2 + 1)) { + return 1; + } + + if (*(us1 + 1) < *us2) { + return -1; + } else if (*(us1 + 1) > *us2) { + return 1; + } + } + return 0; +} + +static inline bool is_signature(const ByteValue *bv, const char *str) { + const size_t len = strlen(str); + if (bv->GetLength() >= len && memcmp(bv->GetPointer(), str, len) == 0) { + return true; + } + return false; +} + +static inline bool bs_is_signature(const ByteValue *bv, const char *str) { + const size_t len = strlen(str); + if (bv->GetLength() >= len && bs_memcmp(bv->GetPointer(), str, len) == 0) { + return true; + } + return false; +} + +static bool CleanCSAImage(DataSet &ds, const DataElement &de) { + const ByteValue *bv = de.GetByteValue(); + // fast path: + if (!bv) return true; + + CSAImageHeaderType image_type = IMAGE_UNK; + std::string ref; + { + const PrivateTag ihtTag(0x0029, 0x08, "SIEMENS CSA HEADER"); + image_type = GetCSAType(ref, ds, ihtTag, + CSAImageHeaderTypeStrings); + } + static const char sv10[] = "SV10\4\3\2\1"; // 8 + // what if a dumb anonymizer removed the CSA Image Header Type: + bool isSV10 = false; + if (image_type == IMAGE_UNK) { + if (is_signature(bv, sv10)) { + if (!ref.empty()) { + gdcmWarningMacro( + "Please report. SV10 Header found for new type: " << ref); + } + isSV10 = true; + } + } + + // easy case: recognized keywords: + if (image_type == IMAGE_NUM_4 // MR Image Storage / NUMARIS/4 + || image_type == IMAGE_MR // Enhanced SR Storage + || image_type == NONIMAGE_NUM_4 // CSA Non-Image Storage + || image_type == PET_NUM_4 // Positron Emission Tomography Image Storage + || isSV10) { + DataElement clean(de.GetTag()); + clean.SetVR(de.GetVR()); + std::vector v; + v.resize(bv->GetLength()); + if (csa_memcpy(v.data(), bv->GetPointer(), bv->GetLength())) { + clean.SetByteValue(v.data(), (uint32_t)v.size()); + ds.Replace(clean); + return true; + } + // we failed to clean CSA, let's check possible well known errors + if (bs_is_signature(bv, sv10)) { + gdcmWarningMacro("Found byte-swapped SV10. Skipping."); + return true; + } else if (isAllZero(bv->GetPointer(), bv->GetLength())) { + gdcmDebugMacro("Zero-out CSA header"); + return true; + } + gdcmErrorMacro("Failure to call CleanCSAImage"); + return false; + } + // else + // add a dummy check for SV10 signature + if (is_signature(bv, sv10)) { + gdcmErrorMacro("Failure to clean SV10 Header for type: " << ref); + return false; + } + return true; +} + +static bool CleanCSASeries(DataSet &ds, const DataElement &de) { + const ByteValue *bv = de.GetByteValue(); + // fast path: + if (!bv) return true; + + CSASeriesHeaderType series_type = SERIES_UNK; + std::string ref; + { + const PrivateTag shtTag(0x0029, 0x18, "SIEMENS CSA HEADER"); + series_type = GetCSAType(ref, ds, shtTag, + CSASeriesHeaderTypeStrings); + } + static const char sv10[] = "SV10\4\3\2\1"; // 8 + // what if a dumb anonymizer removed the CSA Series Header Type: + bool isSV10 = false; + if (series_type == SERIES_UNK) { + if (is_signature(bv, sv10)) { + if (!ref.empty()) { + gdcmWarningMacro( + "Please report. SV10 Header found for new type: " << ref); + } + isSV10 = true; + } + } + + // easy case: recognized keywords: + if (series_type == PT || series_type == SERIES_MR || isSV10) { + DataElement clean(de.GetTag()); + clean.SetVR(de.GetVR()); + std::vector v; + v.resize(bv->GetLength()); + if (csa_memcpy(v.data(), bv->GetPointer(), bv->GetLength())) { + clean.SetByteValue(v.data(), (uint32_t)v.size()); + ds.Replace(clean); + return true; + } + // we failed to clean CSA, let's check possible well known errors + if (bs_is_signature(bv, sv10)) { + gdcmWarningMacro("Found byte-swapped SV10. Skipping."); + return true; + } else if (isAllZero(bv->GetPointer(), bv->GetLength())) { + gdcmDebugMacro("Zero-out CSA header"); + return true; + } + gdcmErrorMacro("Failure to call CleanCSASeries"); + return false; + } + // else + // add a dummy check for SV10 signature + if (is_signature(bv, sv10)) { + gdcmErrorMacro("Failure to clean SV10 Header for type: " << ref); + return false; + } + return true; +} + +static bool CleanMEC_MR3(DataSet &ds, const DataElement &de) { + const ByteValue *bv = de.GetByteValue(); + // fast path: + if (!bv) return true; + + DataElement clean(de.GetTag()); + clean.SetVR(de.GetVR()); + std::vector v; + v.resize(bv->GetLength()); + { + // check a pseudo magic value here: + uint32_t magic = 0xffff; + if (bv->GetLength() > 4) { + memcpy(&magic, bv->GetPointer(), sizeof magic); + } + if (magic > 512) { + gdcmWarningMacro("Cannot handle MEC_MR3"); + return true; + } + } + if (mec_mr3_memcpy(v.data(), bv->GetPointer(), bv->GetLength())) { + clean.SetByteValue(v.data(), (uint32_t)v.size()); + ds.Replace(clean); + return true; + } + gdcmErrorMacro("Failure to call CleanMEC_MR3"); + return false; +} + +static bool CleanPMTF(DataSet &ds, const DataElement &de) { + const ByteValue *bv = de.GetByteValue(); + // fast path: + if (!bv) return true; + const char *input = bv->GetPointer(); + const size_t len = bv->GetLength(); + + gdcm::Cleaner cleaner; + gdcm::File &file = cleaner.GetFile(); + gdcm::DataSet &revds = file.GetDataSet(); + try { + std::istringstream is; + { + std::vector copy(input, input + len); + std::reverse(copy.begin(), copy.end()); + std::string dup(copy.data(), copy.size()); + is.str(dup); + } + + // FIXME gdcm::Cleaner will by default change defined length SQ into undef + // length...there is a risk of incompatibily with vendor + gdcm::FileMetaInformation &fmi = file.GetHeader(); + fmi.SetDataSetTransferSyntax(gdcm::TransferSyntax::ExplicitVRLittleEndian); + revds.Read(is); + } catch (...) { + gdcmDebugMacro("Unhanded file format"); + return true; + } + + bool success = true; + try { + gdcm::VR vr = VR::PN; + cleaner.Empty(vr); + if (!cleaner.Clean()) { + success = false; + } else { + std::ostringstream os; + revds.Write(os); + const std::string str = os.str(); + std::vector v(str.c_str(), str.c_str() + str.size()); + std::reverse(v.begin(), v.end()); + + DataElement clean(de.GetTag()); + clean.SetVR(de.GetVR()); + clean.SetByteValue(v.data(), (uint32_t)v.size()); + ds.Replace(clean); + } + } catch (...) { + success = false; + } + + if (success) { + return true; + } + gdcmErrorMacro("Failure to call CleanPMTF"); + return false; +} + +static DPath ConstructDPath(std::string const &tag_path, const DataSet &ds, + const Tag &tag) { + DPath dpath; + std::ostringstream oss; + oss << tag_path; + const std::vector tag_strings = tag2strings(ds, tag); + print_contents(oss, tag_strings); + dpath.ConstructFromString(oss.str().c_str()); + return dpath; +} + +static bool IsDPathInSet(std::set const &aset, DPath const dpath) { + bool found = false; + for (std::set::const_iterator it = aset.begin(); + found == false && it != aset.end(); ++it) { + found = it->Match(dpath); + } + + return found; +} + +Cleaner::impl::ACTION Cleaner::impl::ComputeAction( + File const & /*file*/, DataSet &ds, const DataElement &de, VR const &ref_dict_vr, + const std::string &tag_path) { + const Tag &tag = de.GetTag(); + // Group Length & Illegal cannot be preserved so it is safe to do them now: + if (tag.IsGroupLength()) { + if (AllGroupLength) return Cleaner::impl::REMOVE; + } else if (tag.IsIllegal()) { + if (AllIllegal) return Cleaner::impl::REMOVE; + } + + if (tag.IsPublic()) { + const DPath dpath = ConstructDPath(tag_path, ds, tag); + // Preserve + if (IsDPathInSet(preserve_dpaths, dpath)) return Cleaner::impl::NONE; + // Scrub + if (scrub_tags.find(tag) != scrub_tags.end() || + IsDPathInSet(scrub_dpaths, dpath)) { + return Cleaner::impl::SCRUB; + } + // Empty + if (empty_tags.find(tag) != empty_tags.end() || + IsDPathInSet(empty_dpaths, dpath)) { + assert(!tag.IsGroupLength()); + assert(!tag.IsPrivateCreator()); + assert(ds.FindDataElement(tag)); + return Cleaner::impl::EMPTY; + } + // Remove + if (remove_tags.find(tag) != remove_tags.end() || + IsDPathInSet(remove_dpaths, dpath)) { + return Cleaner::impl::REMOVE; + } + } + + if (tag.IsPrivate() && !tag.IsPrivateCreator() && !tag.IsGroupLength()) { + const PrivateTag pt = ds.GetPrivateTag(tag); + const char *owner = pt.GetOwner(); + assert(owner); + if (*owner == 0 && AllMissingPrivateCreator) { + return Cleaner::impl::REMOVE; + } + // At this point we have a private creator, it makes sense to check for + // preserve: Preserve + const DPath dpath = ConstructDPath(tag_path, ds, tag); + if (IsDPathInSet(preserve_dpaths, dpath)) return Cleaner::impl::NONE; + // Scrub + if (scrub_privatetags.find(pt) != scrub_privatetags.end() || + IsDPathInSet(scrub_dpaths, dpath)) { + return Cleaner::impl::SCRUB; + } + // Empty + if (empty_privatetags.find(pt) != empty_privatetags.end() || + IsDPathInSet(empty_dpaths, dpath)) { + return Cleaner::impl::EMPTY; + } + // Remove + if (remove_privatetags.find(pt) != remove_privatetags.end() || + IsDPathInSet(remove_dpaths, dpath)) { + return Cleaner::impl::REMOVE; + } + } + + // VR cleanup + if (!empty_vrs.empty() || !remove_vrs.empty()) { + VR vr = de.GetVR(); + assert(ref_dict_vr != VR::INVALID); + // be careful with vr handling since we must always prefer the one from + // the dict in case of attribute written as 'OB' but dict states 'PN': + if (ref_dict_vr != VR::UN /*&& ref_dict_vr != VR::INVALID*/) { + // we want to clean VR==PN; but this is a problem for implicit transfer + // syntax, so let's be nice to the user and prefer dict_vr. however for + // explicit, do not assume value in dict can take over the read VR + if (vr == VR::UN || vr == VR::INVALID) { + vr = ref_dict_vr; + } + if (vr != ref_dict_vr) { + // assert(vr == VR::OB || vr == VR::OW); + vr = ref_dict_vr; + } + } + // Empty + if (empty_vrs.find(vr) != empty_vrs.end()) { + return Cleaner::impl::EMPTY; + } + // Remove + if (remove_vrs.find(vr) != remove_vrs.end()) { + return Cleaner::impl::REMOVE; + } + } + + // default action: + return Cleaner::impl::NONE; +} + +bool Cleaner::impl::ProcessDataSet(Subject &subject, File &file, DataSet &ds, + const std::string &tag_path) { + subject.InvokeEvent(IterationEvent()); + ConstIterator it = ds.GetDES().begin(); + + for (; it != ds.GetDES().end(); /*++it*/) { + const DataElement &de = *it; + ++it; // 'Remove/Empty' may invalidate iterator + const Tag &tag = de.GetTag(); + AnonymizeEvent ae; + ae.SetTag(tag); + + VR dict_vr = ComputeDictVR(file, ds, de); + Cleaner::impl::ACTION action = + Cleaner::impl::ComputeAction(file, ds, de, dict_vr, tag_path); + + if (action == Cleaner::impl::NONE) { + // nothing to do, but recurse in nested-dataset: + if (dict_vr == VR::SQ) { + SmartPointer sqi = de.GetValueAsSQ(); + if (sqi) { + SequenceOfItems::SizeType s = sqi->GetNumberOfItems(); + for (SequenceOfItems::SizeType i = 1; i <= s; ++i) { + Item &item = sqi->GetItem(i); + + DataSet &nestedds = item.GetNestedDataSet(); + const std::vector tag_strings = tag2strings(ds, tag); + + std::ostringstream os; + os << tag_path; // already padded with trailing '/' + print_contents(os, tag_strings); + os << '/'; + os << '*'; // no need for item numbering + os << '/'; + + if (!ProcessDataSet(subject, file, nestedds, os.str())) { + gdcmErrorMacro("Error processing Item #" << i); + return false; + } + // Simple memcmp to avoid recomputation of Item Length: make them + // undefined length. TODO would be nice to only do this when + // strictly needed. + item.SetVLToUndefined(); + } + // Simple mechanism to avoid recomputation of Sequence Length: make + // them undefined length + DataElement dup(de.GetTag()); + dup.SetVR(VR::SQ); + dup.SetValue(*sqi); + dup.SetVLToUndefined(); + ds.Replace(dup); + } else { + // SmartPointer sqi = de.GetValueAsSQ(); + if (!de.IsEmpty()) { + gdcmWarningMacro( + "Please report. Dictionary states this should be a SQ. But " + "we " + "failed to load it as such. Passing-through as-is" + << de); + } + } + } + } else if (action == Cleaner::impl::EMPTY) { + DataElement clean(de.GetTag()); + clean.SetVR(de.GetVR()); + ds.Replace(clean); + subject.InvokeEvent(ae); + } else if (action == Cleaner::impl::REMOVE) { + ds.Remove(tag); + subject.InvokeEvent(ae); + } else if (action == Cleaner::impl::SCRUB) { + const PrivateTag pt = ds.GetPrivateTag(tag); + + static const PrivateTag &csa1 = CSAHeader::GetCSAImageHeaderInfoTag(); + static const PrivateTag &csa2 = CSAHeader::GetCSASeriesHeaderInfoTag(); + const PrivateTag mec_mr3(0x700d, 0x08, "TOSHIBA_MEC_MR3"); + static const PrivateTag &pmtf1 = + gdcm::MEC_MR3::GetPMTFInformationDataTag(); + static const PrivateTag &pmtf2 = gdcm::MEC_MR3::GetToshibaMECMR3Tag(); + static const PrivateTag &pmtf3 = gdcm::MEC_MR3::GetCanonMECMR3Tag(); + + if (pt == csa1) { + const bool ret = CleanCSAImage(ds, de); + if (!ret) return false; + } else if (pt == csa2) { + const bool ret = CleanCSASeries(ds, de); + if (!ret) return false; + } else if (pt == mec_mr3) { + const bool ret = CleanMEC_MR3(ds, de); + if (!ret) return false; + } else if (pt == pmtf1) { + const bool ret = CleanPMTF(ds, de); + if (!ret) return false; + } else if (pt == pmtf2) { + const bool ret = CleanPMTF(ds, de); + if (!ret) return false; + } else if (pt == pmtf3) { + const bool ret = CleanPMTF(ds, de); + if (!ret) return false; + } else { + gdcmErrorMacro(" not implemented"); + return false; + } + subject.InvokeEvent(ae); + } else { + gdcmErrorMacro("Missing handling of action: " << action); + return false; + } + } + return true; +} + +Cleaner::Cleaner() : F(new File), pimpl(new impl) {} + +Cleaner::~Cleaner() { delete pimpl; } + +bool Cleaner::Empty(Tag const &t) { return pimpl->Empty(t); } +bool Cleaner::Empty(PrivateTag const &pt) { return pimpl->Empty(pt); } +bool Cleaner::Empty(DPath const &dpath) { return pimpl->Empty(dpath); } +bool Cleaner::Empty(VR const &vr) { return pimpl->Empty(vr); } + +bool Cleaner::Remove(Tag const &t) { return pimpl->Remove(t); } +bool Cleaner::Remove(PrivateTag const &pt) { return pimpl->Remove(pt); } +bool Cleaner::Remove(DPath const &dpath) { return pimpl->Remove(dpath); } +bool Cleaner::Remove(VR const &vr) { return pimpl->Remove(vr); } + +bool Cleaner::Scrub(Tag const &t) { return pimpl->Scrub(t); } +bool Cleaner::Scrub(PrivateTag const &pt) { return pimpl->Scrub(pt); } +bool Cleaner::Scrub(DPath const &dpath) { return pimpl->Scrub(dpath); } +bool Cleaner::Scrub(VR const &vr) { return pimpl->Scrub(vr); } + +bool Cleaner::Preserve(DPath const &dpath) { return pimpl->Preserve(dpath); } + +void Cleaner::RemoveAllMissingPrivateCreator(bool remove) { + pimpl->RemoveAllMissingPrivateCreator(remove); +} +bool Cleaner::RemoveMissingPrivateCreator(Tag const &t) { + return pimpl->RemoveMissingPrivateCreator(t); +} +void Cleaner::RemoveAllGroupLength(bool remove) { + pimpl->RemoveAllGroupLength(remove); +} +void Cleaner::RemoveAllIllegal(bool remove) { pimpl->RemoveAllIllegal(remove); } + +bool Cleaner::Clean() { + DataSet &ds = F->GetDataSet(); + this->InvokeEvent(StartEvent()); + const bool ret = pimpl->ProcessDataSet(*this, *F, ds, "/"); + this->InvokeEvent(EndEvent()); + return ret; +} + +} // end namespace gdcm diff --git a/Source/MediaStorageAndFileFormat/gdcmCleaner.h b/Source/MediaStorageAndFileFormat/gdcmCleaner.h new file mode 100644 index 00000000000..4d8c351abe7 --- /dev/null +++ b/Source/MediaStorageAndFileFormat/gdcmCleaner.h @@ -0,0 +1,90 @@ +/*========================================================================= + + Program: GDCM (Grassroots DICOM). A DICOM library + + Copyright (c) 2006-2011 Mathieu Malaterre + All rights reserved. + See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef GDCMCLEANER_H +#define GDCMCLEANER_H + +#include "gdcmDPath.h" +#include "gdcmFile.h" +#include "gdcmSmartPointer.h" +#include "gdcmSubject.h" + +namespace gdcm { +/** + * \brief Cleaner + * + * This class implement the Subject/Observer pattern trigger the following + * event: \li AnonymizeEvent \li IterationEvent \li StartEvent \li EndEvent + * + */ +class GDCM_EXPORT Cleaner : public Subject { + public: + Cleaner(); + ~Cleaner() override; + + /// + bool Empty(Tag const &t); + bool Empty(PrivateTag const &pt); + bool Empty(DPath const &dpath); + bool Empty(VR const &vr); + + bool Remove(Tag const &t); + bool Remove(PrivateTag const &pt); + bool Remove(DPath const &dpath); + bool Remove(VR const &vr); + + /// Clean digital tash (typically SIEMENS CSA header): + bool Scrub(Tag const &t); + bool Scrub(PrivateTag const &pt); + bool Scrub(DPath const &dpath); + bool Scrub(VR const &vr); + + bool Preserve(DPath const &dpath); + + /// Should I remove all private tag for which no private creator is found. + /// Default: true + void RemoveAllMissingPrivateCreator(bool remove); + + /// Specify a private tag (odd number) without a private creator (root level + /// only for now): + bool RemoveMissingPrivateCreator(Tag const &t); + + /// Should I remove all group length (deprecated). Default: true + void RemoveAllGroupLength(bool remove); + + /// Should I remove all illegal attribute. Default: true + void RemoveAllIllegal(bool remove); + + /// main loop + bool Clean(); + + /// Set/Get File + void SetFile(const File &f) { F = f; } + // const File &GetFile() const { return *F; } + File &GetFile() { return *F; } + + /// for wrapped language: instantiate a reference counted object + static SmartPointer New() { return new Cleaner; } + + private: + // I would prefer to have a smart pointer to DataSet but DataSet does not + // derive from Object... + SmartPointer F; + struct impl; + // PIMPL idiom + impl *pimpl; +}; + +} // end namespace gdcm + +#endif // GDCMCLEANER_H diff --git a/Source/MediaStorageAndFileFormat/gdcmConstCharWrapper.h b/Source/MediaStorageAndFileFormat/gdcmConstCharWrapper.h index bf8601efb1b..15633cc67cf 100644 --- a/Source/MediaStorageAndFileFormat/gdcmConstCharWrapper.h +++ b/Source/MediaStorageAndFileFormat/gdcmConstCharWrapper.h @@ -30,7 +30,7 @@ namespace gdcm * As a side note there is also a problem with const reference to enum type: * - http://sourceforge.net/mailarchive/forum.php?thread_name=bf0c3b3f0802290552y5163989t76572b80a044ce28%40mail.gmail.com&forum_name=swig-user * - * And to keep a track of isse with swig here is the last one: + * And to keep track of an issue with swig here is the last one: * * - http://sourceforge.net/mailarchive/forum.php?thread_name=bf0c3b3f0802290552y5163989t76572b80a044ce28%40mail.gmail.com&forum_name=swig-user */ diff --git a/Source/MediaStorageAndFileFormat/gdcmCurve.cxx b/Source/MediaStorageAndFileFormat/gdcmCurve.cxx index 92d86968f57..a8d9f7c1c07 100644 --- a/Source/MediaStorageAndFileFormat/gdcmCurve.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmCurve.cxx @@ -76,7 +76,7 @@ class CurveInternal os << "TypeOfData :" << TypeOfData << std::endl; os << "CurveDescription :" << CurveDescription << std::endl; os << "DataValueRepresentation :" << DataValueRepresentation << std::endl; - const unsigned short * p = (const unsigned short*)(const void*)&Data[0]; + const unsigned short * p = (const unsigned short*)(const void*)Data.data(); for(int i = 0; i < NumberOfPoints; i+=2) { os << p[i] << "," << p[i+1] << std::endl; @@ -450,7 +450,7 @@ void Curve::GetAsPoints(float *array) const assert( 0 && "TODO" ); } } - const char * beg = &Internal->Data[0]; + const char * beg = Internal->Data.data(); const char * end = beg + Internal->Data.size(); if( genidx == -1 ) { @@ -466,7 +466,7 @@ void Curve::GetAsPoints(float *array) const { // PS 3.3 - 2004 // C.10.2.1.5 Curve data descriptor, coordinate start value, coordinate step value - uint16_t * p = (uint16_t*)(void*)&Internal->Data[0]; + uint16_t * p = (uint16_t*)(void*)Internal->Data.data(); // X if( genidx == 0 ) for(int i = 0; i < Internal->NumberOfPoints; i++ ) @@ -502,7 +502,7 @@ void Curve::GetAsPoints(float *array) const } else if( Internal->DataValueRepresentation == 1 ) { - int16_t * p = (int16_t*)(void*)&Internal->Data[0]; + int16_t * p = (int16_t*)(void*)Internal->Data.data(); for(int i = 0; i < Internal->NumberOfPoints; i++ ) { array[3*i+0] = p[mult*i + 0]; @@ -515,7 +515,7 @@ void Curve::GetAsPoints(float *array) const } else if( Internal->DataValueRepresentation == 2 ) { - float * p = (float*)(void*)&Internal->Data[0]; + float * p = (float*)(void*)Internal->Data.data(); for(int i = 0; i < Internal->NumberOfPoints; i++ ) { array[3*i+0] = p[mult*i + 0]; @@ -528,7 +528,7 @@ void Curve::GetAsPoints(float *array) const } else if( Internal->DataValueRepresentation == 3 ) { - double * p = (double*)(void*)&Internal->Data[0]; + double * p = (double*)(void*)Internal->Data.data(); for(int i = 0; i < Internal->NumberOfPoints; i++ ) { array[3*i+0] = (float)p[mult*i + 0]; @@ -541,7 +541,7 @@ void Curve::GetAsPoints(float *array) const } else if( Internal->DataValueRepresentation == 4 ) { - int32_t * p = (int32_t*)(void*)&Internal->Data[0]; + int32_t * p = (int32_t*)(void*)Internal->Data.data(); for(int i = 0; i < Internal->NumberOfPoints; i++ ) { array[3*i+0] = (float)p[mult*i + 0]; diff --git a/Source/MediaStorageAndFileFormat/gdcmDICOMDIRGenerator.cxx b/Source/MediaStorageAndFileFormat/gdcmDICOMDIRGenerator.cxx index 97a37de45b4..09e6dd61d63 100644 --- a/Source/MediaStorageAndFileFormat/gdcmDICOMDIRGenerator.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmDICOMDIRGenerator.cxx @@ -288,7 +288,7 @@ size_t DICOMDIRGenerator::FindLowerLevelDirectoryRecord( size_t item1, const cha /* * Finding the next Directory Record type is easy, simply starting from the start and iterating - * to the end guarantee travering everything without omitting anyone. + * to the end guarantees traversing everything without omitting anyone. * * TODO: Need to make sure that Series belong to the same Study... */ diff --git a/Source/MediaStorageAndFileFormat/gdcmDPath.cxx b/Source/MediaStorageAndFileFormat/gdcmDPath.cxx new file mode 100644 index 00000000000..0666a741b7f --- /dev/null +++ b/Source/MediaStorageAndFileFormat/gdcmDPath.cxx @@ -0,0 +1,158 @@ +/*========================================================================= + + Program: GDCM (Grassroots DICOM). A DICOM library + + Copyright (c) 2006-2011 Mathieu Malaterre + All rights reserved. + See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "gdcmDPath.h" +#include "gdcmPrivateTag.h" +#include "gdcmTag.h" + +namespace gdcm { + +DPath::DPath() = default; + +DPath::~DPath() = default; + +// LO mandates that '\\' is never used: +static const char SEPARATOR = '\\'; +void DPath::Print(std::ostream &os) const { os << Path; } + +bool DPath::IsValid(const char *path) { + DPath tp; + return tp.ConstructFromString(path); +} + +template +static void print_contents(std::ostream &oss, const std::vector &v, + const char *const separator = ",") { + if (!v.empty()) { + std::copy(v.begin(), --v.end(), std::ostream_iterator(oss, separator)); + oss << v.back(); + } +} + +static inline std::string tostring(uint16_t const val, int const width = 4) { + std::ostringstream oss; + oss.setf(std::ios::right); + oss << std::hex << std::setw(width) << std::setfill('0') << val; + return oss.str(); +} + +static std::vector tag2strings(gdcm::Tag const &tag) { + std::vector ret; + assert(tag.IsPublic() || tag.IsPrivateCreator() || tag.IsGroupLength()); + ret.push_back(tostring(tag.GetGroup())); + ret.push_back(tostring(tag.GetElement())); + return ret; +} + +static std::vector tag2strings(gdcm::PrivateTag const &pt) { + std::vector ret; + ret.push_back(tostring(pt.GetGroup())); + ret.push_back(tostring(pt.GetElement(), 2)); + ret.push_back(pt.GetOwner()); + return ret; +} + +static inline bool is_digits(const std::string &str) { + return str.find_first_not_of("0123456789") == std::string::npos; +} + +static std::vector split_from_slash_separated( + std::string const &path, const char separator) { + std::vector comps; + std::istringstream is(path); + std::string sub; + while (std::getline(is, sub, separator)) { + const bool isEmpty = sub.empty(); + const bool isDigits = is_digits(sub); + const bool isWildCard = sub == "*"; + const bool hasComma = sub.find(',') != std::string::npos; + if (isEmpty && comps.empty()) { + comps.push_back(sub); + } else if (isDigits) { + comps.push_back(sub); + } else if (isWildCard) { + comps.push_back(sub); + } else if (hasComma) { + comps.push_back(sub); + } else { +#if 0 + assert(!comps.empty()); + std::string &last = comps.back(); + last.push_back(separator); + last.append(sub); +#else + gdcmErrorMacro("Failed to parse: " << path << " using : " << separator); + comps.clear(); + return comps; +#endif + } + } + return comps; +} + +bool DPath::ConstructFromString(const char *spath) { + Path.clear(); + if (!spath) return false; + std::vector comps; + if (*spath == '/') { + comps = split_from_slash_separated(spath, '/'); + } else if (*spath == '\\') { + comps = split_from_slash_separated(spath, '\\'); + } else { +#if 0 + // 'name' and '//name' is equivalent: + comps.push_back(""); // + comps.push_back(spath); +#endif + return false; + } + if (comps.empty()) return false; + gdcm::PrivateTag pt; + gdcm::Tag t; + std::ostringstream os; + std::vector::const_iterator it = comps.begin(); + unsigned int index = 0; + assert(comps.size() >= 2); + // check root + if (!it->empty()) return false; + ++it; + for (; it != comps.end(); ++it) { + os << SEPARATOR; + const char *str = it->c_str(); + if (pt.ReadFromCommaSeparatedString(str)) { + const std::vector tag_strings = tag2strings(pt); + print_contents(os, tag_strings, ","); + } else if (t.ReadFromCommaSeparatedString(str)) { + const std::vector tag_strings = tag2strings(t); + print_contents(os, tag_strings, ","); + } else if (is_digits(str) && sscanf(str, "%u", &index) == 1 && index > 0) { + os << index; + } else if (*str == '*') { + os << '*'; + } else { + gdcmErrorMacro("Not implemented: " << str); + return false; + } + } + Path = os.str(); + return true; +} + +bool DPath::Match(DPath const &other) const { + if (this->Path == other.Path) return true; + return false; +} + +bool DPath::operator<(const DPath &rhs) const { return this->Path < rhs.Path; } + +} // end namespace gdcm diff --git a/Source/MediaStorageAndFileFormat/gdcmDPath.h b/Source/MediaStorageAndFileFormat/gdcmDPath.h new file mode 100644 index 00000000000..5c037fe7266 --- /dev/null +++ b/Source/MediaStorageAndFileFormat/gdcmDPath.h @@ -0,0 +1,56 @@ +/*========================================================================= + + Program: GDCM (Grassroots DICOM). A DICOM library + + Copyright (c) 2006-2011 Mathieu Malaterre + All rights reserved. + See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef GDCMDPATH_H +#define GDCMDPATH_H + +#include "gdcmTag.h" +#include + +namespace gdcm { + +/** + * \brief class to handle a DICOM path + * While supp 118 did introduced a notion of XPath for XML Native model this + * convention is too XML-centric. Instead prefer DCMTK style notation + * https://groups.google.com/g/comp.protocols.dicom/c/IyIH0IOBMPA + */ +class GDCM_EXPORT DPath { + friend std::ostream &operator<<(std::ostream &_os, const DPath &_val); + + public: + DPath(); + ~DPath(); + void Print(std::ostream &) const; + bool operator<(const DPath &rhs) const; + + bool ConstructFromString(const char *path); + + /// Return whether or not 'other' match the template DPath + bool Match(DPath const &other) const; + + /// Return if path is valid or not + static bool IsValid(const char *path); + + private: + std::string Path; +}; + +inline std::ostream &operator<<(std::ostream &os, const DPath &val) { + os << val.Path; + return os; +} + +} // end namespace gdcm + +#endif // GDCMDPATH_H diff --git a/Source/MediaStorageAndFileFormat/gdcmDataSetHelper.cxx b/Source/MediaStorageAndFileFormat/gdcmDataSetHelper.cxx index d251874c65f..aebe1b8662b 100644 --- a/Source/MediaStorageAndFileFormat/gdcmDataSetHelper.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmDataSetHelper.cxx @@ -116,6 +116,21 @@ VR DataSetHelper::ComputeVR(File const &file, DataSet const &ds, const Tag& tag) // postcondition says it cannot be VR::INVALID, so return VR::UN return VR::UN; } + else + { + if( ds.FindDataElement( t ) ) + { + const DataElement &de = ds.GetDataElement( t ); + const VR &devr = de.GetVR(); + if( devr != refvr ) + { + if(!refvr.Compatible(devr)) { + gdcmWarningMacro("Inconsistent VR: " << devr << " should be " << refvr << " for: [" << (owner ? owner : "") << "]" << " de is: " << de ); + } + } + } + + } VR vr = refvr; @@ -197,10 +212,9 @@ VR DataSetHelper::ComputeVR(File const &file, DataSet const &ds, const Tag& tag) else // ( pixeldata == t ) { // For Pixel Data: - if( !ds.FindDataElement( bitsallocated ) ) - return VR::UN; + // if( !ds.FindDataElement( bitsallocated ) ) return VR::UN; Attribute<0x0028,0x0100> at; - at.SetFromDataElement( ds.GetDataElement( bitsallocated ) ); + // at.SetFromDataElement( ds.GetDataElement( bitsallocated ) ); } (void)v; diff --git a/Source/MediaStorageAndFileFormat/gdcmDataSetHelper.h b/Source/MediaStorageAndFileFormat/gdcmDataSetHelper.h index 08b02465163..161a7c37195 100644 --- a/Source/MediaStorageAndFileFormat/gdcmDataSetHelper.h +++ b/Source/MediaStorageAndFileFormat/gdcmDataSetHelper.h @@ -26,8 +26,6 @@ class SequenceOfItems; /** * \brief DataSetHelper (internal class, not intended for user level) - * - * \details */ class GDCM_EXPORT DataSetHelper { diff --git a/Source/MediaStorageAndFileFormat/gdcmDictPrinter.cxx b/Source/MediaStorageAndFileFormat/gdcmDictPrinter.cxx index 81cc77785d3..5ec8cab61c8 100644 --- a/Source/MediaStorageAndFileFormat/gdcmDictPrinter.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmDictPrinter.cxx @@ -27,9 +27,6 @@ DictPrinter::DictPrinter() } //----------------------------------------------------------------------------- -DictPrinter::~DictPrinter() -= default; - VM GuessVMType(DataElement const &de) { if( de.IsEmpty() ) return VM::VM1; @@ -440,15 +437,19 @@ void DictPrinter::PrintDataElement2(std::ostream& os, const DataSet &ds, const D std::string strowner; const char *owner = nullptr; const Tag& t = de.GetTag(); - if( t.IsPrivate() && !t.IsPrivateCreator() ) + VR dict_vr = VR::UN; + if( t.IsPrivate() && !t.IsPrivateCreator() && !t.IsGroupLength()) { strowner = ds.GetPrivateCreator(t); owner = strowner.c_str(); } - const DictEntry &entry = dicts.GetDictEntry(t,owner); - - if( de.GetTag().IsPrivate() && de.GetTag().GetElement() >= 0x0100 ) + // illegal element do not have private creator: + if(owner && *owner) { + const DictEntry &entry = dicts.GetDictEntry(t,owner); + dict_vr = entry.GetVR(); + + assert(t.GetElement() >= 0x0100 ); //owner = GetOwner(ds,de); //version = GetVersion(owner); @@ -466,24 +467,24 @@ void DictPrinter::PrintDataElement2(std::ostream& os, const DataSet &ds, const D } VM vm = GuessVMType(de); - if( PrintStyle == XML ) + if( PrintStyle == XML /*&& pvr != VR::UN*/ ) { os << "> 8) << "\" "; os << "vr=\"" << pvr << "\" vm=\"" << vm << "\" "; - if( de.GetTag().IsPrivate() ) + if( t.IsPrivate() ) { - os << R"(name="?" owner=")" << owner - << /*"\" version=\"" << version << */ "\"/>\n"; + assert( owner && *owner ); + os << R"(name="?" owner=")" << owner << "\"/>\n"; } } - else if ( PrintStyle == CXX ) + else if ( PrintStyle == CXX /*&& pvr != VR::UN*/ ) { os << "{0x" << std::hex << std::setw(4) << std::setfill('0') << t.GetGroup() << ",0x" << std::setw(4) << ((uint16_t)(t.GetElement() << 8) >> 8) << ","; - if( de.GetTag().IsPrivate() ) + if( t.IsPrivate() ) { os << "\"" << owner << "\","; @@ -492,21 +493,9 @@ void DictPrinter::PrintDataElement2(std::ostream& os, const DataSet &ds, const D std::replace( vm_str.begin(), vm_str.end(), '-', '_'); os << "VR::" << pvr << ",VM::VM" << vm_str << ",\"??\",false},\n"; } - - //os << "\n ?\n"; - //os << "\n"; - //os << "/>\n"; - //os << " Unknown "; - //os << (t.IsPrivate() ? "Private" : "Public"); - //os << " Tag & Data\n"; - //os << " \n"; - //os << " \n"; - //os << " \n"; - //os << "\n"; } - if( entry.GetVR() == VR::SQ || true ) + if( dict_vr == VR::SQ ) { SmartPointer sqi = de.GetValueAsSQ(); if( sqi ) @@ -537,7 +526,6 @@ void DictPrinter::Print(std::ostream& os) { const DataSet &ds = F->GetDataSet(); PrintDataSet2(os, ds); - //os << "\n"; } } diff --git a/Source/MediaStorageAndFileFormat/gdcmDictPrinter.h b/Source/MediaStorageAndFileFormat/gdcmDictPrinter.h index 5287f30f97b..39cad5a9af2 100644 --- a/Source/MediaStorageAndFileFormat/gdcmDictPrinter.h +++ b/Source/MediaStorageAndFileFormat/gdcmDictPrinter.h @@ -27,7 +27,7 @@ class GDCM_EXPORT DictPrinter : public Printer { public: DictPrinter(); - ~DictPrinter(); + ~DictPrinter() = default; void Print(std::ostream& os); diff --git a/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.cxx b/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.cxx index 23c5bd3595b..275d74855a6 100644 --- a/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.cxx @@ -13,9 +13,9 @@ =========================================================================*/ #include "gdcmDirectionCosines.h" +#include // fabs +#include // sscanf #include -#include // fabs -#include // sscanf namespace gdcm { @@ -40,8 +40,6 @@ DirectionCosines::DirectionCosines(const double dircos[6]) Values[5] = dircos[5]; } -DirectionCosines::~DirectionCosines() = default; - void DirectionCosines::Print(std::ostream &os) const { os << Values[0] << ","; diff --git a/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.h b/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.h index d03eafb89eb..73717fdc0ca 100644 --- a/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.h +++ b/Source/MediaStorageAndFileFormat/gdcmDirectionCosines.h @@ -29,7 +29,7 @@ class GDCM_EXPORT DirectionCosines DirectionCosines(const double dircos[6]); // Cannot get the following signature to be wrapped with swig... //DirectionCosines(const double *dircos = 0 ); - ~DirectionCosines(); + ~DirectionCosines() = default; /// Print void Print(std::ostream &) const; diff --git a/Source/MediaStorageAndFileFormat/gdcmDirectoryHelper.cxx b/Source/MediaStorageAndFileFormat/gdcmDirectoryHelper.cxx index 2cfb0c6b819..84f67ac24b9 100644 --- a/Source/MediaStorageAndFileFormat/gdcmDirectoryHelper.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmDirectoryHelper.cxx @@ -35,10 +35,10 @@ Directory::FilenamesType DirectoryHelper::GetSeriesUIDsBySOPClassUID(const std:: theScanner.GetFilenameFromTagToValue(Tag(0x0020,0x000e), theSeriesValues[i].c_str()); std::string theSOPClassUID = theScanner.GetValue(theFirstFilename.c_str(), Tag(0x0008,0x0016)); //dicom strings sometimes have trailing spaces; make sure to avoid those - size_t endpos = theSOPClassUID.find_last_not_of(" "); // Find the first character position from reverse af + size_t endpos = theSOPClassUID.find_last_not_of(' '); // Find the first character position from reverse af if( std::string::npos != endpos ) theSOPClassUID = theSOPClassUID.substr( 0, endpos+1 ); - if (theSOPClassUID == inSOPClassUID.c_str()){ + if (theSOPClassUID == inSOPClassUID){ theReturn.push_back(theSeriesValues[i]); } } @@ -88,7 +88,7 @@ Directory::FilenamesType DirectoryHelper::GetFilenamesFromSeriesUIDs(const std:: { std::string theSeriesUID = theSeriesValues[i]; //dicom strings sometimes have trailing spaces; make sure to avoid those - size_t endpos = theSeriesUID.find_last_not_of(" "); // Find the first character position from reverse af + size_t endpos = theSeriesUID.find_last_not_of(' '); // Find the first character position from reverse af if( std::string::npos != endpos ) theSeriesUID = theSeriesUID.substr( 0, endpos+1 ); if (inSeriesUID == theSeriesUID) diff --git a/Source/MediaStorageAndFileFormat/gdcmDumper.h b/Source/MediaStorageAndFileFormat/gdcmDumper.h index 079ab1c2561..6b08e48e201 100644 --- a/Source/MediaStorageAndFileFormat/gdcmDumper.h +++ b/Source/MediaStorageAndFileFormat/gdcmDumper.h @@ -22,7 +22,6 @@ namespace gdcm // It's a sink there is no output /** * \brief Codec class - * \details * \note * Use it to simply dump value read from the file. No interpretation is done. * But it is real fast ! Almost no overhead diff --git a/Source/MediaStorageAndFileFormat/gdcmEquipmentManufacturer.cxx b/Source/MediaStorageAndFileFormat/gdcmEquipmentManufacturer.cxx index e21d118ba1e..c3bd504237a 100644 --- a/Source/MediaStorageAndFileFormat/gdcmEquipmentManufacturer.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmEquipmentManufacturer.cxx @@ -16,88 +16,236 @@ #include "gdcmAttribute.h" #include "gdcmSystem.h" -namespace gdcm -{ +namespace gdcm { -struct Mapping -{ +// FIXME: fuji and hitachi are the same now +static const char* TypeStrings[] = {"UNKNOWN", "FUJI", "GEMS", "HITACHI", + "KODAK", "MARCONI", "PMS", "SIEMENS", + "TOSHIBA", "AGFA", "SAMSUNG", "UIH"}; + +const char* EquipmentManufacturer::TypeToString(Type type) { + return TypeStrings[type]; +} + +struct Mapping { EquipmentManufacturer::Type type; size_t nstrings; - const char* const *strings; + const char* const* strings; }; -static const char* const fuji[] = {"FUJI", "FUJI PHOTO FILM Co., ltd.","FUJIFILM Corporation","FUJI PHOTO FILM CO. LTD."}; -static const char* const gems[] = {"GE MEDICAL SYSTEMS", "GE_MEDICAL_SYSTEMS", "GE Healthcare", "G.E. Medical Systems","GE Vingmed Ultrasound","\"GE Healthcare\""/*sigh*/}; -static const char* const hitachi[] = {"Hitachi Medical Corporation","ALOKA CO., LTD."}; +static const char* const agfa[] = {"Agfa"}; +static const char* const fuji[] = {"FUJI", + "FUJI PHOTO FILM Co., ltd.", + "FUJIFILM Healthcare Corporation", + "FUJIFILM SonoSite", + "FUJIFILM Corporation", + "FUJI PHOTO FILM CO. LTD."}; +static const char* const gems[] = {"GE MEDICAL SYSTEMS", + "GE_MEDICAL_SYSTEMS", + "GE Healthcare", + "G.E. Medical Systems", + "GE Healthcare IT Cardiology", + "GE Healthcare Austria GmbH & Co OG", + "GE Healthcare Ultrasound", + "GE MEDICAL SYSTEMS, NUCLEAR", + "GEMS Ultrasound", + "GE OEC Medical Systems GmbH", + "GE Vingmed Ultrasound", + "\"GE Healthcare\"" /*sigh*/}; +static const char* const hitachi[] = {"Hitachi Medical Corporation", + "Hitachi, Ltd.", "ALOKA CO., LTD."}; static const char* const kodak[] = {"Kodak"}; -static const char* const pms[] = { "Philips Medical Systems", "Philips Healthcare", "Philips Medical Systems, Inc.","Philips","Picker International, Inc." }; -static const char* const siemens[] = { "SIEMENS", "Siemens HealthCare GmbH", "Siemens Health Services","Acuson" }; -static const char* const marconi[] = { "Marconi Medical Systems, Inc." }; -static const char* const toshiba[] = { "TOSHIBA_MEC", "Toshiba" }; - -#define ARRAY_SIZE( X ) \ - sizeof(X) / sizeof(*X) +static const char* const pms[] = { + "Philips Medical Systems", "Philips Healthcare", + "Philips Medical Systems, Inc.", "Philips", "Picker International, Inc."}; +static const char* const siemens[] = {"Siemens Healthineers", + "SIEMENS", + "SIEMENS NM", + "Siemens HealthCare GmbH", + "Siemens Health Services", + "Acuson"}; +static const char* const marconi[] = {"Marconi Medical Systems, Inc."}; +static const char* const samsung[] = {"SAMSUNG MEDISON CO., LTD.", + "SAMSUNG MEDISON CO.,LTD." /*sigh*/}; +static const char* const toshiba[] = {"TOSHIBA_MEC", "CANON_MEC", + "TOSHIBA_MEC_US", + "Toshiba"}; // must include canon +static const char* const uih[] = {"UIH"}; // United Imaging Healthcare + +#define ARRAY_SIZE(X) (sizeof(X) / sizeof(*X)) #define MAPPING(X, Y) \ { X, ARRAY_SIZE(Y), Y } static const Mapping mappings[] = { - MAPPING( EquipmentManufacturer::FUJI, fuji ), - MAPPING( EquipmentManufacturer::GEMS, gems ), - MAPPING( EquipmentManufacturer::HITACHI, hitachi ), - MAPPING( EquipmentManufacturer::KODAK, kodak ), - MAPPING( EquipmentManufacturer::PMS, pms ), - MAPPING( EquipmentManufacturer::SIEMENS, siemens ), - MAPPING( EquipmentManufacturer::MARCONI, marconi ), - MAPPING( EquipmentManufacturer::TOSHIBA, toshiba ) -}; + MAPPING(EquipmentManufacturer::AGFA, agfa), + MAPPING(EquipmentManufacturer::FUJI, fuji), + MAPPING(EquipmentManufacturer::GEMS, gems), + MAPPING(EquipmentManufacturer::HITACHI, hitachi), + MAPPING(EquipmentManufacturer::KODAK, kodak), + MAPPING(EquipmentManufacturer::PMS, pms), + MAPPING(EquipmentManufacturer::SIEMENS, siemens), + MAPPING(EquipmentManufacturer::MARCONI, marconi), + MAPPING(EquipmentManufacturer::SAMSUNG, samsung), + MAPPING(EquipmentManufacturer::TOSHIBA, toshiba), + MAPPING(EquipmentManufacturer::UIH, uih)}; + +// long story short, private creator could be moved around, what we are trying +// to achieve here is true modality check, so generally they should not have +// been moved in the process. +static bool IsPrivateCreatorFound(DataSet const& ds, Tag const& private_tag, + std::string const& creator_value) { + if (ds.FindDataElement(private_tag)) { + const DataElement& de = ds.GetDataElement(private_tag); + Element priv_creator; + priv_creator.SetFromDataElement(de); + if (priv_creator.GetValue().Trim() == creator_value) return true; + } + return false; +} -EquipmentManufacturer::Type EquipmentManufacturer::Compute( DataSet const & ds ) -{ - // proper anonymizer should not touch Manufacturer attribute value: - // http://dicom.nema.org/medical/dicom/current/output/chtml/part15/chapter_E.html#table_E.1-1 - gdcm::Attribute<0x0008,0x0070> manu = { "" }; // Manufacturer - manu.SetFromDataSet( ds ); - const std::string manufacturer = manu.GetValue().Trim(); - for( const Mapping * mapping = mappings; mapping != mappings + ARRAY_SIZE(mappings); ++mapping ) - { - for( size_t i = 0; i < mapping->nstrings; ++i ) - { - // case insensitive to handle: "GE MEDICAL SYSTEMS" vs "GE Medical Systems" - if( System::StrCaseCmp( mapping->strings[i], manufacturer.c_str() ) == 0 ) - return mapping->type; - } +template +static std::string GetPrivateTagValueOrEmpty(DataSet const& ds, + PrivateTag const& pt) { + if (ds.FindDataElement(pt)) { + const DataElement& de = ds.GetDataElement(pt); + Element value = {""}; + value.SetFromDataElement(de); + return value.GetValue().Trim(); } + return ""; +} +EquipmentManufacturer::Type EquipmentManufacturer::GuessFromPrivateAttributes( + DataSet const& ds) { // try against with well known private tag: - gdcm::Tag gems_iden_01(0x0009,0x0010); - if( ds.FindDataElement( gems_iden_01 ) ) - { - const gdcm::DataElement & de = ds.GetDataElement( gems_iden_01 ); - gdcm::Element priv_creator; - priv_creator.SetFromDataElement( de ); - if( priv_creator.GetValue() == "GEMS_IDEN_01" ) return GEMS; - } + // watch out for private creator such as ELSCINT1 which can be found in + // GEMS/PEMS and maybe even SIEMENS ! + // Try to prefer those listed at: + // https://dicom.nema.org/medical/dicom/current/output/chtml/part15/sect_E.3.10.html#table_E.3.10-1 + if (ds.FindDataElement(PrivateTag(0x0019, 0x0023, "GEMS_ACQU_01")) || + ds.FindDataElement(PrivateTag(0x0043, 0x0039, "GEMS_PARM_01")) || + ds.FindDataElement(PrivateTag(0x0045, 0x0001, "GEMS_HELIOS_01")) || + ds.FindDataElement(PrivateTag(0x0025, 0x001b, "GEMS_SERS_01")) + /* extra */ + || ds.FindDataElement( + PrivateTag(0x6003, 0x0010, "GEMS_Ultrasound_ImageGroup_001")) || + ds.FindDataElement(PrivateTag(0x0019, 0x0007, "DLX_SERIE_01")) || + ds.FindDataElement(PrivateTag(0x0009, 0x0001, "GEMS_GENIE_1")) || + ds.FindDataElement(PrivateTag(0x0011, 0x0003, "GEMS_GDXE_FALCON_04"))) + return GEMS; + +#if 0 + if (IsPrivateCreatorFound(ds, Tag(0x0025, 0x0010), "GEMS_IDEN_01") || + IsPrivateCreatorFound(ds, Tag(0x0009, 0x0010), "GEMS_IDEN_01") || + IsPrivateCreatorFound(ds, Tag(0x0009, 0x0010), "GEMS_GENIE_1") || + IsPrivateCreatorFound(ds, Tag(0x0009, 0x0010), "GEMS_PETD_01")) + return GEMS; +#endif + + // Philips: + if (ds.FindDataElement( + PrivateTag(0x2005, 0x000d, "Philips MR Imaging DD 001")) || + ds.FindDataElement( + PrivateTag(0x2005, 0x000e, "Philips MR Imaging DD 001")) || + ds.FindDataElement( + PrivateTag(0x2001, 0x0003, "Philips Imaging DD 001")) || + ds.FindDataElement(PrivateTag(0x2001, 0x005f, "Philips Imaging DD 001"))) + return PMS; +#if 0 + if (IsPrivateCreatorFound(ds, Tag(0x2005, 0x0014), + "Philips MR Imaging DD 005")) + return PMS; +#endif + if (IsPrivateCreatorFound(ds, Tag(0x0019, 0x0010), "PHILIPS MR/PART") && + IsPrivateCreatorFound(ds, Tag(0x0021, 0x0010), "PHILIPS MR/PART")) + return PMS; + if (IsPrivateCreatorFound(ds, Tag(0x0009, 0x0010), "SPI-P Release 1") && + IsPrivateCreatorFound(ds, Tag(0x0019, 0x0010), "SPI-P Release 1")) + return PMS; + + // Siemens: + if (ds.FindDataElement(PrivateTag(0x0029, 0x0010, "SIEMENS CSA HEADER")) || + ds.FindDataElement(PrivateTag(0x0029, 0x0020, "SIEMENS CSA HEADER")) || + ds.FindDataElement(PrivateTag(0x0029, 0x0010, "SIEMENS MEDCOM OOG")) || + ds.FindDataElement( + PrivateTag(0x7fdf, 0x0000, "ACUSON:1.2.840.113680.1.0:7ffe")) || + ds.FindDataElement(PrivateTag(0x0019, 0x0012, "SIEMENS CM VA0 ACQU")) || + ds.FindDataElement(PrivateTag(0x0009, 0x0010, "SIEMENS CT VA0 IDE"))) + return SIEMENS; +#if 0 + if (GetPrivateTagValueOrEmpty( + ds, PrivateTag(0x0021, 0x0022, "SIEMENS MR SDS 01")) == "SIEMENS") + return SIEMENS; + // gdcm-MR-SIEMENS-16-2.acr + if (GetPrivateTagValueOrEmpty( + ds, PrivateTag(0x0019, 0x0012, "SIEMENS CM VA0 ACQU")) == "SIEMENS") + return SIEMENS; +#endif + + // toshiba: + if (ds.FindDataElement(PrivateTag(0x7005, 0x0008, "TOSHIBA_MEC_CT3")) || + ds.FindDataElement(PrivateTag(0x700d, 0x0008, "TOSHIBA_MEC_MR3")) || + ds.FindDataElement(PrivateTag(0x0029, 0x0001, "PMTF INFORMATION DATA")) || + ds.FindDataElement(PrivateTag(0x0029, 0x0001, "CANON_MEC_MR3")) || + ds.FindDataElement(PrivateTag(0x0029, 0x0001, "TOSHIBA_MEC_MR3"))) + return TOSHIBA; + // fuji + if (ds.FindDataElement(PrivateTag(0x0021, 0x0010, "FDMS 1.0"))) return FUJI; + // hitachi + if (ds.FindDataElement(PrivateTag(0x0009, 0x0000, "HMC - CT - ID")) || + ds.FindDataElement(PrivateTag(0x0009, 0x0003, "MMCPrivate")) || + ds.FindDataElement(PrivateTag(0x0009, 0x0050, "MMCPrivate")) || + ds.FindDataElement(PrivateTag(0x0019, 0x000e, "MMCPrivate")) || + ds.FindDataElement(PrivateTag(0x0019, 0x0021, "MMCPrivate")) || + ds.FindDataElement(PrivateTag(0x0029, 0x002f, "MMCPrivate")) || + ds.FindDataElement(PrivateTag(0x0029, 0x00d7, "MMCPrivate"))) + return HITACHI; + // UIH + if (ds.FindDataElement(PrivateTag(0x0065, 0x000a, "Image Private Header"))) + return UIH; - gdcm::PrivateTag siemens_manu(0x0021,0x0022,"SIEMENS MR SDS 01"); - if( ds.FindDataElement( siemens_manu ) ) - { - const gdcm::DataElement & de = ds.GetDataElement( siemens_manu ); - gdcm::Element value; - value.SetFromDataElement( de ); - if( value.GetValue().Trim() == "SIEMENS" ) return SIEMENS; - } + return UNKNOWN; +} + +EquipmentManufacturer::Type EquipmentManufacturer::Compute(DataSet const& ds) { + EquipmentManufacturer::Type ret = GuessFromPrivateAttributes(ds); - gdcm::Tag elscint1(0x00e1,0x0010); - if( ds.FindDataElement( elscint1 ) ) - { - const gdcm::DataElement & de = ds.GetDataElement( elscint1 ); - gdcm::Element priv_creator; - priv_creator.SetFromDataElement( de ); - if( priv_creator.GetValue() == "ELSCINT1" ) return GEMS; + // proper anonymizer should not touch Manufacturer attribute value: + // http://dicom.nema.org/medical/dicom/current/output/chtml/part15/chapter_E.html#table_E.1-1 + Attribute<0x0008, 0x0070> manu = {""}; // Manufacturer + std::string manufacturer; + if (ds.FindDataElement(manu.GetTag())) { + manu.SetFromDataSet(ds); + manufacturer = manu.GetValue().Trim(); + // TODO: contributing equipement ? + } else { + // MFSPLIT export seems to remove the attribute completely: + manufacturer = GetPrivateTagValueOrEmpty( + ds, PrivateTag(0x0021, 0x0022, "SIEMENS MR SDS 01")); + } + if (!manufacturer.empty()) { + for (const Mapping* mapping = mappings; + mapping != mappings + ARRAY_SIZE(mappings); ++mapping) { + for (size_t i = 0; i < mapping->nstrings; ++i) { + // case insensitive to handle: "GE MEDICAL SYSTEMS" vs "GE Medical + // Systems" + if (System::StrCaseCmp(mapping->strings[i], manufacturer.c_str()) == + 0) { + if (ret != UNKNOWN && ret != mapping->type) { + gdcmErrorMacro(" Impossible happen: " << ret << " vs " + << mapping->type); + return UNKNOWN; + } + return mapping->type; + } + } + } } - return UNKNOWN; + gdcmWarningMacro("Unknown Manufacturer [" << manufacturer + << "] trying guess."); + return ret; } -} // end namespace gdcm +} // end namespace gdcm diff --git a/Source/MediaStorageAndFileFormat/gdcmEquipmentManufacturer.h b/Source/MediaStorageAndFileFormat/gdcmEquipmentManufacturer.h index 123deda782e..2b6c78641d8 100644 --- a/Source/MediaStorageAndFileFormat/gdcmEquipmentManufacturer.h +++ b/Source/MediaStorageAndFileFormat/gdcmEquipmentManufacturer.h @@ -16,19 +16,17 @@ #include "gdcmTypes.h" -namespace gdcm -{ +namespace gdcm { class DataSet; /** - * \brief - * \details - * + * \details + * The intent is for private tags handling. This class is not meant to handle + * all possible vendors in the world, simply those well known where we intend + * to read private tags afterwards (typically SIEMENS+CSA, GEMS+PDB ...) */ -class GDCM_EXPORT EquipmentManufacturer -{ -public: - +class GDCM_EXPORT EquipmentManufacturer { + public: typedef enum { UNKNOWN = 0, FUJI, @@ -38,14 +36,21 @@ class GDCM_EXPORT EquipmentManufacturer MARCONI, PMS, SIEMENS, - TOSHIBA + TOSHIBA, + AGFA, + SAMSUNG, + UIH } Type; - static Type Compute( DataSet const & ds ); + static Type Compute(DataSet const &ds); + + static const char *TypeToString(Type type); -private: + private: + static EquipmentManufacturer::Type GuessFromPrivateAttributes( + DataSet const &ds); }; -} // end namespace gdcm +} // end namespace gdcm -#endif // GDCMEQUIPMENTMANUFACTURER_H +#endif // GDCMEQUIPMENTMANUFACTURER_H diff --git a/Source/MediaStorageAndFileFormat/gdcmFileAnonymizer.cxx b/Source/MediaStorageAndFileFormat/gdcmFileAnonymizer.cxx index 5b2e3af7144..3038cb19901 100644 --- a/Source/MediaStorageAndFileFormat/gdcmFileAnonymizer.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmFileAnonymizer.cxx @@ -27,7 +27,7 @@ // See : POD value-init, see GCC #36750 /* Test for GCC < 5.1.1 */ /* GCC 4.2 reports: error: #pragma GCC diagnostic not allowed inside functions */ -#if GCC_VERSION < 50101 +#if defined(GCC_VERSION) && GCC_VERSION < 50101 #pragma GCC diagnostic ignored "-Wmissing-field-initializers" #endif diff --git a/Source/MediaStorageAndFileFormat/gdcmFileChangeTransferSyntax.cxx b/Source/MediaStorageAndFileFormat/gdcmFileChangeTransferSyntax.cxx index e6a7d69a541..cfd62a65d4f 100644 --- a/Source/MediaStorageAndFileFormat/gdcmFileChangeTransferSyntax.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmFileChangeTransferSyntax.cxx @@ -131,7 +131,7 @@ bool FileChangeTransferSyntax::Change() std::vector vbuffer; vbuffer.resize( dims[0] * pixsize ); - char *data = &vbuffer[0]; + char *data = vbuffer.data(); const size_t datalen = vbuffer.size(); const size_t nscanlines = dims[2] * dims[1]; @@ -176,7 +176,7 @@ bool FileChangeTransferSyntax::Change() std::vector vbuffer; vbuffer.resize( dims[0] * dims[1] * pixsize ); - char *data = &vbuffer[0]; + char *data = vbuffer.data(); const size_t datalen = vbuffer.size(); const size_t nscanlines = dims[2]; @@ -287,7 +287,7 @@ void FileChangeTransferSyntax::SetTransferSyntax( TransferSyntax const & ts ) &jpeg2000, &rle }; - const int n = sizeof( codecs ) / sizeof( *codecs ); + const int n = sizeof( codecs ) / sizeof( codecs[0] ); for( int i = 0; i < n; ++i ) { if( codecs[i]->CanCode( ts ) ) diff --git a/Source/MediaStorageAndFileFormat/gdcmFileExplicitFilter.cxx b/Source/MediaStorageAndFileFormat/gdcmFileExplicitFilter.cxx index ffa7cb6d2d9..726f43a6e7b 100644 --- a/Source/MediaStorageAndFileFormat/gdcmFileExplicitFilter.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmFileExplicitFilter.cxx @@ -95,7 +95,7 @@ bool FileExplicitFilter::ProcessDataSet(DataSet &ds, Dicts const & dicts) //assert( de.GetVR() == VR::INVALID ); VR cvr = DataSetHelper::ComputeVR(*F,ds, t); VR oldvr = de.GetVR(); - if( cvr == VR::SQ ) { assert( oldvr == VR::SQ || oldvr == VR::UN || oldvr == VR::INVALID ); } + if( cvr == VR::SQ ) { assert( oldvr == VR::SQ || oldvr == VR::UN || oldvr == VR::INVALID || oldvr == VR::OB ); } //SequenceOfItems *sqi = de.GetSequenceOfItems(); //SequenceOfItems *sqi = dynamic_cast(&de.GetValue()); SmartPointer sqi = nullptr; @@ -126,7 +126,7 @@ bool FileExplicitFilter::ProcessDataSet(DataSet &ds, Dicts const & dicts) //assert( oldvr & VR::VRASCII || oldvr == VR::INVALID || oldvr == VR::UN ); // gdcm-JPEG-Extended.dcm has a couple of VR::OB private field // is this a good idea to change them to an ASCII when we know this might not work ? - if( !(oldvr & VR::VRASCII || oldvr == VR::INVALID || oldvr == VR::UN) ) + if( !(oldvr & VR::VRASCII || oldvr == VR::INVALID || oldvr == VR::UN || oldvr == VR::OB) ) { gdcmErrorMacro( "Cannot convert VR for tag: " << t << " " << oldvr << " is incompatible with " << cvr << " as given by ref. dict." ); return false; @@ -181,7 +181,7 @@ bool FileExplicitFilter::ProcessDataSet(DataSet &ds, Dicts const & dicts) } else if( de.GetSequenceOfFragments() ) { - assert( cvr & VR::OB_OW ); + assert( cvr & VR::OB ); } else { diff --git a/Source/MediaStorageAndFileFormat/gdcmFileStreamer.cxx b/Source/MediaStorageAndFileFormat/gdcmFileStreamer.cxx index c44e1f702aa..7723b0a83f9 100644 --- a/Source/MediaStorageAndFileFormat/gdcmFileStreamer.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmFileStreamer.cxx @@ -22,11 +22,14 @@ #include "gdcmEvent.h" #include "gdcmProgressEvent.h" +// The GNU C library (glibc) requires this be defined to have fseeko() and ftello(). +#ifdef __GNU_LIBRARY__ #define _FILE_OFFSET_BITS 64 +#endif +#include #include #include // fstat -#include #if defined(_WIN32) && (defined(_MSC_VER) || defined(__MINGW32__)) #include @@ -51,7 +54,7 @@ namespace gdcm // much guarantee to be 32bits only. static inline int FSeeko(FILE *stream, off64_t offset, int whence) { -#if _WIN32 +#ifdef _WIN32 #if defined(__MINGW32__) return fseek(stream, offset, whence); // 32bits #else @@ -64,7 +67,7 @@ static inline int FSeeko(FILE *stream, off64_t offset, int whence) static inline off64_t FTello(FILE *stream) { -#if _WIN32 +#ifdef _WIN32 #if defined(__MINGW32__) return ftell( stream ); // 32bits #else @@ -77,7 +80,7 @@ static inline off64_t FTello(FILE *stream) static inline bool FTruncate( const int fd, const off64_t len ) { -#if _WIN32 +#ifdef _WIN32 #if defined(__MINGW32__) const long size = len; const int ret = _chsize( fd, size ); // 32bits @@ -788,7 +791,7 @@ bool FileStreamer::InitializeCopy() Reader reader; reader.SetFileName( filename ); if( !reader.Read() ) return false; - if( strcmp( filename, outfilename ) ) + if( strcmp( filename, outfilename ) != 0 ) { Writer writer; writer.SetFileName( outfilename ); @@ -802,7 +805,7 @@ bool FileStreamer::InitializeCopy() assert( outfilename ); std::ifstream is( filename, std::ios::binary ); if( !is.good() ) return false; - if( strcmp( filename, outfilename ) ) + if( strcmp( filename, outfilename ) != 0 ) { std::ofstream of( outfilename, std::ios::binary ); if( !of.good() ) return false; diff --git a/Source/MediaStorageAndFileFormat/gdcmIPPSorter.cxx b/Source/MediaStorageAndFileFormat/gdcmIPPSorter.cxx index 9ccaa61337d..d811c5975ae 100644 --- a/Source/MediaStorageAndFileFormat/gdcmIPPSorter.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmIPPSorter.cxx @@ -16,8 +16,8 @@ #include "gdcmElement.h" #include "gdcmDirectionCosines.h" +#include #include -#include namespace gdcm { diff --git a/Source/MediaStorageAndFileFormat/gdcmIconImageGenerator.cxx b/Source/MediaStorageAndFileFormat/gdcmIconImageGenerator.cxx index 1d0e331b763..496979d04c4 100644 --- a/Source/MediaStorageAndFileFormat/gdcmIconImageGenerator.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmIconImageGenerator.cxx @@ -345,10 +345,10 @@ void IconImageGenerator::BuildLUT( Bitmap & bitmap, unsigned int maxcolor ) for( int i = 0; i < 3; ++i ) { lut.InitializeLUT( LookupTable::LookupTableType(i), (unsigned short)ncolors, 0, 8 ); - lut.SetLUT( LookupTable::LookupTableType(i), &buffer[i][0], (unsigned short)ncolors ); + lut.SetLUT( LookupTable::LookupTableType(i), buffer[i].data(), (unsigned short)ncolors ); } - bitmap.GetDataElement().SetByteValue( (char*)&indeximage[0], (uint32_t)indeximage.size() ); + bitmap.GetDataElement().SetByteValue( (char*)indeximage.data(), (uint32_t)indeximage.size() ); assert( lut.Initialized() ); } @@ -544,7 +544,7 @@ f. If a Palette Color lookup Table is used, an 8 Bit Allocated (0028,0100) shall framelen /= dims[2]; } vbuffer.resize( P->GetBufferLength() ); - char *buffer = &vbuffer[0]; + char *buffer = vbuffer.data(); bool boolean = P->GetBuffer(buffer); if( !boolean ) return false; @@ -560,8 +560,8 @@ f. If a Palette Color lookup Table is used, an 8 Bit Allocated (0028,0100) shall uint8_t ps = I->GetPixelFormat().GetPixelSize(); - char *iconb = &vbuffer2[0]; - char *imgb = &vbuffer[0]; + char *iconb = vbuffer2.data(); + char *imgb = vbuffer.data(); const unsigned int *imgdims = P->GetDimensions(); const unsigned int stepi = imgdims[0] / Internals->dims[0]; @@ -581,7 +581,7 @@ f. If a Palette Color lookup Table is used, an 8 Bit Allocated (0028,0100) shall // Apply LUT if( P->GetPhotometricInterpretation() == PhotometricInterpretation::PALETTE_COLOR ) { - std::string tempvbuf(&vbuffer2[0], vbuffer2.size()); + std::string tempvbuf(vbuffer2.data(), vbuffer2.size()); std::istringstream is( tempvbuf ); std::stringstream ss; P->GetLUT().Decode( is, ss ); @@ -613,7 +613,7 @@ f. If a Palette Color lookup Table is used, an 8 Bit Allocated (0028,0100) shall std::vector v8; v8.resize( Internals->dims[0] * Internals->dims[1] * 3 ); - if( !r.Rescale(&v8[0],&s[0],s.size()) ) + if( !r.Rescale(v8.data(),s.data(),s.size()) ) { assert( 0 ); // should not happen in real life gdcmErrorMacro( "Problem in the rescaler" ); @@ -626,12 +626,12 @@ f. If a Palette Color lookup Table is used, an 8 Bit Allocated (0028,0100) shall // re-encode: std::stringstream ss2; - ss2.str( std::string( &v8[0], v8.size() ) ); + ss2.str( std::string( v8.data(), v8.size() ) ); std::string s2 = ss2.str(); // As per standard, we only support 8bits icon I->SetPixelFormat( PixelFormat::UINT8 ); - pixeldata.SetByteValue( &s2[0], (uint32_t)s2.size() ); + pixeldata.SetByteValue( s2.data(), (uint32_t)s2.size() ); BuildLUT( *I, 256 ); } @@ -639,7 +639,7 @@ f. If a Palette Color lookup Table is used, an 8 Bit Allocated (0028,0100) shall { I->SetPixelFormat( PixelFormat::UINT8 ); I->GetPixelFormat().SetSamplesPerPixel( 3 ); - pixeldata.SetByteValue( &v8[0], (uint32_t)v8.size() ); + pixeldata.SetByteValue( v8.data(), (uint32_t)v8.size() ); } } else @@ -653,7 +653,7 @@ f. If a Palette Color lookup Table is used, an 8 Bit Allocated (0028,0100) shall // As per standard, we only support 8bits icon I->SetPixelFormat( PixelFormat::UINT8 ); - pixeldata.SetByteValue( &s[0], (uint32_t)s.size() ); + pixeldata.SetByteValue( s.data(), (uint32_t)s.size() ); BuildLUT(*I, 256 ); } @@ -661,7 +661,7 @@ f. If a Palette Color lookup Table is used, an 8 Bit Allocated (0028,0100) shall { I->SetPixelFormat( PixelFormat::UINT8 ); I->GetPixelFormat().SetSamplesPerPixel( 3 ); - pixeldata.SetByteValue( &s[0], (uint32_t)s.size() ); + pixeldata.SetByteValue( s.data(), (uint32_t)s.size() ); } } } @@ -671,14 +671,14 @@ f. If a Palette Color lookup Table is used, an 8 Bit Allocated (0028,0100) shall || P->GetPhotometricInterpretation() == PhotometricInterpretation::YBR_ICT || P->GetPhotometricInterpretation() == PhotometricInterpretation::YBR_RCT ) { - std::string tempvbuf( &vbuffer2[0], vbuffer2.size() ); + std::string tempvbuf( vbuffer2.data(), vbuffer2.size() ); if( P->GetPhotometricInterpretation() == PhotometricInterpretation::YBR_FULL || P->GetPhotometricInterpretation() == PhotometricInterpretation::YBR_FULL_422 ) { assert( I->GetPixelFormat() == PixelFormat::UINT8 ); if( P->GetPlanarConfiguration() == 0 ) { - unsigned char *ybr = (unsigned char*)&tempvbuf[0]; + unsigned char *ybr = (unsigned char*)tempvbuf.data(); unsigned char *ybr_out = ybr; unsigned char *ybr_end = ybr + vbuffer2.size(); int R, G, B; @@ -718,7 +718,7 @@ f. If a Palette Color lookup Table is used, an 8 Bit Allocated (0028,0100) shall { std::string tempvbufybr = tempvbuf; - unsigned char *ybr = (unsigned char*)&tempvbufybr[0]; + unsigned char *ybr = (unsigned char*)tempvbufybr.data(); unsigned char *ybr_end = ybr + vbuffer2.size(); assert( vbuffer2.size() % 3 == 0 ); size_t ybrl = vbuffer2.size() / 3; @@ -726,7 +726,7 @@ f. If a Palette Color lookup Table is used, an 8 Bit Allocated (0028,0100) shall unsigned char *ybrb = ybr + 1 * ybrl; unsigned char *ybrc = ybr + 2 * ybrl; - unsigned char *ybr_out = (unsigned char*)&tempvbuf[0]; + unsigned char *ybr_out = (unsigned char*)tempvbuf.data(); unsigned char *ybr_out_end = ybr_out + vbuffer2.size(); int R, G, B; for( ; ybr_out != ybr_out_end; ) @@ -766,7 +766,7 @@ f. If a Palette Color lookup Table is used, an 8 Bit Allocated (0028,0100) shall assert( I->GetPixelFormat() == PixelFormat::UINT8 ); std::string tempvbufrgb = tempvbuf; - unsigned char *rgb = (unsigned char*)&tempvbufrgb[0]; + unsigned char *rgb = (unsigned char*)tempvbufrgb.data(); unsigned char *rgb_end = rgb + vbuffer2.size(); assert( vbuffer2.size() % 3 == 0 ); size_t rgbl = vbuffer2.size() / 3; @@ -774,7 +774,7 @@ f. If a Palette Color lookup Table is used, an 8 Bit Allocated (0028,0100) shall unsigned char *rgbb = rgb + 1 * rgbl; unsigned char *rgbc = rgb + 2 * rgbl; - unsigned char *rgb_out = (unsigned char*)&tempvbuf[0]; + unsigned char *rgb_out = (unsigned char*)tempvbuf.data(); unsigned char *rgb_out_end = rgb_out + vbuffer2.size(); for( ; rgb_out != rgb_out_end; ) { @@ -800,7 +800,7 @@ f. If a Palette Color lookup Table is used, an 8 Bit Allocated (0028,0100) shall { // As per standard, we only support 8bits icon I->SetPixelFormat( PixelFormat::UINT8 ); - pixeldata.SetByteValue( &s[0], (uint32_t)s.size() ); + pixeldata.SetByteValue( s.data(), (uint32_t)s.size() ); BuildLUT(*I, 256 ); } @@ -808,7 +808,7 @@ f. If a Palette Color lookup Table is used, an 8 Bit Allocated (0028,0100) shall { I->SetPixelFormat( PixelFormat::UINT8 ); I->GetPixelFormat().SetSamplesPerPixel( 3 ); - pixeldata.SetByteValue( &s[0], (uint32_t)s.size() ); + pixeldata.SetByteValue( s.data(), (uint32_t)s.size() ); } } else @@ -839,7 +839,7 @@ f. If a Palette Color lookup Table is used, an 8 Bit Allocated (0028,0100) shall std::vector v8; v8.resize( Internals->dims[0] * Internals->dims[1] * 3 ); - if( !r.Rescale(&v8[0],&s[0],s.size()) ) + if( !r.Rescale(v8.data(),s.data(),s.size()) ) { assert( 0 ); // should not happen in real life gdcmErrorMacro( "Problem in the rescaler" ); @@ -852,7 +852,7 @@ f. If a Palette Color lookup Table is used, an 8 Bit Allocated (0028,0100) shall lut.Allocate(); I->SetPixelFormat( PixelFormat::UINT8 ); - pixeldata.SetByteValue( &v8[0], (uint32_t)v8.size() ); + pixeldata.SetByteValue( v8.data(), (uint32_t)v8.size() ); BuildLUT(*I, 256 ); } @@ -860,14 +860,14 @@ f. If a Palette Color lookup Table is used, an 8 Bit Allocated (0028,0100) shall { I->SetPixelFormat( PixelFormat::UINT8 ); I->GetPixelFormat().SetSamplesPerPixel( 3 ); - pixeldata.SetByteValue( &v8[0], (uint32_t)v8.size() ); + pixeldata.SetByteValue( v8.data(), (uint32_t)v8.size() ); } } } else { // MONOCHROME1 / MONOCHROME2 ... - char *buffer2 = &vbuffer2[0]; + char *buffer2 = vbuffer2.data(); pixeldata.SetByteValue( buffer2, (uint32_t)vbuffer2.size() ); Rescaler r; @@ -886,7 +886,7 @@ f. If a Palette Color lookup Table is used, an 8 Bit Allocated (0028,0100) shall } if( Internals->AutoMinMax ) { - void *p = &vbuffer2[0]; + void *p = vbuffer2.data(); size_t len = vbuffer2.size(); const PixelFormat &pf = I->GetPixelFormat(); assert( pf.GetSamplesPerPixel() == 1 ); @@ -963,7 +963,7 @@ f. If a Palette Color lookup Table is used, an 8 Bit Allocated (0028,0100) shall std::vector v8; v8.resize( Internals->dims[0] * Internals->dims[1] ); - if( !r.Rescale(&v8[0],&vbuffer2[0],vbuffer2.size()) ) + if( !r.Rescale(v8.data(),vbuffer2.data(),vbuffer2.size()) ) { assert( 0 ); // should not happen in real life gdcmErrorMacro( "Problem in the rescaler" ); @@ -972,7 +972,7 @@ f. If a Palette Color lookup Table is used, an 8 Bit Allocated (0028,0100) shall // As per standard, we only support 8bits icon I->SetPixelFormat( PixelFormat::UINT8 ); - pixeldata.SetByteValue( &v8[0], (uint32_t)v8.size() ); + pixeldata.SetByteValue( v8.data(), (uint32_t)v8.size() ); } // \postcondition diff --git a/Source/MediaStorageAndFileFormat/gdcmImage.cxx b/Source/MediaStorageAndFileFormat/gdcmImage.cxx index 78a1f7a5c13..e1e03efb617 100644 --- a/Source/MediaStorageAndFileFormat/gdcmImage.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmImage.cxx @@ -28,7 +28,7 @@ namespace gdcm const double *Image::GetSpacing() const { assert( NumberOfDimensions ); - return &Spacing[0]; + return Spacing.data(); } double Image::GetSpacing(unsigned int idx) const @@ -59,7 +59,7 @@ const double *Image::GetOrigin() const { assert( NumberOfDimensions ); if( !Origin.empty() ) - return &Origin[0]; + return Origin.data(); return nullptr; } @@ -99,7 +99,7 @@ const double *Image::GetDirectionCosines() const { assert( NumberOfDimensions ); if( !DirectionCosines.empty() ) - return &DirectionCosines[0]; + return DirectionCosines.data(); return nullptr; } double Image::GetDirectionCosines(unsigned int idx) const diff --git a/Source/MediaStorageAndFileFormat/gdcmImageApplyLookupTable.cxx b/Source/MediaStorageAndFileFormat/gdcmImageApplyLookupTable.cxx index 140dd2415f2..22030526bd6 100644 --- a/Source/MediaStorageAndFileFormat/gdcmImageApplyLookupTable.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmImageApplyLookupTable.cxx @@ -57,7 +57,7 @@ bool ImageApplyLookupTable::Apply() const unsigned long len = image.GetBufferLength(); std::vector v; v.resize( len ); - char *p = &v[0]; + char *p = v.data(); image.GetBuffer( p ); std::stringstream is; if( !is.write( p, len ) ) @@ -77,14 +77,14 @@ bool ImageApplyLookupTable::Apply() std::vector v2; v2.resize( len * 3 ); if( pimpl->rgb8 ) - lut.Decode8(&v2[0], v2.size(), &v[0], v.size()); + lut.Decode8(v2.data(), v2.size(), v.data(), v.size()); else - lut.Decode(&v2[0], v2.size(), &v[0], v.size()); + lut.Decode(v2.data(), v2.size(), v.data(), v.size()); assert( v2.size() < (size_t)std::numeric_limits::max() ); if( pimpl->rgb8 ) - de.SetByteValue( &v2[0], (uint32_t)v2.size() / 2); + de.SetByteValue( v2.data(), (uint32_t)v2.size() / 2); else - de.SetByteValue( &v2[0], (uint32_t)v2.size() ); + de.SetByteValue( v2.data(), (uint32_t)v2.size() ); #endif Output->GetLUT().Clear(); Output->SetPhotometricInterpretation( PhotometricInterpretation::RGB ); diff --git a/Source/MediaStorageAndFileFormat/gdcmImageChangePhotometricInterpretation.cxx b/Source/MediaStorageAndFileFormat/gdcmImageChangePhotometricInterpretation.cxx index 945fdad3a1f..53b0dc44102 100644 --- a/Source/MediaStorageAndFileFormat/gdcmImageChangePhotometricInterpretation.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmImageChangePhotometricInterpretation.cxx @@ -107,9 +107,10 @@ bool ImageChangePhotometricInterpretation::ChangeYBR2RGB() return true; } + // Note: allocate with malloc because it guarantees to align suitable for any type, unlike new. unsigned long len = image.GetBufferLength(); - char *p8 = new char[len]; - image.GetBuffer( p8 ); + void *p8 = malloc (len); + image.GetBuffer( (char *)p8 ); const PixelFormat &pf = image.GetPixelFormat(); if( image.GetPlanarConfiguration() != 0 ) return false; @@ -146,7 +147,7 @@ bool ImageChangePhotometricInterpretation::ChangeYBR2RGB() } DataElement &de = Output->GetDataElement(); - de.SetByteValue( p8, len); + de.SetByteValue( (char *)p8, len); //Output->GetLUT().Clear(); Output->SetPhotometricInterpretation( PI ); //Output->GetPixelFormat().SetSamplesPerPixel( 3 ); @@ -165,7 +166,7 @@ bool ImageChangePhotometricInterpretation::ChangeYBR2RGB() bool success = true; - delete[] p8; + free(p8); return success; } @@ -183,9 +184,10 @@ bool ImageChangePhotometricInterpretation::ChangeRGB2YBR() return true; } + // Note: allocate with malloc because it guarantees to align suitable for any type, unlike new. unsigned long len = image.GetBufferLength(); - char *p8 = new char[len]; - image.GetBuffer( p8 ); + void *p8 = malloc(len); + image.GetBuffer( (char *)p8 ); const PixelFormat &pf = image.GetPixelFormat(); if( image.GetPlanarConfiguration() != 0 ) return false; @@ -222,7 +224,7 @@ bool ImageChangePhotometricInterpretation::ChangeRGB2YBR() } DataElement &de = Output->GetDataElement(); - de.SetByteValue( p8, len); + de.SetByteValue( (char *)p8, len); //Output->GetLUT().Clear(); Output->SetPhotometricInterpretation( PI ); //Output->GetPixelFormat().SetSamplesPerPixel( 3 ); @@ -241,7 +243,7 @@ bool ImageChangePhotometricInterpretation::ChangeRGB2YBR() bool success = true; - delete[] p8; + free(p8); return success; } diff --git a/Source/MediaStorageAndFileFormat/gdcmImageChangeTransferSyntax.cxx b/Source/MediaStorageAndFileFormat/gdcmImageChangeTransferSyntax.cxx index e4c222408ba..fcb61e611d2 100644 --- a/Source/MediaStorageAndFileFormat/gdcmImageChangeTransferSyntax.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmImageChangeTransferSyntax.cxx @@ -278,10 +278,11 @@ bool ImageChangeTransferSyntax::TryJPEGLSCodec(const DataElement &pixelde, Bitma UpdatePhotometricInterpretation( input, output ); if( input.GetPixelFormat().GetSamplesPerPixel() == 3 ) { - if( input.GetPlanarConfiguration() == 0 ) + if( input.GetPlanarConfiguration() == 1 ) { - // http://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_8.2.3.html#table_8.2.3-1 - output.SetPlanarConfiguration(1); + // CP-1843 + // https://dicom.nema.org/medical/dicom/current/output/chtml/part05/sect_8.2.3.html#para_d1e96f41-db25-4a4b-9009-9fd3796e5b43 + output.SetPlanarConfiguration(0); } } diff --git a/Source/MediaStorageAndFileFormat/gdcmImageCodec.cxx b/Source/MediaStorageAndFileFormat/gdcmImageCodec.cxx index 3db77eabcb5..deba8ab004c 100644 --- a/Source/MediaStorageAndFileFormat/gdcmImageCodec.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmImageCodec.cxx @@ -21,8 +21,8 @@ #include #include +#include #include -#include namespace gdcm { @@ -157,14 +157,13 @@ assert(0); // Do not use this code ! const unsigned char *a = copy + 0; const unsigned char *b = copy + size; const unsigned char *c = copy + size + size; - int R, G, B; unsigned char *p = (unsigned char*)dummy_buffer; for (unsigned long j = 0; j < size; ++j) { - R = 38142 *(*a-16) + 52298 *(*c -128); - G = 38142 *(*a-16) - 26640 *(*c -128) - 12845 *(*b -128); - B = 38142 *(*a-16) + 66093 *(*b -128); + int R = 38142 *(*a-16) + 52298 *(*c -128); + int G = 38142 *(*a-16) - 26640 *(*c -128) - 12845 *(*b -128); + int B = 38142 *(*a-16) + 66093 *(*b -128); R = (R+16384)>>15; G = (G+16384)>>15; @@ -461,8 +460,7 @@ bool ImageCodec::CleanupUnusedBits(char * data8, size_t datalen) smask = (uint16_t)( smask << ( 16 - (PF.GetBitsAllocated() - PF.GetBitsStored() + 1) )); // nmask : to propagate sign bit on negative values - int16_t nmask = (int16_t)0x8000; - nmask = (int16_t)(nmask >> ( PF.GetBitsAllocated() - PF.GetBitsStored() - 1 )); + int16_t nmask = (int16_t)(0x8000U >> ( PF.GetBitsAllocated() - PF.GetBitsStored() - 1 )); uint16_t *start = (uint16_t*)data; for( uint16_t *p = start ; p != start + datalen / 2; ++p ) @@ -517,8 +515,7 @@ bool ImageCodec::DoOverlayCleanup(std::istream &is, std::ostream &os) smask = (uint16_t)( smask << ( 16 - (PF.GetBitsAllocated() - PF.GetBitsStored() + 1) )); // nmask : to propagate sign bit on negative values - int16_t nmask = (int16_t)0x8000; - nmask = (int16_t)(nmask >> ( PF.GetBitsAllocated() - PF.GetBitsStored() - 1 )); + int16_t nmask = (int16_t)(0x8000U >> ( PF.GetBitsAllocated() - PF.GetBitsStored() - 1 )); uint16_t c; while( is.read((char*)&c,2) ) @@ -545,14 +542,14 @@ bool ImageCodec::DoOverlayCleanup(std::istream &is, std::ostream &os) std::vector buffer(bufferSize); while (is) { - is.read((char *)&buffer[0], bufferSize * sizeof(uint16_t)); + is.read((char *)buffer.data(), bufferSize * sizeof(uint16_t)); std::streamsize bytesRead = is.gcount(); std::vector::iterator validBufferEnd = buffer.begin() + bytesRead / sizeof(uint16_t); for (std::vector::iterator it = buffer.begin(); it != validBufferEnd; ++it) { *it = ((*it >> (PF.GetBitsStored() - PF.GetHighBit() - 1)) & pmask); } - os.write((char *)&buffer[0], bytesRead); + os.write((char *)buffer.data(), bytesRead); } #else //std::ostreambuf_iterator end_of_stream_iterator; diff --git a/Source/MediaStorageAndFileFormat/gdcmImageHelper.cxx b/Source/MediaStorageAndFileFormat/gdcmImageHelper.cxx index a0294d493ee..d8973f41304 100644 --- a/Source/MediaStorageAndFileFormat/gdcmImageHelper.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmImageHelper.cxx @@ -27,7 +27,7 @@ #include "gdcmSegmentedPaletteColorLookupTable.h" #include "gdcmByteValue.h" -#include // fabs +#include // fabs /* TODO: * @@ -203,7 +203,7 @@ static bool ComputeZSpacingFromIPP(const DataSet &ds, double &zspacing) if( !sqi ) return false; assert( sqi ); double normal[3]; - DirectionCosines dc( &cosines[0] ); + DirectionCosines dc( cosines.data() ); dc.Cross( normal ); // For each item @@ -611,7 +611,7 @@ bool ImageHelper::GetDirectionCosinesFromDataSet(DataSet const & ds, std::vector { dircos[i] = at.GetValue(i); } - DirectionCosines dc( &dircos[0] ); + DirectionCosines dc( dircos.data() ); if( !dc.IsValid() ) { dc.Normalize(); @@ -1009,10 +1009,19 @@ void ImageHelper::SetDimensionsValue(File& f, const Pixmap & img) const Tag tfgs(0x5200,0x9230); if( ds.FindDataElement( tfgs ) ) { - SmartPointer sqi = ds.GetDataElement( tfgs ).GetValueAsSQ(); + const DataElement &de = ds.GetDataElement( tfgs ); + SmartPointer sqi = de.GetValueAsSQ(); assert( sqi ); - sqi->SetLengthToUndefined(); sqi->SetNumberOfItems( dims[2] ); + { + // Simple mechanism to avoid recomputation of Sequence Length: make + // them undefined length + DataElement dup(de.GetTag()); + dup.SetVR(VR::SQ); + dup.SetValue(*sqi); + dup.SetVLToUndefined(); + ds.Replace(dup); + } } } @@ -1165,7 +1174,7 @@ std::vector ImageHelper::GetRescaleInterceptSlopeValue(File const & f) interceptslope[1] = el_rs.GetValue(); if( interceptslope[1] == 0 ) interceptslope[1] = 1; - gdcmWarningMacro( "PMS Modality LUT loaded for MR Image Storage: [" << interceptslope[0] << "," << interceptslope[1] << "]" ); + gdcmDebugMacro( "PMS Modality LUT loaded for MR Image Storage: [" << interceptslope[0] << "," << interceptslope[1] << "]" ); } } else @@ -1173,8 +1182,13 @@ std::vector ImageHelper::GetRescaleInterceptSlopeValue(File const & f) std::vector dummy(2); if( GetRescaleInterceptSlopeValueFromDataSet(ds, dummy) ) { - // for everyone else, read your DCS, and set: ForceRescaleInterceptSlope = true if needed - gdcmDebugMacro( "Modality LUT unused for MR Image Storage: [" << dummy[0] << "," << dummy[1] << "]" ); + if(dummy[0] != 0 || dummy[1] != 1) { + // SIEMENS is sending MFSPLIT with Modality LUT + // Case is: MAGNETOM Prisma / syngo MR XA30A with MFSPLIT + interceptslope[0] = dummy[0]; + interceptslope[1] = dummy[1]; + gdcmWarningMacro( "Forcing Modality LUT used for MR Image Storage: [" << dummy[0] << "," << dummy[1] << "]" ); + } } } #endif @@ -2129,7 +2143,7 @@ void ImageHelper::SetDirectionCosinesValue(DataSet & ds, const std::vector iop = {{1,0,0,0,1,0}}; // default value assert( dircos.size() == 6 ); - DirectionCosines dc( &dircos[0] ); + DirectionCosines dc( dircos.data() ); if( !dc.IsValid() ) { gdcmWarningMacro( "Direction Cosines are not valid. Using default value (1\\0\\0\\0\\1\\0)" ); @@ -2468,7 +2482,7 @@ bool ImageHelper::GetRealWorldValueMappingContent(File const & f, RealWorldValue ms.SetFromFile(f); const DataSet& ds = f.GetDataSet(); - if( ms == MediaStorage::MRImageStorage ) + if( ms == MediaStorage::MRImageStorage || ms == MediaStorage::NuclearMedicineImageStorage ) { const Tag trwvms(0x0040,0x9096); // Real World Value Mapping Sequence if( ds.FindDataElement( trwvms ) ) diff --git a/Source/MediaStorageAndFileFormat/gdcmImageReader.cxx b/Source/MediaStorageAndFileFormat/gdcmImageReader.cxx index 90852b5d1ff..cd945aa959f 100644 --- a/Source/MediaStorageAndFileFormat/gdcmImageReader.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmImageReader.cxx @@ -68,7 +68,7 @@ bool ImageReader::ReadImage(MediaStorage const &ms) if( !spacing.empty() ) { assert( spacing.size() >= pixeldata.GetNumberOfDimensions() ); // In MR, you can have a Z spacing, but store a 2D image - pixeldata.SetSpacing( &spacing[0] ); + pixeldata.SetSpacing( spacing.data() ); if( spacing.size() > pixeldata.GetNumberOfDimensions() ) // FIXME HACK { pixeldata.SetSpacing(pixeldata.GetNumberOfDimensions(), spacing[pixeldata.GetNumberOfDimensions()] ); @@ -78,7 +78,7 @@ bool ImageReader::ReadImage(MediaStorage const &ms) std::vector origin = ImageHelper::GetOriginValue(*F); if( !origin.empty() ) { - pixeldata.SetOrigin( &origin[0] ); + pixeldata.SetOrigin( origin.data() ); if( origin.size() > pixeldata.GetNumberOfDimensions() ) // FIXME HACK { pixeldata.SetOrigin(pixeldata.GetNumberOfDimensions(), origin[pixeldata.GetNumberOfDimensions()] ); @@ -88,7 +88,7 @@ bool ImageReader::ReadImage(MediaStorage const &ms) std::vector dircos = ImageHelper::GetDirectionCosinesValue(*F); if( !dircos.empty() ) { - pixeldata.SetDirectionCosines( &dircos[0] ); + pixeldata.SetDirectionCosines( dircos.data() ); } // Do the Rescale Intercept & Slope diff --git a/Source/MediaStorageAndFileFormat/gdcmImageRegionReader.cxx b/Source/MediaStorageAndFileFormat/gdcmImageRegionReader.cxx index 1dbebf70389..250967e32b2 100644 --- a/Source/MediaStorageAndFileFormat/gdcmImageRegionReader.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmImageRegionReader.cxx @@ -174,7 +174,7 @@ bool ImageRegionReader::ReadInformation() if( !spacing.empty() ) { assert( spacing.size() >= pixeldata.GetNumberOfDimensions() ); // In MR, you can have a Z spacing, but store a 2D image - pixeldata.SetSpacing( &spacing[0] ); + pixeldata.SetSpacing( spacing.data() ); if( spacing.size() > pixeldata.GetNumberOfDimensions() ) // FIXME HACK { pixeldata.SetSpacing(pixeldata.GetNumberOfDimensions(), spacing[pixeldata.GetNumberOfDimensions()] ); @@ -184,7 +184,7 @@ bool ImageRegionReader::ReadInformation() std::vector origin = ImageHelper::GetOriginValue(*F); if( !origin.empty() ) { - pixeldata.SetOrigin( &origin[0] ); + pixeldata.SetOrigin( origin.data() ); if( origin.size() > pixeldata.GetNumberOfDimensions() ) // FIXME HACK { pixeldata.SetOrigin(pixeldata.GetNumberOfDimensions(), origin[pixeldata.GetNumberOfDimensions()] ); @@ -194,7 +194,7 @@ bool ImageRegionReader::ReadInformation() std::vector dircos = ImageHelper::GetDirectionCosinesValue(*F); if( !dircos.empty() ) { - pixeldata.SetDirectionCosines( &dircos[0] ); + pixeldata.SetDirectionCosines( dircos.data() ); } // Do the Rescale Intercept & Slope @@ -260,10 +260,10 @@ bool ImageRegionReader::ReadRAWIntoBuffer(char *buffer, size_t buflen) std::vector buffer1; buffer1.resize( rowsize*bytesPerPixel ); - char *tmpBuffer1 = &buffer1[0]; + char *tmpBuffer1 = buffer1.data(); std::vector buffer2; buffer2.resize( rowsize*bytesPerPixel ); - char *tmpBuffer2 = &buffer2[0]; + char *tmpBuffer2 = buffer2.data(); unsigned int y, z; std::streamoff theOffset; for (z = zmin; z <= zmax; ++z) diff --git a/Source/MediaStorageAndFileFormat/gdcmJPEG12Codec.cxx b/Source/MediaStorageAndFileFormat/gdcmJPEG12Codec.cxx index 971aaf168f0..b7b41c83e86 100644 --- a/Source/MediaStorageAndFileFormat/gdcmJPEG12Codec.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmJPEG12Codec.cxx @@ -15,7 +15,7 @@ #include "gdcm_ljpeg12.h" -#include +#include #define JPEGBITSCodec JPEG12Codec #define my_error_mgr my_error_mgr_12BIT diff --git a/Source/MediaStorageAndFileFormat/gdcmJPEG16Codec.cxx b/Source/MediaStorageAndFileFormat/gdcmJPEG16Codec.cxx index 63a6ad05ec1..c4d065e2b2c 100644 --- a/Source/MediaStorageAndFileFormat/gdcmJPEG16Codec.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmJPEG16Codec.cxx @@ -15,7 +15,7 @@ #include "gdcm_ljpeg16.h" -#include +#include #define JPEGBITSCodec JPEG16Codec #define my_error_mgr my_error_mgr_16BIT diff --git a/Source/MediaStorageAndFileFormat/gdcmJPEG2000Codec.cxx b/Source/MediaStorageAndFileFormat/gdcmJPEG2000Codec.cxx index c91a5ecb136..10ac23cca4b 100644 --- a/Source/MediaStorageAndFileFormat/gdcmJPEG2000Codec.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmJPEG2000Codec.cxx @@ -187,8 +187,8 @@ static bool parsej2k_imp( const char * const stream, const size_t file_size, boo } cur += lenmarker; cur_size -= lenmarker; } - else if( marker == SOD ) - return true; + else if( marker == SOD ) + return true; } return false; } @@ -553,7 +553,7 @@ bool JPEG2000Codec::Decode(DataElement const &in, DataElement &out) if(!r) return false; out = in; std::string str = os.str(); - out.SetByteValue( &str[0], (uint32_t)str.size() ); + out.SetByteValue( str.data(), (uint32_t)str.size() ); //memcpy(buffer, os.str().c_str(), len); return r; } @@ -591,8 +591,8 @@ bool JPEG2000Codec::Decode(DataElement const &in, DataElement &out) assert( r == true ); } std::string str = os.str(); - assert( str.size() ); - out.SetByteValue( &str[0], (uint32_t)str.size() ); + assert( !str.empty() ); + out.SetByteValue( str.data(), (uint32_t)str.size() ); return true; } @@ -683,7 +683,7 @@ std::pair JPEG2000Codec::DecodeByStreamsCommon(char *dummy_buffe break; default: gdcmErrorMacro( "Impossible happen" ); - return std::make_pair(0,0); + return std::pair(nullptr,0); } #if ((OPJ_VERSION_MAJOR == 2 && OPJ_VERSION_MINOR >= 3) || (OPJ_VERSION_MAJOR > 2)) opj_codec_set_threads(dinfo, Internals->nNumberOfThreadsForDecompression); @@ -714,7 +714,7 @@ std::pair JPEG2000Codec::DecodeByStreamsCommon(char *dummy_buffe opj_destroy_codec(dinfo); opj_stream_destroy(cio); gdcmErrorMacro( "opj_setup_decoder failure" ); - return std::make_pair(0,0); + return std::pair(nullptr,0); } #if 0 OPJ_INT32 l_tile_x0,l_tile_y0; @@ -729,7 +729,7 @@ std::pair JPEG2000Codec::DecodeByStreamsCommon(char *dummy_buffe opj_destroy_codec(dinfo); opj_stream_destroy(cio); gdcmErrorMacro( "opj_setup_decoder failure" ); - return std::make_pair(0,0); + return std::pair(nullptr,0); } #if 0 /* Optional if you want decode the entire image */ @@ -743,7 +743,7 @@ std::pair JPEG2000Codec::DecodeByStreamsCommon(char *dummy_buffe opj_destroy_codec(dinfo); opj_stream_destroy(cio); gdcmErrorMacro( "opj_decode failed" ); - return std::make_pair(0,0); + return std::pair(nullptr,0); } bResult = bResult && (image != nullptr); bResult = bResult && opj_end_decompress(dinfo,cio); @@ -752,7 +752,7 @@ std::pair JPEG2000Codec::DecodeByStreamsCommon(char *dummy_buffe opj_destroy_codec(dinfo); opj_stream_destroy(cio); gdcmErrorMacro( "opj_decode failed" ); - return std::make_pair(0,0); + return std::pair(nullptr,0); } #if 0 @@ -776,8 +776,8 @@ std::pair JPEG2000Codec::DecodeByStreamsCommon(char *dummy_buffe #endif bool b = false; - bool lossless; - bool mct; + bool lossless = false; + bool mct = false; if( parameters.decod_format == JP2_CFMT ) b = parsejp2_imp( dummy_buffer, buf_size, &lossless, &mct); else if( parameters.decod_format == J2K_CFMT ) @@ -931,7 +931,7 @@ void rawtoimage_fill2(const T *inputbuffer, int w, int h, int numcomps, opj_imag // nmask : to propagate sign bit on negative values int16_t nmask = (int16_t)0x8000; nmask = (int16_t)(nmask >> ( bitsallocated - bitsstored - 1 )); - if( pc ) + if( pc ) { for(int compno = 0; compno < numcomps; compno++) { @@ -1260,6 +1260,7 @@ bool JPEG2000Codec::CodeFrameIntoBuffer(char * outdata, size_t outlen, size_t & image_width, image_height, sample_pixel, bitsallocated, bitsstored, highbit, sign, quality, this->GetPlanarConfiguration() ); if (!image) { + free(parameters.cp_comment); return false; } @@ -1288,6 +1289,7 @@ bool JPEG2000Codec::CodeFrameIntoBuffer(char * outdata, size_t outlen, size_t & cio = opj_stream_create_memory_stream(fsrc,OPJ_J2K_STREAM_CHUNK_SIZE,false); if (! cio) { + free(parameters.cp_comment); return false; } /* encode the image */ @@ -1301,6 +1303,7 @@ bool JPEG2000Codec::CodeFrameIntoBuffer(char * outdata, size_t outlen, size_t & if (!bSuccess) { opj_stream_destroy(cio); + free(parameters.cp_comment); return false; } codestream_length = mysrc.len; @@ -1309,6 +1312,7 @@ bool JPEG2000Codec::CodeFrameIntoBuffer(char * outdata, size_t outlen, size_t & //f = fopen(parameters.outfile, "wb"); //if (!f) { // fprintf(stderr, "failed to open %s for writing\n", parameters.outfile); + // free(parameters.cp_comment); // return 1; //} //fwrite(cio->buffer, 1, codestream_length, f); @@ -1376,12 +1380,12 @@ bool JPEG2000Codec::Code(DataElement const &in, DataElement &out) rgbyteCompressed.resize(image_width * image_height * 4); size_t cbyteCompressed; - const bool b = this->CodeFrameIntoBuffer((char*)&rgbyteCompressed[0], rgbyteCompressed.size(), cbyteCompressed, inputdata, inputlength ); + const bool b = this->CodeFrameIntoBuffer((char*)rgbyteCompressed.data(), rgbyteCompressed.size(), cbyteCompressed, inputdata, inputlength ); if( !b ) return false; Fragment frag; assert( cbyteCompressed <= rgbyteCompressed.size() ); // default alloc would be bogus - frag.SetByteValue( &rgbyteCompressed[0], (uint32_t)cbyteCompressed ); + frag.SetByteValue( rgbyteCompressed.data(), (uint32_t)cbyteCompressed ); sq->AddFragment( frag ); } @@ -1498,8 +1502,8 @@ bool JPEG2000Codec::GetHeaderInfo(const char * dummy_buffer, size_t buf_size, Tr assert( mct == 0 || mct == 1 ); #else bool b = false; - bool lossless; - bool mctb; + bool lossless = false; + bool mctb = false; if( parameters.decod_format == JP2_CFMT ) b = parsejp2_imp( dummy_buffer, buf_size, &lossless, &mctb); else if( parameters.decod_format == J2K_CFMT ) @@ -1702,7 +1706,7 @@ bool JPEG2000Codec::DecodeExtent( // update buf_size = fraglen + oldlen; vdummybuffer.resize( buf_size ); - dummy_buffer = &vdummybuffer[0]; + dummy_buffer = vdummybuffer.data(); // read J2K is.read( &vdummybuffer[oldlen], fraglen ); } @@ -1847,10 +1851,10 @@ bool JPEG2000Codec::AppendFrameEncode( std::ostream & out, const char * data, si rgbyteCompressed.resize(dimensions[0] * dimensions[1] * 4); size_t cbyteCompressed; - const bool b = this->CodeFrameIntoBuffer((char*)&rgbyteCompressed[0], rgbyteCompressed.size(), cbyteCompressed, data, datalen ); + const bool b = this->CodeFrameIntoBuffer((char*)rgbyteCompressed.data(), rgbyteCompressed.size(), cbyteCompressed, data, datalen ); if( !b ) return false; - out.write( (char*)&rgbyteCompressed[0], cbyteCompressed ); + out.write( (char*)rgbyteCompressed.data(), cbyteCompressed ); return true; } diff --git a/Source/MediaStorageAndFileFormat/gdcmJPEG8Codec.cxx b/Source/MediaStorageAndFileFormat/gdcmJPEG8Codec.cxx index 8ca05c953a5..c031adaa346 100644 --- a/Source/MediaStorageAndFileFormat/gdcmJPEG8Codec.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmJPEG8Codec.cxx @@ -15,7 +15,7 @@ #include "gdcm_ljpeg8.h" -#include +#include #define JPEGBITSCodec JPEG8Codec #define my_error_mgr my_error_mgr_8BIT diff --git a/Source/MediaStorageAndFileFormat/gdcmJPEGBITSCodec.hxx b/Source/MediaStorageAndFileFormat/gdcmJPEGBITSCodec.hxx index 1d6c9eb8149..5a08842681b 100644 --- a/Source/MediaStorageAndFileFormat/gdcmJPEGBITSCodec.hxx +++ b/Source/MediaStorageAndFileFormat/gdcmJPEGBITSCodec.hxx @@ -477,9 +477,9 @@ bool JPEGBITSCodec::GetHeaderInfo(std::istream &is, TransferSyntax &ts) else if( cinfo.jpeg_color_space == JCS_YCCK ) { assert( cinfo.num_components == 4 ); - PI = PhotometricInterpretation::YBR_FULL_422; // 4th plane ?? + gdcmWarningMacro( "JCS_YCCK is not handled. Setting to CMYK for now." ); + PI = PhotometricInterpretation::CMYK; // non-sense...oh well this->PF.SetSamplesPerPixel( 4 ); - assert( 0 ); //TODO } else { diff --git a/Source/MediaStorageAndFileFormat/gdcmJPEGCodec.cxx b/Source/MediaStorageAndFileFormat/gdcmJPEGCodec.cxx index 4d2d35e3b0d..467e1ff64f4 100644 --- a/Source/MediaStorageAndFileFormat/gdcmJPEGCodec.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmJPEGCodec.cxx @@ -21,8 +21,8 @@ #include "gdcmJPEG12Codec.h" #include "gdcmJPEG16Codec.h" +#include #include -#include namespace gdcm { @@ -342,11 +342,11 @@ bool JPEGCodec::Code(DataElement const &in, DataElement &out) } std::string str = os.str(); - assert( str.size() ); + assert( !str.empty() ); Fragment frag; //frag.SetTag( itemStart ); VL::Type strSize = (VL::Type)str.size(); - frag.SetByteValue( &str[0], strSize ); + frag.SetByteValue( str.data(), strSize ); sq->AddFragment( frag ); } @@ -528,7 +528,7 @@ bool JPEGCodec::DecodeExtent( assert( zmin == 0 ); std::stringstream iis; - iis.write( &vdummybuffer[0], vdummybuffer.size() ); + iis.write( vdummybuffer.data(), vdummybuffer.size() ); std::stringstream os; bool b = DecodeByStreams(iis,os); if(!b) return false; @@ -542,7 +542,7 @@ bool JPEGCodec::DecodeExtent( std::istream *theStream = &os; std::vector buffer1; buffer1.resize( rowsize*bytesPerPixel ); - char *tmpBuffer1 = &buffer1[0]; + char *tmpBuffer1 = buffer1.data(); unsigned int y, z; std::streamoff theOffset; for (z = zmin; z <= zmax; ++z) @@ -609,7 +609,7 @@ bool JPEGCodec::DecodeExtent( std::vector buffer1; buffer1.resize( rowsize*bytesPerPixel ); - char *tmpBuffer1 = &buffer1[0]; + char *tmpBuffer1 = buffer1.data(); unsigned int y; std::streamoff theOffset; for (y = ymin; y <= ymax; ++y) diff --git a/Source/MediaStorageAndFileFormat/gdcmJPEGLSCodec.cxx b/Source/MediaStorageAndFileFormat/gdcmJPEGLSCodec.cxx index 0769655ea89..38d2f6d65f7 100644 --- a/Source/MediaStorageAndFileFormat/gdcmJPEGLSCodec.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmJPEGLSCodec.cxx @@ -24,7 +24,7 @@ #include "gdcm_charls.h" -#if defined(__GNUC__) && GCC_VERSION < 50101 +#if defined(GCC_VERSION) && GCC_VERSION < 50101 #pragma GCC diagnostic ignored "-Wmissing-field-initializers" #endif @@ -110,7 +110,7 @@ bool JPEGLSCodec::GetHeaderInfo(std::istream &is, TransferSyntax &ts) else if( metadata.components == 3 ) { PI = PhotometricInterpretation::RGB; - PlanarConfiguration = 1; + PlanarConfiguration = 0; // CP-1843 this->PF.SetSamplesPerPixel( 3 ); } else assert(0); @@ -151,6 +151,32 @@ bool JPEGLSCodec::CanCode(TransferSyntax const &ts) const #endif } +template +static void ConvPlanar(std::vector &input) +{ + size_t buf_size = input.size(); + assert( buf_size % sizeof(T) == 0 ); + size_t npixels = buf_size / sizeof( T ); + assert( npixels % 3 == 0 ); + size_t size = npixels / 3; + T* buffer = (T*)input.data(); + + const T *r = buffer; + const T *g = buffer + size; + const T *b = buffer + size + size; + + T *copy = new T[ npixels ]; + T *p = copy; + for (size_t j = 0; j < size; ++j) + { + *(p++) = *(r++); + *(p++) = *(g++); + *(p++) = *(b++); + } + std::memcpy(input.data(), copy, input.size() ); + delete[] copy; +} + bool JPEGLSCodec::DecodeByStreamsCommon(const char *buffer, size_t totalLen, std::vector &rgbyteOut) { using namespace charls; @@ -164,12 +190,30 @@ bool JPEGLSCodec::DecodeByStreamsCommon(const char *buffer, size_t totalLen, std return false; } + if( params.colorTransformation != charls::ColorTransformation::None ) + { + gdcmWarningMacro( "APP8 marker found to contains a color transformation. This is an HP extension" ); + } // allowedlossyerror == 0 => Lossless LossyFlag = params.allowedLossyError!= 0; rgbyteOut.resize(params.height *params.width * ((params.bitsPerSample + 7) / 8) * params.components); - ApiResult result = JpegLsDecode(&rgbyteOut[0], rgbyteOut.size(), pbyteCompressed, cbyteCompressed, ¶ms, nullptr); + ApiResult result = JpegLsDecode(rgbyteOut.data(), rgbyteOut.size(), pbyteCompressed, cbyteCompressed, ¶ms, nullptr); + + if( params.components == 3 ) + { + const unsigned int nBytes = (params.bitsPerSample + 7) / 8; + if( params.interleaveMode == InterleaveMode::None ) + { + if(nBytes == 1 ) + ConvPlanar(rgbyteOut); + else if(nBytes == 2 ) + ConvPlanar(rgbyteOut); + else + assert(0); + } + } if (result != ApiResult::OK) { @@ -201,7 +245,7 @@ bool JPEGLSCodec::Decode(DataElement const &in, DataElement &out) out = in; - out.SetByteValue( (char*)&rgbyteOut[0], (uint32_t)rgbyteOut.size() ); + out.SetByteValue( (char*)rgbyteOut.data(), (uint32_t)rgbyteOut.size() ); return true; } else if( NumberOfDimensions == 3 ) @@ -244,7 +288,7 @@ bool JPEGLSCodec::Decode(DataElement const &in, DataElement &out) std::vector rgbyteOut; rgbyteOut.resize(params.height *params.width * ((params.bitsPerSample + 7) / 8) * params.components); - ApiResult result = JpegLsDecode(&rgbyteOut[0], rgbyteOut.size(), pbyteCompressed, cbyteCompressed, ¶ms, nullptr); + ApiResult result = JpegLsDecode(rgbyteOut.data(), rgbyteOut.size(), pbyteCompressed, cbyteCompressed, ¶ms, nullptr); bool r = true; delete[] mybuffer; @@ -252,14 +296,14 @@ bool JPEGLSCodec::Decode(DataElement const &in, DataElement &out) { return false; } - os.write( (const char*)&rgbyteOut[0], rgbyteOut.size() ); + os.write( (const char*)rgbyteOut.data(), rgbyteOut.size() ); if(!r) return false; assert( r == true ); } std::string str = os.str(); - assert( str.size() ); - out.SetByteValue( &str[0], (uint32_t)str.size() ); + assert( !str.empty() ); + out.SetByteValue( str.data(), (uint32_t)str.size() ); return true; } @@ -279,6 +323,7 @@ bool JPEGLSCodec::CodeFrameIntoBuffer(char * outdata, size_t outlen, size_t & co int image_height = dims[1]; const PixelFormat &pf = this->GetPixelFormat(); + unsigned int planarConf = this->GetPlanarConfiguration(); int sample_pixel = pf.GetSamplesPerPixel(); int bitsallocated = pf.GetBitsAllocated(); int bitsstored = pf.GetBitsStored(); @@ -331,13 +376,18 @@ bool JPEGLSCodec::CodeFrameIntoBuffer(char * outdata, size_t outlen, size_t & co if (sample_pixel == 4) { - params.interleaveMode = InterleaveMode::Line; + params.interleaveMode = InterleaveMode::Sample; } else if (sample_pixel == 3) { - params.interleaveMode = InterleaveMode::Line; - params.colorTransformation = ColorTransformation::HP1; + if(planarConf == 0) + params.interleaveMode = InterleaveMode::Sample; + else + params.interleaveMode = InterleaveMode::None; + params.colorTransformation = ColorTransformation::None; } + else if (sample_pixel == 1) + params.interleaveMode = InterleaveMode::None; ApiResult error = JpegLsEncode(outdata, outlen, &complen, indata, inlen, ¶ms, nullptr); @@ -382,11 +432,11 @@ bool JPEGLSCodec::Code(DataElement const &in, DataElement &out) rgbyteCompressed.resize(image_width * image_height * 4 * 2); // overallocate in case of weird case size_t cbyteCompressed; - const bool b = this->CodeFrameIntoBuffer((char*)&rgbyteCompressed[0], rgbyteCompressed.size(), cbyteCompressed, inputdata, inputlength ); + const bool b = this->CodeFrameIntoBuffer((char*)rgbyteCompressed.data(), rgbyteCompressed.size(), cbyteCompressed, inputdata, inputlength ); if( !b ) return false; Fragment frag; - frag.SetByteValue( (char*)&rgbyteCompressed[0], (uint32_t)cbyteCompressed ); + frag.SetByteValue( (char*)rgbyteCompressed.data(), (uint32_t)cbyteCompressed ); sq->AddFragment( frag ); } @@ -442,7 +492,7 @@ bool JPEGLSCodec::DecodeExtent( // update buf_size = fraglen + oldlen; vdummybuffer.resize( buf_size ); - dummy_buffer = &vdummybuffer[0]; + dummy_buffer = vdummybuffer.data(); // read J2K is.read( &vdummybuffer[oldlen], fraglen ); } @@ -454,7 +504,7 @@ bool JPEGLSCodec::DecodeExtent( bool b = DecodeByStreamsCommon(dummy_buffer, buf_size, outv); if( !b ) return false; - unsigned char *raw = &outv[0]; + unsigned char *raw = outv.data(); const unsigned int rowsize = xmax - xmin + 1; const unsigned int colsize = ymax - ymin + 1; const unsigned int bytesPerPixel = pf.GetPixelSize(); @@ -516,7 +566,7 @@ bool JPEGLSCodec::DecodeExtent( if( !b ) return false; - unsigned char *raw = &outv[0]; + unsigned char *raw = outv.data(); const unsigned int rowsize = xmax - xmin + 1; const unsigned int colsize = ymax - ymin + 1; const unsigned int bytesPerPixel = pf.GetPixelSize(); @@ -576,10 +626,10 @@ bool JPEGLSCodec::AppendFrameEncode( std::ostream & out, const char * data, size rgbyteCompressed.resize(dimensions[0] * dimensions[1] * 4); size_t cbyteCompressed; - const bool b = this->CodeFrameIntoBuffer((char*)&rgbyteCompressed[0], rgbyteCompressed.size(), cbyteCompressed, data, datalen ); + const bool b = this->CodeFrameIntoBuffer((char*)rgbyteCompressed.data(), rgbyteCompressed.size(), cbyteCompressed, data, datalen ); if( !b ) return false; - out.write( (char*)&rgbyteCompressed[0], cbyteCompressed ); + out.write( (char*)rgbyteCompressed.data(), cbyteCompressed ); return true; } diff --git a/Source/MediaStorageAndFileFormat/gdcmLookupTable.cxx b/Source/MediaStorageAndFileFormat/gdcmLookupTable.cxx index 1e72d6e7e66..0d5a99c4002 100644 --- a/Source/MediaStorageAndFileFormat/gdcmLookupTable.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmLookupTable.cxx @@ -18,7 +18,7 @@ #include #include -#include +#include namespace gdcm { @@ -171,7 +171,7 @@ void LookupTable::SetLUT(LookupTableType type, const unsigned char *array, else if( BitSample == 16 ) { assert( Internal->Length[type]*(BitSample/8) == length ); - uint16_t *uchar16 = (uint16_t*)(void*)&Internal->RGB[0]; + uint16_t *uchar16 = (uint16_t*)(void*)Internal->RGB.data(); const uint16_t *array16 = (const uint16_t*)(const void*)array; for( unsigned int i = 0; i < Internal->Length[type]; ++i) { @@ -203,7 +203,7 @@ void LookupTable::GetLUT(LookupTableType type, unsigned char *array, unsigned in else if( BitSample == 16 ) { length = Internal->Length[type]*(BitSample/8); - uint16_t *uchar16 = (uint16_t*)(void*)&Internal->RGB[0]; + uint16_t *uchar16 = (uint16_t*)(void*)Internal->RGB.data(); uint16_t *array16 = (uint16_t*)(void*)array; for( unsigned int i = 0; i < Internal->Length[type]; ++i) { @@ -279,6 +279,8 @@ namespace { uint64_t I; }; +#if 0 + // FIXME: see comments below struct ltstr8 { bool operator()(U8 u1, U8 u2) const @@ -293,6 +295,7 @@ namespace { return u1.I < u2.I; } }; +#endif } // end namespace inline void printrgb( const unsigned char *rgb ) @@ -306,7 +309,7 @@ void LookupTable::Encode(std::istream &is, std::ostream &os) { #if 0 // FIXME: - // There is a very subbtle issue here. We are trying to compress a 8bits RGB image + // There is a very subtle issue here. We are trying to compress a 8bits RGB image // into an 8bits allocated indexed Pixel Data with 8bits LUT... this is just not // possible in the general case typedef std::set< U8, ltstr8 > RGBColorIndexer; @@ -476,7 +479,7 @@ void LookupTable::Decode(std::istream &is, std::ostream &os) const else if ( BitSample == 16 ) { // gdcmData/NM-PAL-16-PixRep1.dcm - const uint16_t *rgb16 = (uint16_t*)(void*)&Internal->RGB[0]; + const uint16_t *rgb16 = (uint16_t*)(void*)Internal->RGB.data(); while( !is.eof() ) { unsigned short idx; @@ -531,7 +534,7 @@ bool LookupTable::Decode(char *output, size_t outlen, const char *input, size_t } else if ( BitSample == 16 ) { - const uint16_t *rgb16 = (const uint16_t*)(void*)&Internal->RGB[0]; + const uint16_t *rgb16 = (const uint16_t*)(void*)Internal->RGB.data(); assert( inlen % 2 == 0 ); const uint16_t * end = (const uint16_t*)(const void*)(input + inlen); uint16_t * rgb = (uint16_t*)(void*)output; @@ -587,7 +590,7 @@ bool LookupTable::Decode8(char *output, size_t outlen, const char *input, size_t } else if ( BitSample == 16 ) { - const uint16_t *rgb16 = (const uint16_t*)(void*)&Internal->RGB[0]; + const uint16_t *rgb16 = (const uint16_t*)(void*)Internal->RGB.data(); assert( inlen % 2 == 0 ); const uint16_t * end = (const uint16_t*)(const void*)(input + inlen); uint8_t * rgb = (uint8_t*)output; @@ -613,7 +616,7 @@ const unsigned char *LookupTable::GetPointer() const { if ( BitSample == 8 ) { - return &Internal->RGB[0]; + return Internal->RGB.data(); } return nullptr; } @@ -654,7 +657,7 @@ bool LookupTable::GetBufferAsRGBA(unsigned char *rgba) const ret = true; */ //std::vector::const_iterator it = Internal->RGB.begin(); - uint16_t *uchar16 = (uint16_t*)(void*)&Internal->RGB[0]; + uint16_t *uchar16 = (uint16_t*)(void*)Internal->RGB.data(); uint16_t *rgba16 = (uint16_t*)(void*)rgba; size_t s = Internal->RGB.size(); s /= 2; @@ -699,7 +702,7 @@ bool LookupTable::WriteBufferAsRGBA(const unsigned char *rgba) else if ( BitSample == 16 ) { //assert( Internal->Length[type]*(BitSample/8) == length ); - uint16_t *uchar16 = (uint16_t*)(void*)&Internal->RGB[0]; + uint16_t *uchar16 = (uint16_t*)(void*)Internal->RGB.data(); const uint16_t *rgba16 = (const uint16_t*)(const void*)rgba; size_t s = Internal->RGB.size(); s /= 2; @@ -734,7 +737,7 @@ void LookupTable::Print(std::ostream &os) const { uint16_t maxlut[3] = { 0 , 0 , 0}; uint16_t minlut[3] = { 0xffff, 0xffff, 0xffff }; - uint16_t *uchar16 = (uint16_t*)(void*)&Internal->RGB[0]; + uint16_t *uchar16 = (uint16_t*)(void*)Internal->RGB.data(); if( Internal->Length[BLUE] != Internal->Length[RED] || Internal->Length[RED] != Internal->Length[GREEN] ) return; for( unsigned int i = 0; i < Internal->Length[BLUE]; ++i) @@ -767,7 +770,7 @@ bool LookupTable::IsRGB8() const { uint16_t maxlut[3] = { 0 , 0 , 0}; uint16_t minlut[3] = { 0xffff, 0xffff, 0xffff }; - uint16_t *uchar16 = (uint16_t*)(void*)&Internal->RGB[0]; + uint16_t *uchar16 = (uint16_t*)(void*)Internal->RGB.data(); if( Internal->Length[BLUE] != Internal->Length[RED] || Internal->Length[RED] != Internal->Length[GREEN] ) return false; for( unsigned int i = 0; i < Internal->Length[BLUE]; ++i) diff --git a/Source/MediaStorageAndFileFormat/gdcmMEC_MR3.cxx b/Source/MediaStorageAndFileFormat/gdcmMEC_MR3.cxx new file mode 100644 index 00000000000..c294554f06f --- /dev/null +++ b/Source/MediaStorageAndFileFormat/gdcmMEC_MR3.cxx @@ -0,0 +1,37 @@ +/*========================================================================= + + Program: GDCM (Grassroots DICOM). A DICOM library + + Copyright (c) 2006-2011 Mathieu Malaterre + All rights reserved. + See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "gdcmMEC_MR3.h" + +#include "gdcmext/mec_mr3_io.h" + +namespace gdcm { +bool MEC_MR3::Print(const char *src, size_t srclen) { + return mec_mr3_print(src, srclen); +} +const PrivateTag &MEC_MR3::GetPMTFInformationDataTag() { + static const PrivateTag tseq(0x0029, 0x90, "PMTF INFORMATION DATA"); + return tseq; +} + +const PrivateTag &MEC_MR3::GetCanonMECMR3Tag() { + static const PrivateTag tseq(0x0029, 0x90, "CANON_MEC_MR3"); + return tseq; +} + +const PrivateTag &MEC_MR3::GetToshibaMECMR3Tag() { + static const PrivateTag tseq(0x0029, 0x90, "TOSHIBA_MEC_MR3"); + return tseq; +} + +} // end namespace gdcm diff --git a/Source/MediaStorageAndFileFormat/gdcmMEC_MR3.h b/Source/MediaStorageAndFileFormat/gdcmMEC_MR3.h new file mode 100644 index 00000000000..c0228102877 --- /dev/null +++ b/Source/MediaStorageAndFileFormat/gdcmMEC_MR3.h @@ -0,0 +1,43 @@ +/*========================================================================= + + Program: GDCM (Grassroots DICOM). A DICOM library + + Copyright (c) 2006-2011 Mathieu Malaterre + All rights reserved. + See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef GDCMMEC_MR3_H +#define GDCMMEC_MR3_H + +#include "gdcmPrivateTag.h" + +namespace gdcm { +/** + * \brief Class for MEC_MR3 + * + */ +class GDCM_EXPORT MEC_MR3 { + public: + static bool Print(const char *src, size_t srclen); + + /// Return the private tag used by PMTF to store the MEC_MR3 data + /// This is: PrivateTag(0x0029,0x90,"PMTF INFORMATION DATA"); + static const PrivateTag &GetPMTFInformationDataTag(); + + /// Return the private tag used by CANON to store the MEC_MR3 data + /// This is: PrivateTag(0x0029,0x90,"CANON_MEC_MR3"); + static const PrivateTag &GetCanonMECMR3Tag(); + + /// Return the private tag used by TOSHIBA to store the MEC_MR3 data + /// This is: PrivateTag(0x0029,0x90,"TOSHIBA_MEC_MR3"); + static const PrivateTag &GetToshibaMECMR3Tag(); +}; + +} // end namespace gdcm + +#endif // GDCMMEC_MR3_H diff --git a/Source/MediaStorageAndFileFormat/gdcmOrientation.cxx b/Source/MediaStorageAndFileFormat/gdcmOrientation.cxx index fa70a3d10a0..836e5ae0a93 100644 --- a/Source/MediaStorageAndFileFormat/gdcmOrientation.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmOrientation.cxx @@ -19,7 +19,6 @@ namespace gdcm { Orientation::Orientation() = default; -Orientation::~Orientation() = default; void Orientation::Print(std::ostream &os) const { diff --git a/Source/MediaStorageAndFileFormat/gdcmOrientation.h b/Source/MediaStorageAndFileFormat/gdcmOrientation.h index c4d21f6367a..bced6667fad 100644 --- a/Source/MediaStorageAndFileFormat/gdcmOrientation.h +++ b/Source/MediaStorageAndFileFormat/gdcmOrientation.h @@ -27,7 +27,7 @@ class GDCM_EXPORT Orientation friend std::ostream& operator<<(std::ostream &_os, const Orientation &o); public: Orientation(); - ~Orientation(); + ~Orientation() = default; /// Print void Print(std::ostream &) const; diff --git a/Source/MediaStorageAndFileFormat/gdcmOverlay.cxx b/Source/MediaStorageAndFileFormat/gdcmOverlay.cxx index 5c2d5743cee..2298687f458 100644 --- a/Source/MediaStorageAndFileFormat/gdcmOverlay.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmOverlay.cxx @@ -274,7 +274,7 @@ bool Overlay::GrabOverlayFromPixelData(DataSet const &ds) gdcmWarningMacro("Internal Data is empty." ); return false; } - unsigned char * overlay = (unsigned char*)&Internal->Data[0]; + unsigned char * overlay = (unsigned char*)Internal->Data.data(); int c = 0; uint8_t pmask = (uint8_t)(1 << Internal->BitPosition); assert( length / 1 == ovlength * 8 ); @@ -326,7 +326,7 @@ bool Overlay::GrabOverlayFromPixelData(DataSet const &ds) gdcmWarningMacro("Internal Data is empty." ); return false; } - unsigned char * overlay = (unsigned char*)&Internal->Data[0]; + unsigned char * overlay = (unsigned char*)Internal->Data.data(); int c = 0; uint16_t pmask = (uint16_t)(1 << Internal->BitPosition); assert( length / 2 == ovlength * 8 ); diff --git a/Source/MediaStorageAndFileFormat/gdcmPGXCodec.cxx b/Source/MediaStorageAndFileFormat/gdcmPGXCodec.cxx index 497ce8fe649..88f3cf1f49e 100644 --- a/Source/MediaStorageAndFileFormat/gdcmPGXCodec.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmPGXCodec.cxx @@ -62,8 +62,16 @@ bool PGXCodec::Write(const char *filename, const DataElement &out) const "You need to decompress first." ); return false; } +#if 1 + gdcm::PhotometricInterpretation pi = this->GetPhotometricInterpretation(); + if( pi != gdcm::PhotometricInterpretation::MONOCHROME2 ) { + gdcmErrorMacro( "Bogus PI" << pi ); + return false; + } +#endif const unsigned int *dims = this->GetDimensions(); - size_t image_size = dims[0] * dims[1]; + uint8_t pixelSize = pf.GetPixelSize (); + size_t image_size = dims[0] * dims[1] * pixelSize; const char *img_buffer = bv->GetPointer(); for( unsigned int i = 0; i < num_images; ++i, img_buffer += image_size ) @@ -88,14 +96,55 @@ bool PGXCodec::Read(const char *filename, DataElement &out) const { (void)filename; (void)out; + gdcmErrorMacro("TODO" ); return false; } -bool PGXCodec::GetHeaderInfo(std::istream &is, TransferSyntax &ts) +bool PGXCodec::GetHeaderInfo(std::istream &is0, TransferSyntax &ts) { - (void)is; - (void)ts; - return false; + std::string str; + std::getline(is0, str); + { + std::istringstream is(str); + std::string str1, str2, sign; + int depth; + is >> str1; + if( str1 != "PG" ) { + gdcmErrorMacro("PGX Wrong header: " << str1 ); + return false; + } + is >> str2; + if( str2 != "ML" ) { + gdcmErrorMacro("PGX Wrong header: " << str2 ); + return false; + } + is >> sign; + if( sign != "+" && sign != "-" ) { + gdcmErrorMacro("PGX Wrong header: " << sign); + return false; + } + is >> depth; + if( depth <= 0 ) { + gdcmErrorMacro("PGX Wrong header: " << depth ); + return false; + } + PhotometricInterpretation pi; + pi = PhotometricInterpretation::MONOCHROME2; + unsigned int dims[3] = {}; + is >> dims[0]; is >> dims[1]; + PixelFormat pf = GetPixelFormat(); + unsigned int numbytes = ( depth + 7 ) / 8; + pf.SetBitsAllocated( numbytes * 8); + pf.SetBitsStored( depth ); + if( sign[0] == '-' ) pf.SetPixelRepresentation(1); + ts = TransferSyntax::ExplicitVRLittleEndian; + + SetPhotometricInterpretation( pi ); + SetPixelFormat( pf ); + SetDimensions( dims ); + } + + return true; } ImageCodec * PGXCodec::Clone() const diff --git a/Source/MediaStorageAndFileFormat/gdcmPVRGCodec.h b/Source/MediaStorageAndFileFormat/gdcmPVRGCodec.h index 0b9dbcb10f2..8b550b7682a 100644 --- a/Source/MediaStorageAndFileFormat/gdcmPVRGCodec.h +++ b/Source/MediaStorageAndFileFormat/gdcmPVRGCodec.h @@ -21,7 +21,6 @@ namespace gdcm /** * \brief PVRGCodec - * \details * \note pvrg is a broken implementation of the JPEG standard. It is known to * have a bug in the 16bits lossless implementation of the standard. * diff --git a/Source/MediaStorageAndFileFormat/gdcmPersonName.h b/Source/MediaStorageAndFileFormat/gdcmPersonName.h index 220104b771c..6948f9e00cb 100644 --- a/Source/MediaStorageAndFileFormat/gdcmPersonName.h +++ b/Source/MediaStorageAndFileFormat/gdcmPersonName.h @@ -42,7 +42,7 @@ class GDCM_EXPORT PersonName } return r+1; } - unsigned int GetMaxLength() const { return MaxLength; }; + unsigned int GetMaxLength() const { return MaxLength; } void SetBlob(const std::vector& v) { (void)v; //assert(0); //TODO diff --git a/Source/MediaStorageAndFileFormat/gdcmPixelFormat.cxx b/Source/MediaStorageAndFileFormat/gdcmPixelFormat.cxx index ede86f753f9..37a1b708085 100644 --- a/Source/MediaStorageAndFileFormat/gdcmPixelFormat.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmPixelFormat.cxx @@ -15,7 +15,7 @@ #include "gdcmTrace.h" #include "gdcmTransferSyntax.h" -#include +#include namespace gdcm { diff --git a/Source/MediaStorageAndFileFormat/gdcmPixelFormat.h b/Source/MediaStorageAndFileFormat/gdcmPixelFormat.h index 3b9eb2caeb6..89100e855dd 100644 --- a/Source/MediaStorageAndFileFormat/gdcmPixelFormat.h +++ b/Source/MediaStorageAndFileFormat/gdcmPixelFormat.h @@ -47,7 +47,7 @@ class GDCM_EXPORT PixelFormat friend class Bitmap; friend std::ostream& operator<<(std::ostream &_os, const PixelFormat &pf); public: - // When adding a type please add its dual type (its unsigned conterpart) + // When adding a type please add its dual type (its unsigned counterpart) typedef enum { UINT8, INT8, diff --git a/Source/MediaStorageAndFileFormat/gdcmPixmapReader.cxx b/Source/MediaStorageAndFileFormat/gdcmPixmapReader.cxx index d4fa701cc4c..9c30ff8b9de 100644 --- a/Source/MediaStorageAndFileFormat/gdcmPixmapReader.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmPixmapReader.cxx @@ -1059,7 +1059,7 @@ bool PixmapReader::ReadImageInternal(MediaStorage const &ms, bool handlepixeldat assert( jpeg.GetDimensions()[1] ); v[0] = jpeg.GetDimensions()[0]; v[1] = jpeg.GetDimensions()[1]; - PixelData->SetDimensions( &v[0] ); + PixelData->SetDimensions( v.data() ); //PixelData->SetPixelFormat( jpeg.GetPixelFormat() ); // need to handle carefully if( PixelData->GetPixelFormat().GetSamplesPerPixel() != jpeg.GetPixelFormat().GetSamplesPerPixel() ) { diff --git a/Source/MediaStorageAndFileFormat/gdcmPixmapReader.h b/Source/MediaStorageAndFileFormat/gdcmPixmapReader.h index 7e17a9d47d4..f4653e83b5f 100644 --- a/Source/MediaStorageAndFileFormat/gdcmPixmapReader.h +++ b/Source/MediaStorageAndFileFormat/gdcmPixmapReader.h @@ -24,7 +24,6 @@ class ByteValue; class MediaStorage; /** * \brief PixmapReader - * \details * \note its role is to convert the DICOM DataSet into a Pixmap * representation * By default it is also loading the lookup table and overlay when found as diff --git a/Source/MediaStorageAndFileFormat/gdcmPixmapWriter.cxx b/Source/MediaStorageAndFileFormat/gdcmPixmapWriter.cxx index 3a3008c626e..ecc6622877a 100644 --- a/Source/MediaStorageAndFileFormat/gdcmPixmapWriter.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmPixmapWriter.cxx @@ -123,12 +123,12 @@ Attribute<0x0028,0x0004> piat; rawlut8.resize(256); //unsigned short rawlut16[65536]; std::vector rawlut16; - unsigned short *rawlut = &rawlut8[0]; + unsigned short *rawlut = rawlut8.data(); unsigned int lutlen = 256; if( pf.GetBitsAllocated() == 16 ) { rawlut16.resize(65536); - rawlut = &rawlut16[0]; + rawlut = rawlut16.data(); lutlen = 65536; } unsigned int l; diff --git a/Source/MediaStorageAndFileFormat/gdcmPrinter.cxx b/Source/MediaStorageAndFileFormat/gdcmPrinter.cxx index 6d8758d1aa1..b7a45fac90e 100644 --- a/Source/MediaStorageAndFileFormat/gdcmPrinter.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmPrinter.cxx @@ -82,8 +82,6 @@ Printer::Printer():PrintStyle(Printer::VERBOSE_STYLE),F(nullptr) } //----------------------------------------------------------------------------- -Printer::~Printer() -= default; void Printer::SetColor(bool c) { @@ -463,8 +461,9 @@ VR Printer::PrintDataElement(std::ostringstream &os, const Dicts &dicts, const D std::string strowner; const char *owner = nullptr; const Tag& t = de.GetTag(); - if( t.IsPrivate() && !t.IsPrivateCreator() ) + if( t.IsPrivate() && !t.IsPrivateCreator() && !t.IsGroupLength() ) { + // do not reject illegal at this point to handle group 0x0003 / AEGIS_DICOM_2.00 strowner = ds.GetPrivateCreator(t); owner = strowner.c_str(); } @@ -535,8 +534,14 @@ VR Printer::PrintDataElement(std::ostringstream &os, const Dicts &dicts, const D if( vr != VR::INVALID && (!vr.Compatible( vr_read ) || vr_read == VR::INVALID || vr_read == VR::UN || vr_read != refvr ) ) { assert( vr != VR::INVALID ); + bool valid = true; + if( vr_read == VR::SQ ) { + if( !vr.Compatible( vr_read ) ) { + valid = false; + } + } // FIXME : if terminal supports it: print in red/green ! - os << GDCM_TERMINAL_VT100_FOREGROUND_GREEN; + os << (valid ? GDCM_TERMINAL_VT100_FOREGROUND_GREEN : GDCM_TERMINAL_VT100_FOREGROUND_RED); if( vr == VR::US_SS || vr == VR::OB_OW ) { os << "(" << vr << " => " << refvr << ") "; @@ -843,7 +848,6 @@ VR Printer::PrintDataElement(std::ostringstream &os, const Dicts &dicts, const D // retired element else if( retired ) { - assert( t.IsPublic() || t.GetElement() == 0x0 ); // Is there such thing as private and retired element ? os << " " << GDCM_TERMINAL_VT100_FOREGROUND_RED << GDCM_TERMINAL_VT100_UNDERLINE; os << name; os << GDCM_TERMINAL_VT100_NORMAL; diff --git a/Source/MediaStorageAndFileFormat/gdcmPrinter.h b/Source/MediaStorageAndFileFormat/gdcmPrinter.h index fa183dc6b10..92999178a3d 100644 --- a/Source/MediaStorageAndFileFormat/gdcmPrinter.h +++ b/Source/MediaStorageAndFileFormat/gdcmPrinter.h @@ -60,7 +60,7 @@ class GDCM_EXPORT Printer { public: Printer(); - ~Printer(); + ~Printer() = default; /// Set file void SetFile(File const &f) { F = &f; } diff --git a/Source/MediaStorageAndFileFormat/gdcmRAWCodec.cxx b/Source/MediaStorageAndFileFormat/gdcmRAWCodec.cxx index cc7616ecdc4..19f73939994 100644 --- a/Source/MediaStorageAndFileFormat/gdcmRAWCodec.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmRAWCodec.cxx @@ -120,7 +120,7 @@ bool RAWCodec::DecodeBytes(const char* inBytes, size_t inBufferLength, { size_t len = str.size() * 16 / 12; char * copy = new char[len]; - bool b = Unpacker12Bits::Unpack(copy, &str[0], str.size() ); (void)b; + bool b = Unpacker12Bits::Unpack(copy, str.data(), str.size() ); (void)b; assert( b ); assert (len == inOutBufferLength); assert(inOutBufferLength == len); @@ -176,7 +176,7 @@ bool RAWCodec::Decode(DataElement const &in, DataElement &out) { size_t len = str.size() * 16 / 12; char * copy = new char[len];//why use an array, and not a vector? - bool b = Unpacker12Bits::Unpack(copy, &str[0], str.size() ); + bool b = Unpacker12Bits::Unpack(copy, str.data(), str.size() ); assert( b ); (void)b; VL::Type lenSize = (VL::Type)len; @@ -188,7 +188,7 @@ bool RAWCodec::Decode(DataElement const &in, DataElement &out) else { VL::Type strSize = (VL::Type) str.size(); - out.SetByteValue( &str[0], strSize); + out.SetByteValue( str.data(), strSize); } return r; diff --git a/Source/MediaStorageAndFileFormat/gdcmRLECodec.cxx b/Source/MediaStorageAndFileFormat/gdcmRLECodec.cxx index ccb7d7261bf..38c77852fb3 100644 --- a/Source/MediaStorageAndFileFormat/gdcmRLECodec.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmRLECodec.cxx @@ -20,10 +20,10 @@ #include "gdcmSmartPointer.h" #include "gdcmSwapper.h" -#include #include // req C++11 -#include // ptrdiff_t fix +#include // ptrdiff_t fix #include +#include #include @@ -531,11 +531,11 @@ bool RLECodec::Code(DataElement const &in, DataElement &out) //header.Print( std::cout ); os.write((char*)&header,sizeof(header)); std::string str = os.str() + datastr; - assert( str.size() ); + assert( !str.empty() ); Fragment frag; //frag.SetTag( itemStart ); VL::Type strSize = (VL::Type)str.size(); - frag.SetByteValue( &str[0], strSize ); + frag.SetByteValue( str.data(), strSize ); sq->AddFragment( frag ); } out.SetValue( *sq ); @@ -624,7 +624,7 @@ bool RLECodec::Decode(DataElement const &in, DataElement &out) std::string::size_type check = str.size(); assert( check == len ); VL::Type checkCast = (VL::Type)check; - out.SetByteValue( &str[0], checkCast ); + out.SetByteValue( str.data(), checkCast ); return true; } else if ( NumberOfDimensions == 3 ) @@ -735,7 +735,7 @@ bool RLECodec::DecodeExtent( std::vector buffer1; buffer1.resize( rowsize*bytesPerPixel ); - char *tmpBuffer1 = &buffer1[0]; + char *tmpBuffer1 = buffer1.data(); unsigned int y, z; std::streamoff theOffset; for (z = zmin; z <= zmax; ++z) @@ -771,8 +771,6 @@ bool RLECodec::DecodeByStreams(std::istream &is, std::ostream &os) return false; unsigned long numSegments = frame.Header.NumSegments; - unsigned long numberOfReadBytes = 0; - unsigned long length = Length; assert( length ); // Special case: @@ -801,7 +799,7 @@ bool RLECodec::DecodeByStreams(std::istream &is, std::ostream &os) length /= numSegments; for(unsigned long i = 0; i #include // std::max -#include // abort -#include // memcpy #include // std::lround +#include // abort +#include // memcpy +#include namespace gdcm { diff --git a/Source/MediaStorageAndFileFormat/gdcmRescaler.h b/Source/MediaStorageAndFileFormat/gdcmRescaler.h index 0410e650eef..1853b42f63e 100644 --- a/Source/MediaStorageAndFileFormat/gdcmRescaler.h +++ b/Source/MediaStorageAndFileFormat/gdcmRescaler.h @@ -88,7 +88,7 @@ class GDCM_EXPORT Rescaler /// By default (when UseTargetPixelType is false), a best /// matching Target Pixel Type is computed. However user can override /// this auto selection by switching UseTargetPixelType:true and - /// also specifying the specifix Target Pixel Type + /// also specifying the specific Target Pixel Type void SetTargetPixelType( PixelFormat const & targetst ); /// Override default behavior of Rescale diff --git a/Source/MediaStorageAndFileFormat/gdcmScanner2.cxx b/Source/MediaStorageAndFileFormat/gdcmScanner2.cxx new file mode 100644 index 00000000000..516900ff712 --- /dev/null +++ b/Source/MediaStorageAndFileFormat/gdcmScanner2.cxx @@ -0,0 +1,612 @@ +/*========================================================================= + + Program: GDCM (Grassroots DICOM). A DICOM library + + Copyright (c) 2006-2011 Mathieu Malaterre + All rights reserved. + See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "gdcmScanner2.h" +#include "gdcmReader.h" +#include "gdcmGlobal.h" +#include "gdcmDicts.h" +#include "gdcmDict.h" +#include "gdcmDictEntry.h" +#include "gdcmStringFilter.h" +#include "gdcmProgressEvent.h" +#include "gdcmFileNameEvent.h" + +#include // std::find + +namespace gdcm +{ + +Scanner2::~Scanner2() = default; + +void Scanner2::ClearPublicTags() +{ + PublicTags.clear(); +} + +void Scanner2::ClearPrivateTags() +{ + PrivateTags.clear(); +} + +void Scanner2::ClearSkipTags() +{ + SkipTags.clear(); +} + +bool Scanner2::AddSkipTag( Tag const & t ) +{ + SkipTags.insert( t ); + return true; +} + +bool Scanner2::AddPrivateTag( PrivateTag const & t ) +{ + if( !( t.IsPrivate() && t.GetOwner() && *t.GetOwner() ) ) return false; + // Do not check IsIllegal at this point + static const Global &g = GlobalInstance; + static const Dicts &dicts = g.GetDicts(); + const DictEntry &entry = dicts.GetDictEntry( t ); + // Is this tag an ASCII on ? + if( entry.GetVR() & VR::VRASCII ) + { + PrivateTags.insert( t ); + } + else if( entry.GetVR() == VR::INVALID ) + { + gdcmWarningMacro( "Only tag with known VR are allowed. Tag " << t << " will be discarded" ); + } + else + { + assert( entry.GetVR() & VR::VRBINARY ); + //gdcmWarningMacro( "Only ASCII VR are supported for now. Tag " << t << " will be discarded" ); + PrivateTags.insert( t ); + } + return true; +} + +bool Scanner2::AddPublicTag( Tag const & t ) +{ + if( !t.IsPublic() && !t.IsPrivateCreator() ) return false; + if( t.IsIllegal() ) return false; + static const Global &g = GlobalInstance; + static const Dicts &dicts = g.GetDicts(); + const DictEntry &entry = dicts.GetDictEntry( t ); + // Is this tag an ASCII on ? + if( entry.GetVR() & VR::VRASCII ) + { + PublicTags.insert( t ); + } + else if( entry.GetVR() == VR::INVALID ) + { + gdcmWarningMacro( "Only tag with known VR are allowed. Tag " << t << " will be discarded" ); + } + else + { + assert( entry.GetVR() & VR::VRBINARY ); + //gdcmWarningMacro( "Only ASCII VR are supported for now. Tag " << t << " will be discarded" ); + PublicTags.insert( t ); + } + return true; +} + +bool Scanner2::Scan( Directory::FilenamesType const & filenames ) +{ + this->InvokeEvent( StartEvent() ); + + // Is there at least one tag ? + if( !PublicTags.empty() || !PrivateTags.empty() ) + { + // Prepare hash tables: + PublicMappings.clear(); + PublicMappings[""]; // Create a fake table for dummy file + PrivateMappings.clear(); + PrivateMappings[""]; // Create a fake table for dummy file + + // Make our own copy: + Filenames = filenames; + + // Find the tag with the highest value (get the one from the end of the std::set) + Tag last(0x0,0x0); + if( !PublicTags.empty() ) + { + PublicTagsType::const_reverse_iterator it1 = PublicTags.rbegin(); + const Tag & publiclast = *it1; + last = publiclast; + } + if( !PrivateTags.empty() ) + { + PrivateTagsType::const_reverse_iterator pit1 = PrivateTags.rbegin(); + Tag privatelast = *pit1; + // at this point we do not know the private creator, since it can go up + // to 0xff, simply read up to the next public group (simple logic). + privatelast.SetGroup( privatelast.GetGroup() + 1 ); + privatelast.SetElement( 0x0 ); + if( last < privatelast ) last = privatelast; + } + + StringFilter sf; + Directory::FilenamesType::const_iterator it = Filenames.begin(); + const double progresstick = 1. / (double)Filenames.size(); + Progress = 0; + for(; it != Filenames.end(); ++it) + { + Reader reader; + const char *filename = it->c_str(); + assert( filename ); + reader.SetFileName( filename ); + bool read = false; + try + { + // Start reading all tags, including the 'last' one: + read = reader.ReadUpToTag(last, SkipTags); + } + catch(std::exception & ex) + { + (void)ex; + gdcmWarningMacro( "Failed to read:" << filename << " with ex:" << ex.what() ); + } + catch(...) + { + gdcmWarningMacro( "Failed to read:" << filename << " with unknown error" ); + } + if( read ) + { + // Keep the mapping: + sf.SetFile( reader.GetFile() ); + Scanner2::ProcessPublicTag(sf, filename); + Scanner2::ProcessPrivateTag(sf, filename); + } + // Update progress + Progress += progresstick; + ProgressEvent pe; + pe.SetProgress( Progress ); + this->InvokeEvent( pe ); + // For outside application tell which file is being processed: + FileNameEvent fe( filename ); + this->InvokeEvent( fe ); + } + } + + this->InvokeEvent( EndEvent() ); + return true; +} + +void Scanner2::Print( std::ostream & os ) const +{ + os << "Values:\n"; + for(ValuesType::const_iterator it = Values.begin() ; it != Values.end(); + ++it) + { + os << *it << "\n"; + } + os << "Mapping:\n"; + Directory::FilenamesType::const_iterator file = Filenames.begin(); + for(; file != Filenames.end(); ++file) + { + const char *filename = file->c_str(); + assert( filename && *filename ); + bool b = IsKey(filename); + const char *comment = !b ? "could not be read" : "could be read"; + os << "Filename: " << filename << " (" << comment << ")\n"; + if( PublicMappings.find(filename) != PublicMappings.end() ) + { + const PublicTagToValue &mapping = GetPublicMapping(filename); + PublicTagToValue::const_iterator it = mapping.begin(); + for( ; it != mapping.end(); ++it) + { + const Tag & tag = it->first; + const char *value = it->second; + os << tag << " -> [" << value << "]\n"; + } + } + if( PrivateMappings.find(filename) != PrivateMappings.end() ) + { + const PrivateTagToValue &mapping = GetPrivateMapping(filename); + PrivateTagToValue::const_iterator it = mapping.begin(); + for( ; it != mapping.end(); ++it) + { + const PrivateTag & tag = it->first; + const char *value = it->second; + os << tag << " -> [" << value << "]\n"; + } + } + } +} + +static bool IsVRUI(Tag const &tag) +{ + static const Global &g = Global::GetInstance(); + static const Dicts &dicts = g.GetDicts(); + const DictEntry &dictentry = dicts.GetDictEntry(tag); + if( dictentry.GetVR() == VR::UI ) return true; + return false; +} + +static bool IsVRUI(PrivateTag const &tag) +{ + static const Global &g = Global::GetInstance(); + static const Dicts &dicts = g.GetDicts(); + const DictEntry &dictentry = dicts.GetDictEntry(tag); + if( dictentry.GetVR() == VR::UI ) return true; + return false; +} + + +void Scanner2::PrintTable( std::ostream & os, bool header ) const +{ + if( header ) { + os << "\"Filename\"" << "\t"; + { + PublicTagsType::const_iterator tag = PublicTags.begin(); + for( ; tag != PublicTags.end(); ++tag ) + { + const Tag &t = *tag; + os << '"' << t << '"'; + os << "\t"; + } + } + { + PrivateTagsType::const_iterator tag = PrivateTags.begin(); + for( ; tag != PrivateTags.end(); ++tag ) + { + const PrivateTag &t = *tag; + os << '"' << t << '"'; + os << "\t"; + } + } + os << "\n"; + } + Directory::FilenamesType::const_iterator file = Filenames.begin(); + for(; file != Filenames.end(); ++file) + { + const char *filename = file->c_str(); + assert( filename && *filename ); + os << '"' << filename << '"' << "\t"; + { + PublicTagsType::const_iterator tag = PublicTags.begin(); + const PublicTagToValue &mapping = GetPublicMapping(filename); + for( ; tag != PublicTags.end(); ++tag ) + { + const Tag &t = *tag; + bool isui = IsVRUI(t); + const char *value = ""; + if( mapping.find(t) != mapping.end() ) { + const char * v = mapping.find(t)->second; + if(v) value = v; + } + os << '"' << (isui ? String<>::Trim( value ) : value) << '"'; + os << "\t"; + } + } + { + PrivateTagsType::const_iterator tag = PrivateTags.begin(); + const PrivateTagToValue &mapping = GetPrivateMapping(filename); + for( ; tag != PrivateTags.end(); ++tag ) + { + const PrivateTag &t = *tag; + bool isui = IsVRUI(t); + const char *value = ""; + if( mapping.find(t) != mapping.end() ) { + const char * v = mapping.find(t)->second; + if(v) value = v; + } + os << '"' << (isui ? String<>::Trim( value ) : value) << '"'; + os << "\t"; + } + } + os << "\n"; + } +} + +Scanner2::PublicTagToValue const & Scanner2::GetPublicMapping(const char *filename) const +{ + assert( filename && *filename ); + if( PublicMappings.find(filename) != PublicMappings.end() ) + return PublicMappings.find(filename)->second; + return PublicMappings.find("")->second; // dummy file could not be found +} + +Scanner2::PrivateTagToValue const & Scanner2::GetPrivateMapping(const char *filename) const +{ + assert( filename && *filename ); + if( PrivateMappings.find(filename) != PrivateMappings.end() ) + return PrivateMappings.find(filename)->second; + return PrivateMappings.find("")->second; // dummy file could not be found +} + +bool Scanner2::IsKey( const char * filename ) const +{ + // Look for the file in Mappings tables: + assert( filename && *filename ); + PublicMappingType::const_iterator it2 = PublicMappings.find(filename); + PrivateMappingType::const_iterator it3 = PrivateMappings.find(filename); + return it2 != PublicMappings.end() || it3 != PrivateMappings.end(); +} + +Directory::FilenamesType Scanner2::GetKeys() const +{ + Directory::FilenamesType keys; + + Directory::FilenamesType::const_iterator file = Filenames.begin(); + for(; file != Filenames.end(); ++file) + { + const char *filename = file->c_str(); + if( IsKey( filename ) ) + { + keys.push_back( filename ); + } + } + assert( keys.size() <= Filenames.size() ); + return keys; +} + +const char* Scanner2::GetPublicValue(const char *filename, Tag const &t) const +{ + // \precondition + assert( PublicTags.find( t ) != PublicTags.end() ); + PublicTagToValue const &ftv = GetPublicMapping(filename); + if( ftv.find(t) != ftv.end() ) + { + return ftv.find(t)->second; + } + return nullptr; +} + +const char* Scanner2::GetPrivateValue(const char *filename, PrivateTag const &t) const +{ + // \precondition + assert( PrivateTags.find( t ) != PrivateTags.end() ); + PrivateTagToValue const &ftv = GetPrivateMapping(filename); + if( ftv.find(t) != ftv.end() ) + { + return ftv.find(t)->second; + } + return nullptr; +} + +const char *Scanner2::GetFilenameFromPublicTagToValue(Tag const &t, const char *valueref) const +{ + const char *filenameref = nullptr; + if( valueref ) + { + Directory::FilenamesType::const_iterator file = Filenames.begin(); + const std::string valueref_str = String<>::Trim( valueref ); + for(; file != Filenames.end() && !filenameref; ++file) + { + const char *filename = file->c_str(); + const char * value = GetPublicValue(filename, t); + if( value && valueref == value ) + { + filenameref = filename; + } + } + } + return filenameref; +} + +const char *Scanner2::GetFilenameFromPrivateTagToValue(PrivateTag const &pt, const char *valueref) const +{ + const char *filenameref = nullptr; + if( valueref ) + { + Directory::FilenamesType::const_iterator file = Filenames.begin(); + const std::string valueref_str = String<>::Trim( valueref ); + for(; file != Filenames.end() && !filenameref; ++file) + { + const char *filename = file->c_str(); + const char * value = GetPrivateValue(filename, pt); + if( value && valueref_str == value ) + { + filenameref = filename; + } + } + } + return filenameref; +} + + + +/// Will loop over all files and return a vector of std::strings of filenames +/// where value match the reference value 'valueref' +Directory::FilenamesType Scanner2::GetAllFilenamesFromPublicTagToValue(Tag const &t, const char *valueref) const +{ + Directory::FilenamesType theReturn; + if( valueref ) + { + const std::string valueref_str = String<>::Trim( valueref ); + Directory::FilenamesType::const_iterator file = Filenames.begin(); + for(; file != Filenames.end(); ++file) + { + const char *filename = file->c_str(); + const char * value = GetPublicValue(filename, t); + if( value && valueref_str == value ) + { + theReturn.push_back( filename ); + } + } + } + return theReturn; +} + +Directory::FilenamesType Scanner2::GetAllFilenamesFromPrivateTagToValue(PrivateTag const &pt, const char *valueref) const +{ + Directory::FilenamesType theReturn; + if( valueref ) + { + const std::string valueref_str = String<>::Trim( valueref ); + Directory::FilenamesType::const_iterator file = Filenames.begin(); + for(; file != Filenames.end(); ++file) + { + const char *filename = file->c_str(); + const char * value = GetPrivateValue(filename, pt); + if( value && valueref_str == value ) + { + theReturn.push_back( filename ); + } + } + } + return theReturn; +} + +Scanner2::PublicTagToValue const & Scanner2::GetMappingFromPublicTagToValue(Tag const &t, const char *valueref) const +{ + return GetPublicMapping( GetFilenameFromPublicTagToValue(t, valueref) ); +} + +Scanner2::PrivateTagToValue const & Scanner2::GetMappingFromPrivateTagToValue(PrivateTag const &pt, const char *valueref) const +{ + return GetPrivateMapping( GetFilenameFromPrivateTagToValue(pt, valueref) ); +} + +Scanner2::ValuesType Scanner2::GetPublicValues(Tag const &t) const +{ + ValuesType vt; + Directory::FilenamesType::const_iterator file = Filenames.begin(); + for(; file != Filenames.end(); ++file) + { + const char *filename = file->c_str(); + PublicTagToValue const &ttv = GetPublicMapping(filename); + if( ttv.find(t) != ttv.end() ) + { + vt.insert( ttv.find(t)->second ); + } + } + return vt; +} + +Scanner2::ValuesType Scanner2::GetPrivateValues(PrivateTag const &pt) const +{ + ValuesType vt; + Directory::FilenamesType::const_iterator file = Filenames.begin(); + for(; file != Filenames.end(); ++file) + { + const char *filename = file->c_str(); + PrivateTagToValue const &ttv = GetPrivateMapping(filename); + if( ttv.find(pt) != ttv.end() ) + { + vt.insert( ttv.find(pt)->second ); + } + } + return vt; +} + +Directory::FilenamesType Scanner2::GetPublicOrderedValues(Tag const &t) const +{ + Directory::FilenamesType theReturn; + Directory::FilenamesType::const_iterator file = Filenames.begin(); + for(; file != Filenames.end(); ++file) + { + const char *filename = file->c_str(); + PublicTagToValue const &ttv = GetPublicMapping(filename); + if( ttv.find(t) != ttv.end() ) + { + std::string theVal = std::string(ttv.find(t)->second); + if (std::find(theReturn.begin(), theReturn.end(), theVal) == theReturn.end()){ + theReturn.push_back( theVal );//only add new tags to the list + } + } + } + return theReturn; +} + +Directory::FilenamesType Scanner2::GetPrivateOrderedValues(PrivateTag const &pt) const +{ + Directory::FilenamesType theReturn; + Directory::FilenamesType::const_iterator file = Filenames.begin(); + for(; file != Filenames.end(); ++file) + { + const char *filename = file->c_str(); + PrivateTagToValue const &ttv = GetPrivateMapping(filename); + if( ttv.find(pt) != ttv.end() ) + { + std::string theVal = std::string(ttv.find(pt)->second); + if (std::find(theReturn.begin(), theReturn.end(), theVal) == theReturn.end()){ + theReturn.push_back( theVal );//only add new tags to the list + } + } + } + return theReturn; +} + +void Scanner2::ProcessPublicTag(StringFilter &sf, const char *filename) +{ + assert( filename ); + PublicTagToValue &mapping = PublicMappings[filename]; + const File& file = sf.GetFile(); + + const FileMetaInformation & header = file.GetHeader(); + const DataSet & ds = file.GetDataSet(); + PublicTagsType::const_iterator tag = PublicTags.begin(); + for( ; tag != PublicTags.end(); ++tag ) + { + if( tag->GetGroup() == 0x0002 ) + { + if( header.FindDataElement( *tag ) ) + { + DataElement const & de = header.GetDataElement( *tag ); + std::string s = sf.ToString(de.GetTag()); + + // Store the potentially new value: + Values.insert( s ); + assert( Values.find( s ) != Values.end() ); + const char *value = Values.find( s )->c_str(); + assert( value ); + mapping.insert( + PublicTagToValue::value_type(*tag, value)); + } + } + else + { + if( ds.FindDataElement( *tag ) ) + { + DataElement const & de = ds.GetDataElement( *tag ); + std::string s = sf.ToString(de.GetTag()); + + // Store the potentially new value: + Values.insert( s ); + assert( Values.find( s ) != Values.end() ); + const char *value = Values.find( s )->c_str(); + assert( value ); + mapping.insert( + PublicTagToValue::value_type(*tag, value)); + } + } + } // end for +} + +void Scanner2::ProcessPrivateTag(StringFilter &sf, const char *filename) +{ + assert( filename ); + PrivateTagToValue &mapping = PrivateMappings[filename]; + const File& file = sf.GetFile(); + const DataSet & ds = file.GetDataSet(); + PrivateTagsType::const_iterator ptag = PrivateTags.begin(); + for( ; ptag != PrivateTags.end(); ++ptag ) + { + if( ds.FindDataElement( *ptag ) ) + { + DataElement const & de = ds.GetDataElement( *ptag ); + std::string s = sf.ToString(de.GetTag()); + + // Store the potentially new value: + Values.insert( s ); + assert( Values.find( s ) != Values.end() ); + const char *value = Values.find( s )->c_str(); + assert( value ); + mapping.insert( + PrivateTagToValue::value_type(*ptag, value)); + } + } // end for +} + +} // end namespace gdcm diff --git a/Source/MediaStorageAndFileFormat/gdcmScanner2.h b/Source/MediaStorageAndFileFormat/gdcmScanner2.h new file mode 100644 index 00000000000..568bca7ce57 --- /dev/null +++ b/Source/MediaStorageAndFileFormat/gdcmScanner2.h @@ -0,0 +1,208 @@ +/*========================================================================= + + Program: GDCM (Grassroots DICOM). A DICOM library + + Copyright (c) 2006-2011 Mathieu Malaterre + All rights reserved. + See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef GDCMSCANNER2_H +#define GDCMSCANNER2_H + +#include "gdcmDirectory.h" +#include "gdcmSubject.h" +#include "gdcmTag.h" +#include "gdcmPrivateTag.h" +#include "gdcmSmartPointer.h" + +#include +#include +#include + +#include // strcmp + +namespace gdcm +{ +class StringFilter; + +/** + * \brief Scanner2 + * \details This filter is meant for quickly browsing a FileSet (a set of files on + * disk). Special consideration are taken so as to read the minimum amount of + * information in each file in order to retrieve the user specified set of + * DICOM Attribute. + * + * This filter is dealing with both VRASCII and VRBINARY element, thanks to the + * help of StringFilter + * + * \warning IMPORTANT In case of file where tags are not ordered (illegal as + * per DICOM specification), the output will be missing information + * + * \note implementation details. All values are stored in a std::set of + * std::string. Then the address of the cstring underlying the std::string is + * used in the std::map. + * + * This class implement the Subject/Observer pattern trigger the following events: + * \li ProgressEvent + * \li StartEvent + * \li EndEvent + */ +class GDCM_EXPORT Scanner2 : public Subject +{ + friend std::ostream& operator<<(std::ostream &_os, const Scanner2 &s); +public: + Scanner2():Values(),Filenames(),PublicMappings(),PrivateMappings(),Progress(0.0) {} + ~Scanner2() override; + + /// struct to map a filename to a value + /// Implementation note: + /// all std::map in this class will be using const char * and not std::string + /// since we are pointing to existing std::string (held in a std::vector) + /// this avoid an extra copy of the byte array. + /// Tag are used as Tag class since sizeof(tag) <= sizeof(pointer) + typedef std::map PublicTagToValue; + typedef PublicTagToValue::value_type PublicTagToValueValueType; + + typedef std::map PrivateTagToValue; + typedef PrivateTagToValue::value_type PrivateTagToValueValueType; + + /// Add a tag that will need to be read. Those are root level tags + bool AddPublicTag( Tag const & t ); + void ClearPublicTags(); + + // Work in progress do not use: + bool AddPrivateTag( PrivateTag const & pt ); + void ClearPrivateTags(); + + /// Add a tag that will need to be skipped. Those are root level skip tags + bool AddSkipTag( Tag const & t ); + void ClearSkipTags(); + + /// Start the scan ! + bool Scan( Directory::FilenamesType const & filenames ); + + /// Return the list of filenames + Directory::FilenamesType const &GetFilenames() const { return Filenames; } + + /// Print result + void Print( std::ostream & os ) const override; + + /// Print result as CSV table + void PrintTable( std::ostream & os, bool header = false ) const; + + /// Check if filename is a key in the Mapping table. + /// returns true only of file can be found, which means + /// the file was indeed a DICOM file that could be processed + bool IsKey( const char * filename ) const; + + /// Return the list of filename that are key in the internal map, + /// which means those filename were properly parsed + Directory::FilenamesType GetKeys() const; + + // struct to store all the values found: + typedef std::set< std::string > ValuesType; + + /// Get all the values found (in lexicographic order) + ValuesType const & GetValues() const { return Values; } + + /// Get all the values found (in lexicographic order) associated with Tag 't' + ValuesType GetPublicValues(Tag const &t) const; + + /// Get all the values found (in lexicographic order) associated with PrivateTag 'pt' + ValuesType GetPrivateValues(PrivateTag const &pt) const; + + /// Get all the values found (in a vector) associated with Tag 't' + /// This function is identical to GetValues, but is accessible from the wrapped + /// layer (python, C#, java) + Directory::FilenamesType GetPublicOrderedValues(Tag const &t) const; + + Directory::FilenamesType GetPrivateOrderedValues(PrivateTag const &pt) const; + + /* ltstr is CRITICAL, otherwise pointers value are used to do the key comparison */ + struct ltstr + { + bool operator()(const char* s1, const char* s2) const + { + assert( s1 && s2 ); + return strcmp(s1, s2) < 0; + } + }; + typedef std::map PublicMappingType; + typedef PublicMappingType::const_iterator PublicConstIterator; + PublicConstIterator Begin() const { return PublicMappings.begin(); } + PublicConstIterator End() const { return PublicMappings.end(); } + + typedef std::map PrivateMappingType; + typedef PrivateMappingType::const_iterator PrivateConstIterator; + PrivateConstIterator PrivateBegin() const { return PrivateMappings.begin(); } + PrivateConstIterator PrivateEnd() const { return PrivateMappings.end(); } + + /// Mappings are the mapping from a particular tag to the map, mapping filename to value: + PublicMappingType const & GetPublicMappings() const { return PublicMappings; } + PrivateMappingType const & GetPrivateMappings() const { return PrivateMappings; } + + /// Get the std::map mapping filenames to value for file 'filename' + PublicTagToValue const & GetPublicMapping(const char *filename) const; + PrivateTagToValue const & GetPrivateMapping(const char *filename) const; + + /// Will loop over all files and return the first file where value match the reference value + /// 'valueref' + const char *GetFilenameFromPublicTagToValue(Tag const &t, const char *valueref) const; + const char *GetFilenameFromPrivateTagToValue(PrivateTag const &pt, const char *valueref) const; + + /// Will loop over all files and return a vector of std::strings of filenames + /// where value match the reference value 'valueref' + Directory::FilenamesType GetAllFilenamesFromPublicTagToValue(Tag const &t, const char *valueref) const; + Directory::FilenamesType GetAllFilenamesFromPrivateTagToValue(PrivateTag const &pt, const char *valueref) const; + + /// See GetFilenameFromTagToValue(). This is simply GetFilenameFromTagToValue followed + // by a call to GetMapping() + PublicTagToValue const & GetMappingFromPublicTagToValue(Tag const &t, const char *value) const; + PrivateTagToValue const & GetMappingFromPrivateTagToValue(PrivateTag const &pt, const char *value) const; + + /// Retrieve the value found for tag: t associated with file: filename + /// This is meant for a single short call. If multiple calls (multiple tags) + /// should be done, prefer the GetMapping function, and then reuse the TagToValue + /// hash table. + /// \warning Tag 't' should have been added via AddTag() prior to the Scan() call ! + const char* GetPublicValue(const char *filename, Tag const &t) const; + const char* GetPrivateValue(const char *filename, PrivateTag const &t) const; + + /// for wrapped language: instantiate a reference counted object + static SmartPointer New() { return new Scanner2; } + +protected: + void ProcessPublicTag(StringFilter &sf, const char *filename); + void ProcessPrivateTag(StringFilter &sf, const char *filename); +private: + // struct to store all uniq tags in ascending order: + typedef std::set< Tag > PublicTagsType; + typedef std::set< PrivateTag > PrivateTagsType; + std::set< Tag > PublicTags; // Public and Private Creator + std::set< PrivateTag > PrivateTags; // Only Private (no Private Creator) + std::set< Tag > SkipTags; + ValuesType Values; + Directory::FilenamesType Filenames; + + // Main struct that will hold all public mapping: + PublicMappingType PublicMappings; + // Main struct that will hold all private mapping: + PrivateMappingType PrivateMappings; + + double Progress; +}; +//----------------------------------------------------------------------------- +inline std::ostream& operator<<(std::ostream &os, const Scanner2 &s) +{ + s.Print( os ); + return os; +} + +} // end namespace gdcm + +#endif //GDCMSCANNER2_H diff --git a/Source/MediaStorageAndFileFormat/gdcmSegment.cxx b/Source/MediaStorageAndFileFormat/gdcmSegment.cxx index 5f1e1ff837b..e3f1ed38c37 100644 --- a/Source/MediaStorageAndFileFormat/gdcmSegment.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmSegment.cxx @@ -69,15 +69,12 @@ Segment::ALGOType Segment::GetALGOType(const char * type) Segment::Segment(): SegmentNumber(0), - SegmentLabel(""), - SegmentDescription(""), AnatomicRegion(), AnatomicRegionModifiers(), PropertyCategory(), PropertyType(), PropertyTypeModifiers(), SegmentAlgorithmType(ALGOType_END), - SegmentAlgorithmName(""), SurfaceCount(0), Surfaces() { diff --git a/Source/MediaStorageAndFileFormat/gdcmSegmentReader.cxx b/Source/MediaStorageAndFileFormat/gdcmSegmentReader.cxx index bd4e92c42f3..ee0189b90d0 100644 --- a/Source/MediaStorageAndFileFormat/gdcmSegmentReader.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmSegmentReader.cxx @@ -25,7 +25,7 @@ SegmentReader::SegmentReader() SegmentReader::~SegmentReader() = default; -const SegmentReader::SegmentVector SegmentReader::GetSegments() const +SegmentReader::SegmentVector SegmentReader::GetSegments() const { return const_cast(this)->GetSegments(); } diff --git a/Source/MediaStorageAndFileFormat/gdcmSegmentReader.h b/Source/MediaStorageAndFileFormat/gdcmSegmentReader.h index 7582e55694a..b528fc5fca0 100644 --- a/Source/MediaStorageAndFileFormat/gdcmSegmentReader.h +++ b/Source/MediaStorageAndFileFormat/gdcmSegmentReader.h @@ -41,7 +41,7 @@ class GDCM_EXPORT SegmentReader : public Reader bool Read() override; // Set to protected ? //** Segment getters/setters **// - const SegmentVector GetSegments() const; + SegmentVector GetSegments() const; SegmentVector GetSegments(); // unsigned int GetNumberOfSegments(); diff --git a/Source/MediaStorageAndFileFormat/gdcmSegmentedPaletteColorLookupTable.cxx b/Source/MediaStorageAndFileFormat/gdcmSegmentedPaletteColorLookupTable.cxx index 754a8d4b496..e033b72de9d 100644 --- a/Source/MediaStorageAndFileFormat/gdcmSegmentedPaletteColorLookupTable.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmSegmentedPaletteColorLookupTable.cxx @@ -18,6 +18,7 @@ // #include #include +#include #include #include #include @@ -87,7 +88,7 @@ namespace gdcm double value_float = static_cast(y0) + (static_cast(i)/static_cast(length)) * y01; - EntryType value_int = static_cast(value_float + 0.5); + EntryType value_int = static_cast(std::llround(value_float)); expanded.push_back(value_int); } return true; @@ -193,7 +194,7 @@ void SegmentedPaletteColorLookupTable::SetLUT(LookupTableType type, const unsign // FIXME: inplace byteswapping (BAD!) SwapperNoOp::SwapArray(const_cast(segment_values),length/2); ExpandPalette(segment_values, length, palette); - LookupTable::SetLUT(type, (unsigned char*)&palette[0], (unsigned int)(palette.size() * 2)); + LookupTable::SetLUT(type, (unsigned char*)palette.data(), (unsigned int)(palette.size() * 2)); } } diff --git a/Source/MediaStorageAndFileFormat/gdcmSerieHelper.cxx b/Source/MediaStorageAndFileFormat/gdcmSerieHelper.cxx index 7038aef857e..28f6f2556b9 100644 --- a/Source/MediaStorageAndFileFormat/gdcmSerieHelper.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmSerieHelper.cxx @@ -387,7 +387,7 @@ bool SerieHelper::ImagePositionPatientOrdering( FileList *fileList ) if (distmultimap.count((*it2).first) != 1) { gdcmErrorMacro("File: " - //<< ((*it2).second->GetFileName()) + // << ((*it2).second->GetFileName()) << " Distance: " << (*it2).first << " position is not unique"); diff --git a/Source/MediaStorageAndFileFormat/gdcmSpacing.cxx b/Source/MediaStorageAndFileFormat/gdcmSpacing.cxx index 3d49cc3c688..e2622a173b4 100644 --- a/Source/MediaStorageAndFileFormat/gdcmSpacing.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmSpacing.cxx @@ -18,8 +18,6 @@ namespace gdcm Spacing::Spacing() = default; -Spacing::~Spacing() = default; - /* * http://www.ics.uci.edu/~eppstein/numth/frap.c * http://stackoverflow.com/questions/95727/how-to-convert-floats-to-human-readable-fractions diff --git a/Source/MediaStorageAndFileFormat/gdcmSpacing.h b/Source/MediaStorageAndFileFormat/gdcmSpacing.h index f71299ab616..bec72d4452d 100644 --- a/Source/MediaStorageAndFileFormat/gdcmSpacing.h +++ b/Source/MediaStorageAndFileFormat/gdcmSpacing.h @@ -86,7 +86,7 @@ class GDCM_EXPORT Spacing { public : Spacing(); - ~Spacing(); + ~Spacing() = default; // Here are the list of spacing we support: // (0018,0088) DS [1.500000] # 8,1 Spacing Between Slices diff --git a/Source/MediaStorageAndFileFormat/gdcmSplitMosaicFilter.cxx b/Source/MediaStorageAndFileFormat/gdcmSplitMosaicFilter.cxx index c33e1e25f3e..d3c43ebf872 100644 --- a/Source/MediaStorageAndFileFormat/gdcmSplitMosaicFilter.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmSplitMosaicFilter.cxx @@ -17,7 +17,7 @@ #include "gdcmImageHelper.h" #include "gdcmDirectionCosines.h" -#include +#include namespace gdcm { @@ -31,11 +31,11 @@ namespace details { static bool reorganize_mosaic(const unsigned short *input, const unsigned int *inputdims, unsigned int square, const unsigned int *outputdims, unsigned short *output ) { - for(unsigned int x = 0; x < outputdims[0]; ++x) + for(unsigned int z = 0; z < outputdims[2]; ++z) { for(unsigned int y = 0; y < outputdims[1]; ++y) { - for(unsigned int z = 0; z < outputdims[2]; ++z) + for(unsigned int x = 0; x < outputdims[0]; ++x) { const size_t outputidx = x + y*outputdims[0] + z*outputdims[0]*outputdims[1]; const size_t inputidx = (x + (z%square)*outputdims[0]) + @@ -50,11 +50,11 @@ static bool reorganize_mosaic(const unsigned short *input, const unsigned int *i static bool reorganize_mosaic_invert(const unsigned short *input, const unsigned int *inputdims, unsigned int square, const unsigned int *outputdims, unsigned short *output ) { - for(unsigned int x = 0; x < outputdims[0]; ++x) + for(unsigned int z = 0; z < outputdims[2]; ++z) { for(unsigned int y = 0; y < outputdims[1]; ++y) { - for(unsigned int z = 0; z < outputdims[2]; ++z) + for(unsigned int x = 0; x < outputdims[0]; ++x) { const size_t outputidx = x + y*outputdims[0] + (outputdims[2]-1-z)*outputdims[0]*outputdims[1]; const size_t inputidx = (x + (z%square)*outputdims[0]) + @@ -368,7 +368,7 @@ bool SplitMosaicFilter::Split() unsigned long l = inputimage.GetBufferLength(); std::vector buf; buf.resize(l); - inputimage.GetBuffer( &buf[0] ); + inputimage.GetBuffer( buf.data() ); DataElement pixeldata( Tag(0x7fe0,0x0010) ); std::vector outbuf; @@ -378,19 +378,19 @@ bool SplitMosaicFilter::Split() if( inverted ) { b = details::reorganize_mosaic_invert( - (unsigned short*)(void*)&buf[0], inputimage.GetDimensions(), div, dims, - (unsigned short*)(void*)&outbuf[0] ); + (unsigned short*)(void*)buf.data(), inputimage.GetDimensions(), div, dims, + (unsigned short*)(void*)outbuf.data() ); } else { b = details::reorganize_mosaic( - (unsigned short*)(void*)&buf[0], inputimage.GetDimensions(), div, dims, - (unsigned short*)(void*)&outbuf[0] ); + (unsigned short*)(void*)buf.data(), inputimage.GetDimensions(), div, dims, + (unsigned short*)(void*)outbuf.data() ); } if( !b ) return false; VL::Type outbufSize = (VL::Type)outbuf.size(); - pixeldata.SetByteValue( &outbuf[0], outbufSize ); + pixeldata.SetByteValue( outbuf.data(), outbufSize ); Image &image = GetImage(); const TransferSyntax &ts = image.GetTransferSyntax(); @@ -398,7 +398,7 @@ bool SplitMosaicFilter::Split() { image.SetTransferSyntax( TransferSyntax::ExplicitVRLittleEndian ); } - else + else { image.SetTransferSyntax( TransferSyntax::ImplicitVRLittleEndian ); } @@ -409,7 +409,7 @@ bool SplitMosaicFilter::Split() // Fix origin (direction is ok since we reorganize the tiles): if( hasOriginCSA ) - image.SetOrigin( origin ); + image.SetOrigin( origin ); PhotometricInterpretation pi; pi = PhotometricInterpretation::MONOCHROME2; diff --git a/Source/MediaStorageAndFileFormat/gdcmStrictScanner2.cxx b/Source/MediaStorageAndFileFormat/gdcmStrictScanner2.cxx new file mode 100644 index 00000000000..f8754c96ce0 --- /dev/null +++ b/Source/MediaStorageAndFileFormat/gdcmStrictScanner2.cxx @@ -0,0 +1,621 @@ +/*========================================================================= + + Program: GDCM (Grassroots DICOM). A DICOM library + + Copyright (c) 2006-2011 Mathieu Malaterre + All rights reserved. + See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "gdcmStrictScanner2.h" +#include "gdcmReader.h" +#include "gdcmGlobal.h" +#include "gdcmDicts.h" +#include "gdcmDict.h" +#include "gdcmDictEntry.h" +#include "gdcmStringFilter.h" +#include "gdcmProgressEvent.h" +#include "gdcmFileNameEvent.h" + +#include // std::find + +namespace gdcm +{ + +StrictScanner2::~StrictScanner2() = default; + +void StrictScanner2::ClearPublicTags() +{ + PublicTags.clear(); +} + +void StrictScanner2::ClearPrivateTags() +{ + PrivateTags.clear(); +} + +void StrictScanner2::ClearSkipTags() +{ + SkipTags.clear(); +} + +bool StrictScanner2::AddSkipTag( Tag const & t ) +{ + SkipTags.insert( t ); + return true; +} + +bool StrictScanner2::AddPrivateTag( PrivateTag const & t ) +{ + if( !( t.IsPrivate() && t.GetOwner() && *t.GetOwner() ) ) return false; + if( t.IsIllegal() ) return false; + static const Global &g = GlobalInstance; + static const Dicts &dicts = g.GetDicts(); + const DictEntry &entry = dicts.GetDictEntry( t ); + // Is this tag an ASCII on ? + if( entry.GetVR() & VR::VRASCII ) + { + PrivateTags.insert( t ); + } + else if( entry.GetVR() == VR::INVALID ) + { + gdcmWarningMacro( "Only tag with known VR are allowed. Tag " << t << " will be discarded" ); + } + else + { + assert( entry.GetVR() & VR::VRBINARY ); + //gdcmWarningMacro( "Only ASCII VR are supported for now. Tag " << t << " will be discarded" ); + PrivateTags.insert( t ); + } + return true; +} + +bool StrictScanner2::AddPublicTag( Tag const & t ) +{ + if( !t.IsPublic() && !t.IsPrivateCreator() ) return false; + if( t.IsIllegal() ) return false; + static const Global &g = GlobalInstance; + static const Dicts &dicts = g.GetDicts(); + const DictEntry &entry = dicts.GetDictEntry( t ); + // Is this tag an ASCII on ? + if( entry.GetVR() & VR::VRASCII ) + { + PublicTags.insert( t ); + } + else if( entry.GetVR() == VR::INVALID ) + { + gdcmWarningMacro( "Only tag with known VR are allowed. Tag " << t << " will be discarded" ); + } + else + { + assert( entry.GetVR() & VR::VRBINARY ); + //gdcmWarningMacro( "Only ASCII VR are supported for now. Tag " << t << " will be discarded" ); + PublicTags.insert( t ); + } + return true; +} + +// see gdcmReader.strict.cxx +bool StrictReadUpToTag( const char * filename, Tag const & last, std::set const & skiptags ); + +bool StrictScanner2::Scan( Directory::FilenamesType const & filenames ) +{ + this->InvokeEvent( StartEvent() ); + + // Is there at least one tag ? + if( !PublicTags.empty() || !PrivateTags.empty() ) + { + // Prepare hash tables: + PublicMappings.clear(); + PublicMappings[""]; // Create a fake table for dummy file + PrivateMappings.clear(); + PrivateMappings[""]; // Create a fake table for dummy file + + // Make our own copy: + Filenames = filenames; + + // Find the tag with the highest value (get the one from the end of the std::set) + Tag last(0x0,0x0); + if( !PublicTags.empty() ) + { + PublicTagsType::const_reverse_iterator it1 = PublicTags.rbegin(); + const Tag & publiclast = *it1; + last = publiclast; + } + if( !PrivateTags.empty() ) + { + PrivateTagsType::const_reverse_iterator pit1 = PrivateTags.rbegin(); + Tag privatelast = *pit1; + // at this point we do not know the private creator, since it can go up + // to 0xff, simply read up to the next public group (simple logic). + privatelast.SetGroup( privatelast.GetGroup() + 1 ); + privatelast.SetElement( 0x0 ); + if( last < privatelast ) last = privatelast; + } + + StringFilter sf; + Directory::FilenamesType::const_iterator it = Filenames.begin(); + const double progresstick = 1. / (double)Filenames.size(); + Progress = 0; + for(; it != Filenames.end(); ++it) + { + Reader reader; + const char *filename = it->c_str(); + assert( filename ); + reader.SetFileName( filename ); + // Pass #1, just check if the file is valid (up to the tag) + const bool strict = StrictReadUpToTag( filename, last, SkipTags ); + if( strict ) + { + // Pass #2, syntax is ok, retrieve data now: + bool read = false; + try + { + // Start reading all tags, including the 'last' one: + read = reader.ReadUpToTag(last, SkipTags); + } + catch(std::exception & ex) + { + (void)ex; + gdcmWarningMacro( "Failed to read:" << filename << " with ex:" << ex.what() ); + } + catch(...) + { + gdcmWarningMacro( "Failed to read:" << filename << " with unknown error" ); + } + if( read ) + { + // Keep the mapping: + sf.SetFile( reader.GetFile() ); + StrictScanner2::ProcessPublicTag(sf, filename); + StrictScanner2::ProcessPrivateTag(sf, filename); + } + } + // Update progress + Progress += progresstick; + ProgressEvent pe; + pe.SetProgress( Progress ); + this->InvokeEvent( pe ); + // For outside application tell which file is being processed: + FileNameEvent fe( filename ); + this->InvokeEvent( fe ); + } + } + + this->InvokeEvent( EndEvent() ); + return true; +} + +void StrictScanner2::Print( std::ostream & os ) const +{ + os << "Values:\n"; + for(ValuesType::const_iterator it = Values.begin() ; it != Values.end(); + ++it) + { + os << *it << "\n"; + } + os << "Mapping:\n"; + Directory::FilenamesType::const_iterator file = Filenames.begin(); + for(; file != Filenames.end(); ++file) + { + const char *filename = file->c_str(); + assert( filename && *filename ); + bool b = IsKey(filename); + const char *comment = !b ? "could not be read" : "could be read"; + os << "Filename: " << filename << " (" << comment << ")\n"; + if( PublicMappings.find(filename) != PublicMappings.end() ) + { + const PublicTagToValue &mapping = GetPublicMapping(filename); + PublicTagToValue::const_iterator it = mapping.begin(); + for( ; it != mapping.end(); ++it) + { + const Tag & tag = it->first; + const char *value = it->second; + os << tag << " -> [" << value << "]\n"; + } + } + if( PrivateMappings.find(filename) != PrivateMappings.end() ) + { + const PrivateTagToValue &mapping = GetPrivateMapping(filename); + PrivateTagToValue::const_iterator it = mapping.begin(); + for( ; it != mapping.end(); ++it) + { + const PrivateTag & tag = it->first; + const char *value = it->second; + os << tag << " -> [" << value << "]\n"; + } + } + } +} + +static bool IsVRUI(Tag const &tag) +{ + static const Global &g = Global::GetInstance(); + static const Dicts &dicts = g.GetDicts(); + const DictEntry &dictentry = dicts.GetDictEntry(tag); + if( dictentry.GetVR() == VR::UI ) return true; + return false; +} + +static bool IsVRUI(PrivateTag const &tag) +{ + static const Global &g = Global::GetInstance(); + static const Dicts &dicts = g.GetDicts(); + const DictEntry &dictentry = dicts.GetDictEntry(tag); + if( dictentry.GetVR() == VR::UI ) return true; + return false; +} + + +void StrictScanner2::PrintTable( std::ostream & os, bool header ) const +{ + if( header ) { + os << "\"Filename\"" << "\t"; + { + PublicTagsType::const_iterator tag = PublicTags.begin(); + for( ; tag != PublicTags.end(); ++tag ) + { + const Tag &t = *tag; + os << '"' << t << '"'; + os << "\t"; + } + } + { + PrivateTagsType::const_iterator tag = PrivateTags.begin(); + for( ; tag != PrivateTags.end(); ++tag ) + { + const PrivateTag &t = *tag; + os << '"' << t << '"'; + os << "\t"; + } + } + os << "\n"; + } + Directory::FilenamesType::const_iterator file = Filenames.begin(); + for(; file != Filenames.end(); ++file) + { + const char *filename = file->c_str(); + assert( filename && *filename ); + os << '"' << filename << '"' << "\t"; + { + PublicTagsType::const_iterator tag = PublicTags.begin(); + const PublicTagToValue &mapping = GetPublicMapping(filename); + for( ; tag != PublicTags.end(); ++tag ) + { + const Tag &t = *tag; + bool isui = IsVRUI(t); + const char *value = ""; + if( mapping.find(t) != mapping.end() ) { + const char * v = mapping.find(t)->second; + if(v) value = v; + } + os << '"' << (isui ? String<>::Trim( value ) : value) << '"'; + os << "\t"; + } + } + { + PrivateTagsType::const_iterator tag = PrivateTags.begin(); + const PrivateTagToValue &mapping = GetPrivateMapping(filename); + for( ; tag != PrivateTags.end(); ++tag ) + { + const PrivateTag &t = *tag; + bool isui = IsVRUI(t); + const char *value = ""; + if( mapping.find(t) != mapping.end() ) { + const char * v = mapping.find(t)->second; + if(v) value = v; + } + os << '"' << (isui ? String<>::Trim( value ) : value) << '"'; + os << "\t"; + } + } + os << "\n"; + } +} + +StrictScanner2::PublicTagToValue const & StrictScanner2::GetPublicMapping(const char *filename) const +{ + assert( filename && *filename ); + if( PublicMappings.find(filename) != PublicMappings.end() ) + return PublicMappings.find(filename)->second; + return PublicMappings.find("")->second; // dummy file could not be found +} + +StrictScanner2::PrivateTagToValue const & StrictScanner2::GetPrivateMapping(const char *filename) const +{ + assert( filename && *filename ); + if( PrivateMappings.find(filename) != PrivateMappings.end() ) + return PrivateMappings.find(filename)->second; + return PrivateMappings.find("")->second; // dummy file could not be found +} + +bool StrictScanner2::IsKey( const char * filename ) const +{ + // Look for the file in Mappings tables: + assert( filename && *filename ); + PublicMappingType::const_iterator it2 = PublicMappings.find(filename); + PrivateMappingType::const_iterator it3 = PrivateMappings.find(filename); + return it2 != PublicMappings.end() || it3 != PrivateMappings.end(); +} + +Directory::FilenamesType StrictScanner2::GetKeys() const +{ + Directory::FilenamesType keys; + + Directory::FilenamesType::const_iterator file = Filenames.begin(); + for(; file != Filenames.end(); ++file) + { + const char *filename = file->c_str(); + if( IsKey( filename ) ) + { + keys.push_back( filename ); + } + } + assert( keys.size() <= Filenames.size() ); + return keys; +} + +const char* StrictScanner2::GetPublicValue(const char *filename, Tag const &t) const +{ + // \precondition + assert( PublicTags.find( t ) != PublicTags.end() ); + PublicTagToValue const &ftv = GetPublicMapping(filename); + if( ftv.find(t) != ftv.end() ) + { + return ftv.find(t)->second; + } + return nullptr; +} + +const char* StrictScanner2::GetPrivateValue(const char *filename, PrivateTag const &t) const +{ + // \precondition + assert( PrivateTags.find( t ) != PrivateTags.end() ); + PrivateTagToValue const &ftv = GetPrivateMapping(filename); + if( ftv.find(t) != ftv.end() ) + { + return ftv.find(t)->second; + } + return nullptr; +} + +const char *StrictScanner2::GetFilenameFromPublicTagToValue(Tag const &t, const char *valueref) const +{ + const char *filenameref = nullptr; + if( valueref ) + { + Directory::FilenamesType::const_iterator file = Filenames.begin(); + const std::string valueref_str = String<>::Trim( valueref ); + for(; file != Filenames.end() && !filenameref; ++file) + { + const char *filename = file->c_str(); + const char * value = GetPublicValue(filename, t); + if( value && valueref == value ) + { + filenameref = filename; + } + } + } + return filenameref; +} + +const char *StrictScanner2::GetFilenameFromPrivateTagToValue(PrivateTag const &pt, const char *valueref) const +{ + const char *filenameref = nullptr; + if( valueref ) + { + Directory::FilenamesType::const_iterator file = Filenames.begin(); + const std::string valueref_str = String<>::Trim( valueref ); + for(; file != Filenames.end() && !filenameref; ++file) + { + const char *filename = file->c_str(); + const char * value = GetPrivateValue(filename, pt); + if( value && valueref_str == value ) + { + filenameref = filename; + } + } + } + return filenameref; +} + + + +/// Will loop over all files and return a vector of std::strings of filenames +/// where value match the reference value 'valueref' +Directory::FilenamesType StrictScanner2::GetAllFilenamesFromPublicTagToValue(Tag const &t, const char *valueref) const +{ + Directory::FilenamesType theReturn; + if( valueref ) + { + const std::string valueref_str = String<>::Trim( valueref ); + Directory::FilenamesType::const_iterator file = Filenames.begin(); + for(; file != Filenames.end(); ++file) + { + const char *filename = file->c_str(); + const char * value = GetPublicValue(filename, t); + if( value && valueref_str == value ) + { + theReturn.push_back( filename ); + } + } + } + return theReturn; +} + +Directory::FilenamesType StrictScanner2::GetAllFilenamesFromPrivateTagToValue(PrivateTag const &pt, const char *valueref) const +{ + Directory::FilenamesType theReturn; + if( valueref ) + { + const std::string valueref_str = String<>::Trim( valueref ); + Directory::FilenamesType::const_iterator file = Filenames.begin(); + for(; file != Filenames.end(); ++file) + { + const char *filename = file->c_str(); + const char * value = GetPrivateValue(filename, pt); + if( value && valueref_str == value ) + { + theReturn.push_back( filename ); + } + } + } + return theReturn; +} + +StrictScanner2::PublicTagToValue const & StrictScanner2::GetMappingFromPublicTagToValue(Tag const &t, const char *valueref) const +{ + return GetPublicMapping( GetFilenameFromPublicTagToValue(t, valueref) ); +} + +StrictScanner2::PrivateTagToValue const & StrictScanner2::GetMappingFromPrivateTagToValue(PrivateTag const &pt, const char *valueref) const +{ + return GetPrivateMapping( GetFilenameFromPrivateTagToValue(pt, valueref) ); +} + +StrictScanner2::ValuesType StrictScanner2::GetPublicValues(Tag const &t) const +{ + ValuesType vt; + Directory::FilenamesType::const_iterator file = Filenames.begin(); + for(; file != Filenames.end(); ++file) + { + const char *filename = file->c_str(); + PublicTagToValue const &ttv = GetPublicMapping(filename); + if( ttv.find(t) != ttv.end() ) + { + vt.insert( ttv.find(t)->second ); + } + } + return vt; +} + +StrictScanner2::ValuesType StrictScanner2::GetPrivateValues(PrivateTag const &pt) const +{ + ValuesType vt; + Directory::FilenamesType::const_iterator file = Filenames.begin(); + for(; file != Filenames.end(); ++file) + { + const char *filename = file->c_str(); + PrivateTagToValue const &ttv = GetPrivateMapping(filename); + if( ttv.find(pt) != ttv.end() ) + { + vt.insert( ttv.find(pt)->second ); + } + } + return vt; +} + +Directory::FilenamesType StrictScanner2::GetPublicOrderedValues(Tag const &t) const +{ + Directory::FilenamesType theReturn; + Directory::FilenamesType::const_iterator file = Filenames.begin(); + for(; file != Filenames.end(); ++file) + { + const char *filename = file->c_str(); + PublicTagToValue const &ttv = GetPublicMapping(filename); + if( ttv.find(t) != ttv.end() ) + { + std::string theVal = std::string(ttv.find(t)->second); + if (std::find(theReturn.begin(), theReturn.end(), theVal) == theReturn.end()){ + theReturn.push_back( theVal );//only add new tags to the list + } + } + } + return theReturn; +} + +Directory::FilenamesType StrictScanner2::GetPrivateOrderedValues(PrivateTag const &pt) const +{ + Directory::FilenamesType theReturn; + Directory::FilenamesType::const_iterator file = Filenames.begin(); + for(; file != Filenames.end(); ++file) + { + const char *filename = file->c_str(); + PrivateTagToValue const &ttv = GetPrivateMapping(filename); + if( ttv.find(pt) != ttv.end() ) + { + std::string theVal = std::string(ttv.find(pt)->second); + if (std::find(theReturn.begin(), theReturn.end(), theVal) == theReturn.end()){ + theReturn.push_back( theVal );//only add new tags to the list + } + } + } + return theReturn; +} + +void StrictScanner2::ProcessPublicTag(StringFilter &sf, const char *filename) +{ + assert( filename ); + PublicTagToValue &mapping = PublicMappings[filename]; + const File& file = sf.GetFile(); + + const FileMetaInformation & header = file.GetHeader(); + const DataSet & ds = file.GetDataSet(); + PublicTagsType::const_iterator tag = PublicTags.begin(); + for( ; tag != PublicTags.end(); ++tag ) + { + if( tag->GetGroup() == 0x0002 ) + { + if( header.FindDataElement( *tag ) ) + { + DataElement const & de = header.GetDataElement( *tag ); + std::string s = sf.ToString(de.GetTag()); + + // Store the potentially new value: + Values.insert( s ); + assert( Values.find( s ) != Values.end() ); + const char *value = Values.find( s )->c_str(); + assert( value ); + mapping.insert( + PublicTagToValue::value_type(*tag, value)); + } + } + else + { + if( ds.FindDataElement( *tag ) ) + { + DataElement const & de = ds.GetDataElement( *tag ); + std::string s = sf.ToString(de.GetTag()); + + // Store the potentially new value: + Values.insert( s ); + assert( Values.find( s ) != Values.end() ); + const char *value = Values.find( s )->c_str(); + assert( value ); + mapping.insert( + PublicTagToValue::value_type(*tag, value)); + } + } + } // end for +} + +void StrictScanner2::ProcessPrivateTag(StringFilter &sf, const char *filename) +{ + assert( filename ); + PrivateTagToValue &mapping = PrivateMappings[filename]; + const File& file = sf.GetFile(); + const DataSet & ds = file.GetDataSet(); + PrivateTagsType::const_iterator ptag = PrivateTags.begin(); + for( ; ptag != PrivateTags.end(); ++ptag ) + { + if( ds.FindDataElement( *ptag ) ) + { + DataElement const & de = ds.GetDataElement( *ptag ); + std::string s = sf.ToString(de.GetTag()); + + // Store the potentially new value: + Values.insert( s ); + assert( Values.find( s ) != Values.end() ); + const char *value = Values.find( s )->c_str(); + assert( value ); + mapping.insert( + PrivateTagToValue::value_type(*ptag, value)); + } + } // end for +} + +} // end namespace gdcm diff --git a/Source/MediaStorageAndFileFormat/gdcmStrictScanner2.h b/Source/MediaStorageAndFileFormat/gdcmStrictScanner2.h new file mode 100644 index 00000000000..df5311eb8d7 --- /dev/null +++ b/Source/MediaStorageAndFileFormat/gdcmStrictScanner2.h @@ -0,0 +1,215 @@ +/*========================================================================= + + Program: GDCM (Grassroots DICOM). A DICOM library + + Copyright (c) 2006-2011 Mathieu Malaterre + All rights reserved. + See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef GDCMSTRICTSCANNER2_H +#define GDCMSTRICTSCANNER2_H + +#include "gdcmDirectory.h" +#include "gdcmPrivateTag.h" +#include "gdcmSmartPointer.h" +#include "gdcmSubject.h" +#include "gdcmTag.h" + +#include +#include +#include + +#include // strcmp + +namespace gdcm { +class StringFilter; + +/** + * \brief StrictScanner2 + * \details This filter is meant for quickly browsing a FileSet (a set of files + * on disk). Special consideration are taken so as to read the minimum amount of + * information in each file in order to retrieve the user specified set of + * DICOM Attribute. + * + * This filter is dealing with both VRASCII and VRBINARY element, thanks to the + * help of StringFilter + * + * \warning IMPORTANT In case of file where tags are not ordered (illegal as + * per DICOM specification), the output will be missing information + * + * \note implementation details. All values are stored in a std::set of + * std::string. Then the address of the cstring underlying the std::string is + * used in the std::map. + * + * This class implement the Subject/Observer pattern trigger the following + * events: \li ProgressEvent \li StartEvent \li EndEvent + */ +class GDCM_EXPORT StrictScanner2 : public Subject { + friend std::ostream &operator<<(std::ostream &_os, const StrictScanner2 &s); + + public: + StrictScanner2() : Values(), Filenames(), PublicMappings(), PrivateMappings(), Progress(0.0) {} + ~StrictScanner2() override; + + /// struct to map a filename to a value + /// Implementation note: + /// all std::map in this class will be using const char * and not std::string + /// since we are pointing to existing std::string (held in a std::vector) + /// this avoid an extra copy of the byte array. + /// Tag are used as Tag class since sizeof(tag) <= sizeof(pointer) + typedef std::map PublicTagToValue; + typedef PublicTagToValue::value_type PublicTagToValueValueType; + + typedef std::map PrivateTagToValue; + typedef PrivateTagToValue::value_type PrivateTagToValueValueType; + + /// Add a tag that will need to be read. Those are root level tags + bool AddPublicTag(Tag const &t); + void ClearPublicTags(); + + // Work in progress do not use: + bool AddPrivateTag(PrivateTag const &pt); + void ClearPrivateTags(); + + /// Add a tag that will need to be skipped. Those are root level skip tags + bool AddSkipTag(Tag const &t); + void ClearSkipTags(); + + /// Start the scan ! + bool Scan(Directory::FilenamesType const &filenames); + + /// Return the list of filenames + Directory::FilenamesType const &GetFilenames() const { return Filenames; } + + /// Print result + void Print(std::ostream &os) const override; + + /// Print result as CSV table + void PrintTable(std::ostream &os, bool header = false) const; + + /// Check if filename is a key in the Mapping table. + /// returns true only of file can be found, which means + /// the file was indeed a DICOM file that could be processed + bool IsKey(const char *filename) const; + + /// Return the list of filename that are key in the internal map, + /// which means those filename were properly parsed + Directory::FilenamesType GetKeys() const; + + // struct to store all the values found: + typedef std::set ValuesType; + + /// Get all the values found (in lexicographic order) + ValuesType const &GetValues() const { return Values; } + + /// Get all the values found (in lexicographic order) associated with Tag 't' + ValuesType GetPublicValues(Tag const &t) const; + + /// Get all the values found (in lexicographic order) associated with + /// PrivateTag 'pt' + ValuesType GetPrivateValues(PrivateTag const &pt) const; + + /// Get all the values found (in a vector) associated with Tag 't' + /// This function is identical to GetValues, but is accessible from the + /// wrapped layer (python, C#, java) + Directory::FilenamesType GetPublicOrderedValues(Tag const &t) const; + + Directory::FilenamesType GetPrivateOrderedValues(PrivateTag const &pt) const; + + /* ltstr is CRITICAL, otherwise pointers value are used to do the key + * comparison */ + struct ltstr { + bool operator()(const char *s1, const char *s2) const { + assert(s1 && s2); + return strcmp(s1, s2) < 0; + } + }; + typedef std::map PublicMappingType; + typedef PublicMappingType::const_iterator PublicConstIterator; + PublicConstIterator Begin() const { return PublicMappings.begin(); } + PublicConstIterator End() const { return PublicMappings.end(); } + + typedef std::map PrivateMappingType; + typedef PrivateMappingType::const_iterator PrivateConstIterator; + PrivateConstIterator PrivateBegin() const { return PrivateMappings.begin(); } + PrivateConstIterator PrivateEnd() const { return PrivateMappings.end(); } + + /// Mappings are the mapping from a particular tag to the map, mapping + /// filename to value: + PublicMappingType const &GetPublicMappings() const { return PublicMappings; } + PrivateMappingType const &GetPrivateMappings() const { + return PrivateMappings; + } + + /// Get the std::map mapping filenames to value for file 'filename' + PublicTagToValue const &GetPublicMapping(const char *filename) const; + PrivateTagToValue const &GetPrivateMapping(const char *filename) const; + + /// Will loop over all files and return the first file where value match the + /// reference value 'valueref' + const char *GetFilenameFromPublicTagToValue(Tag const &t, + const char *valueref) const; + const char *GetFilenameFromPrivateTagToValue(PrivateTag const &pt, + const char *valueref) const; + + /// Will loop over all files and return a vector of std::strings of filenames + /// where value match the reference value 'valueref' + Directory::FilenamesType GetAllFilenamesFromPublicTagToValue( + Tag const &t, const char *valueref) const; + Directory::FilenamesType GetAllFilenamesFromPrivateTagToValue( + PrivateTag const &pt, const char *valueref) const; + + /// See GetFilenameFromTagToValue(). This is simply GetFilenameFromTagToValue + /// followed + // by a call to GetMapping() + PublicTagToValue const &GetMappingFromPublicTagToValue( + Tag const &t, const char *value) const; + PrivateTagToValue const &GetMappingFromPrivateTagToValue( + PrivateTag const &pt, const char *value) const; + + /// Retrieve the value found for tag: t associated with file: filename + /// This is meant for a single short call. If multiple calls (multiple tags) + /// should be done, prefer the GetMapping function, and then reuse the + /// TagToValue hash table. \warning Tag 't' should have been added via + /// AddTag() prior to the Scan() call ! + const char *GetPublicValue(const char *filename, Tag const &t) const; + const char *GetPrivateValue(const char *filename, PrivateTag const &t) const; + + /// for wrapped language: instantiate a reference counted object + static SmartPointer New() { return new StrictScanner2; } + + protected: + void ProcessPublicTag(StringFilter &sf, const char *filename); + void ProcessPrivateTag(StringFilter &sf, const char *filename); + + private: + // struct to store all uniq tags in ascending order: + typedef std::set PublicTagsType; + typedef std::set PrivateTagsType; + std::set PublicTags; // Public and Private Creator + std::set PrivateTags; // Only Private (no Private Creator) + std::set SkipTags; + ValuesType Values; + Directory::FilenamesType Filenames; + + // Main struct that will hold all public mapping: + PublicMappingType PublicMappings; + // Main struct that will hold all private mapping: + PrivateMappingType PrivateMappings; + + double Progress; +}; +//----------------------------------------------------------------------------- +inline std::ostream &operator<<(std::ostream &os, const StrictScanner2 &s) { + s.Print(os); + return os; +} + +} // end namespace gdcm + +#endif // GDCMSTRICTSCANNER2_H diff --git a/Source/MediaStorageAndFileFormat/gdcmStringFilter.cxx b/Source/MediaStorageAndFileFormat/gdcmStringFilter.cxx index ef150eff485..7f81fda6843 100644 --- a/Source/MediaStorageAndFileFormat/gdcmStringFilter.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmStringFilter.cxx @@ -18,7 +18,7 @@ #include "gdcmAttribute.h" #include "gdcmDataSetHelper.h" -#include // strtok +#include // strtok namespace gdcm { @@ -143,7 +143,6 @@ bool StringFilter::ExecuteQuery(std::string const & query_const, char *str1, *str2, *token, *subtoken; char *saveptr1= nullptr, *saveptr2; - int j; //bool dicomnativemodel = false;//unused const DataSet *curds = nullptr; @@ -151,13 +150,12 @@ bool StringFilter::ExecuteQuery(std::string const & query_const, Tag t; int state = 0; SmartPointer sqi; - for (j = 1, str1 = query; state >= 0 ; j++, str1 = nullptr) + for (str1 = query; state >= 0 ; str1 = nullptr) { token = System::StrTokR(str1, delim, &saveptr1); if (token == nullptr) break; - //printf("%d: %s\n", j, token); std::vector< std::string > subtokens; for (str2 = token; ; str2 = nullptr) @@ -220,7 +218,7 @@ bool StringFilter::ExecuteQuery(std::string const & query_const, } else { - assert( subtokens.size() ); + assert( !subtokens.empty() ); gdcmDebugMacro( "Unhandled token: " << subtokens[0] ); state = -1; } diff --git a/Source/MediaStorageAndFileFormat/gdcmStringFilter.h b/Source/MediaStorageAndFileFormat/gdcmStringFilter.h index 6abf493eb8c..40bfef88d7e 100644 --- a/Source/MediaStorageAndFileFormat/gdcmStringFilter.h +++ b/Source/MediaStorageAndFileFormat/gdcmStringFilter.h @@ -66,7 +66,7 @@ class GDCM_EXPORT StringFilter /// Execute the XPATH query to find a value (as string) /// return false when attribute is not found (or an error in the XPATH query) - /// You need to make sure that your XPATH query is syntatically correct + /// You need to make sure that your XPATH query is syntactically correct bool ExecuteQuery(std::string const &query, std::string & value) const; protected: diff --git a/Source/MediaStorageAndFileFormat/gdcmSurface.cxx b/Source/MediaStorageAndFileFormat/gdcmSurface.cxx index df082c47294..725550c5d17 100644 --- a/Source/MediaStorageAndFileFormat/gdcmSurface.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmSurface.cxx @@ -116,10 +116,8 @@ Surface::VIEWType Surface::GetVIEWType(const char * type) Surface::Surface(): SurfaceNumber(0), - SurfaceComments(""), SurfaceProcessing(false), SurfaceProcessingRatio(1.), - SurfaceProcessingDescription(""), ProcessingAlgorithm(), RecommendedDisplayGrayscaleValue(0), RecommendedPresentationOpacity(1), @@ -127,8 +125,6 @@ Surface::Surface(): FiniteVolume(UNKNOWN), Manifold(UNKNOWN), AlgorithmFamily(), - AlgorithmVersion(""), - AlgorithmName(""), NumberOfSurfacePoints(0), PointCoordinatesData(), PointPositionAccuracy(nullptr), @@ -150,12 +146,12 @@ Surface::Surface(): Surface::~Surface() { - if (PointPositionAccuracy != nullptr) delete PointPositionAccuracy; - if (PointsBoundingBoxCoordinates != nullptr) delete PointsBoundingBoxCoordinates; - if (AxisOfRotation != nullptr) delete AxisOfRotation; - if (CenterOfRotation != nullptr) delete CenterOfRotation; + delete PointPositionAccuracy; + delete PointsBoundingBoxCoordinates; + delete AxisOfRotation; + delete CenterOfRotation; - if (VectorAccuracy != nullptr) delete VectorAccuracy; + delete VectorAccuracy; } unsigned short Surface::GetRecommendedDisplayGrayscaleValue() const diff --git a/Source/MediaStorageAndFileFormat/gdcmSurfaceWriter.cxx b/Source/MediaStorageAndFileFormat/gdcmSurfaceWriter.cxx index c02f2de1778..0b4d764b050 100644 --- a/Source/MediaStorageAndFileFormat/gdcmSurfaceWriter.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmSurfaceWriter.cxx @@ -380,7 +380,7 @@ bool SurfaceWriter::PrepareWrite() } //****** Surface Mesh Primitives *****// - // Two exemples : + // Two examples : // (0066,0013) SQ (Sequence with undefined length #=1) # u/l, 1 Surface Mesh Primitives Sequence // (fffe,e000) na (Item with undefined length #=1) # u/l, 1 Item // (0066,0042) OL # 0, 1 Long Edge Point Index List diff --git a/Source/MediaStorageAndFileFormat/gdcmTagPath.cxx b/Source/MediaStorageAndFileFormat/gdcmTagPath.cxx index a55eef4dcca..df32df5b56e 100644 --- a/Source/MediaStorageAndFileFormat/gdcmTagPath.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmTagPath.cxx @@ -14,10 +14,10 @@ #include "gdcmTagPath.h" #include "gdcmTag.h" +#include // sscanf +#include // abort +#include // strlen #include -#include // strlen -#include // abort -#include // sscanf namespace gdcm { diff --git a/Source/MediaStorageAndFileFormat/gdcmUIDGenerator.cxx b/Source/MediaStorageAndFileFormat/gdcmUIDGenerator.cxx index 2d777a312da..4d4a9d55ccf 100644 --- a/Source/MediaStorageAndFileFormat/gdcmUIDGenerator.cxx +++ b/Source/MediaStorageAndFileFormat/gdcmUIDGenerator.cxx @@ -120,11 +120,10 @@ const char* UIDGenerator::Generate() { int idx = 0; bool found = false; - std::bitset<8> x; while( !found && idx < 16 ) /* 16 is insane ... oh well */ { // too bad ! randbytesbuf is too long, let's try to truncate the high bits a little - x = uuid[idx]; + std::bitset<8> x = uuid[idx]; unsigned int i = 0; while( ( Unique.size() + len > 64 ) && i < 8 ) { diff --git a/Source/MediaStorageAndFileFormat/gdcmUIDGenerator.h b/Source/MediaStorageAndFileFormat/gdcmUIDGenerator.h index a7b7129bcd8..802aea6e34a 100644 --- a/Source/MediaStorageAndFileFormat/gdcmUIDGenerator.h +++ b/Source/MediaStorageAndFileFormat/gdcmUIDGenerator.h @@ -21,10 +21,7 @@ namespace gdcm /** * \brief Class for generating unique UID - * \details - * \note bla - * Usage: - * When constructing a Series or Study UID, user *has* to keep around the UID, + * \details When constructing a Series or Study UID, user *has* to keep around the UID, * otherwise the UID Generator will simply forget the value and create a new UID. */ class GDCM_EXPORT UIDGenerator @@ -53,7 +50,7 @@ class GDCM_EXPORT UIDGenerator /// successfully been tested for a root of size 26 bytes. Any longer root should work (the Generate() /// function will return a string), but will truncate the high bits of the 128bits UUID until the /// generated string fits on 64 bits. The authors disclaims any - /// responsabitlity for garanteeing uniqueness of UIDs when the root is longer than 26 bytes. + /// responsabitlity for guaranteeing uniqueness of UIDs when the root is longer than 26 bytes. static void SetRoot(const char * root); static const char *GetRoot(); diff --git a/Source/MessageExchangeDefinition/gdcmAAssociateACPDU.cxx b/Source/MessageExchangeDefinition/gdcmAAssociateACPDU.cxx index 4bdbb24f249..261b2fc1000 100644 --- a/Source/MessageExchangeDefinition/gdcmAAssociateACPDU.cxx +++ b/Source/MessageExchangeDefinition/gdcmAAssociateACPDU.cxx @@ -147,7 +147,7 @@ const std::ostream &AAssociateACPDU::Write(std::ostream &os) const //os.write( called, 16 ); os.write( (const char*)&Reserved43_74, sizeof(Reserved43_74) ); AppContext.Write( os ); - gdcmAssertAlwaysMacro( PresContextAC.size() ); + gdcmAssertAlwaysMacro( !PresContextAC.empty() ); std::vector::const_iterator it = PresContextAC.begin(); for( ; it != PresContextAC.end(); ++it ) { diff --git a/Source/MessageExchangeDefinition/gdcmBaseQuery.cxx b/Source/MessageExchangeDefinition/gdcmBaseQuery.cxx index 1063e704ce2..baffb7a7b90 100644 --- a/Source/MessageExchangeDefinition/gdcmBaseQuery.cxx +++ b/Source/MessageExchangeDefinition/gdcmBaseQuery.cxx @@ -49,14 +49,8 @@ passed to a c-find or c-move query. namespace gdcm { - BaseQuery::BaseQuery() - { - //nothing to do, really - } - BaseQuery::~BaseQuery() - { - //nothing to do, really - } + BaseQuery::BaseQuery() = default; + BaseQuery::~BaseQuery() = default; void BaseQuery::SetSearchParameter(const Tag& inTag, const DictEntry& inDictEntry, const std::string& inValue) { @@ -74,7 +68,7 @@ namespace gdcm { de.SetVR( VR::OW ); } - else if( vr == VR::US_SS_OW ) + else if( vr == VR::US_SS_OW ) { de.SetVR( VR::OW ); } diff --git a/Source/MessageExchangeDefinition/gdcmBaseRootQuery.cxx b/Source/MessageExchangeDefinition/gdcmBaseRootQuery.cxx index 84b9c52a1d4..9cd61a45c99 100644 --- a/Source/MessageExchangeDefinition/gdcmBaseRootQuery.cxx +++ b/Source/MessageExchangeDefinition/gdcmBaseRootQuery.cxx @@ -53,10 +53,6 @@ namespace gdcm { //nothing to do, really } - BaseRootQuery::~BaseRootQuery() - { - //nothing to do, really - } static const char *QueryLevelStrings[] = { "PATIENT ", diff --git a/Source/MessageExchangeDefinition/gdcmBaseRootQuery.h b/Source/MessageExchangeDefinition/gdcmBaseRootQuery.h index 4c16a843464..b7d9bb796d4 100644 --- a/Source/MessageExchangeDefinition/gdcmBaseRootQuery.h +++ b/Source/MessageExchangeDefinition/gdcmBaseRootQuery.h @@ -80,7 +80,7 @@ class GDCM_EXPORT BaseRootQuery : public BaseQuery std::string mHelpDescription; //used when generating the help output public: - ~BaseRootQuery() override; + ~BaseRootQuery() override = default; ///this function will return all tags at a given query level, so that ///they maybe selected for searching. The boolean forFind is true diff --git a/Source/MessageExchangeDefinition/gdcmCompositeNetworkFunctions.cxx b/Source/MessageExchangeDefinition/gdcmCompositeNetworkFunctions.cxx index fdd0808f175..59692a20a47 100644 --- a/Source/MessageExchangeDefinition/gdcmCompositeNetworkFunctions.cxx +++ b/Source/MessageExchangeDefinition/gdcmCompositeNetworkFunctions.cxx @@ -257,7 +257,7 @@ bool CompositeNetworkFunctions::CFind( const char *remote, uint16_t portno, gdcmErrorMacro( "Failed to GetResponses." ); return false; } - assert( theResponses.size() >= 1 ); + assert( !theResponses.empty() ); // take the last one: const DataSet &ds = theResponses[ theResponses.size() - 1 ]; // FIXME assert ( ds.FindDataElement(Tag(0x0, 0x0900)) ); @@ -423,7 +423,7 @@ bool CompositeNetworkFunctions::CStore( const char *remote, uint16_t portno, //case 0xA700: //case 0xA900: //case 0xC000: - { + { // TODO: value from 0901 ? gdcmErrorMacro( "C-Store of file " << filename << " was a failure." ); Attribute<0x0,0x0902> errormsg; @@ -432,8 +432,8 @@ bool CompositeNetworkFunctions::CStore( const char *remote, uint16_t portno, assert( themsg ); (void)themsg; gdcmErrorMacro( "Response Status: " << themsg ); ret = false; // at least one file was not sent correctly - } - else + } + else gdcmWarningMacro( "Unhandle error code: " << theVal ); theManager.InvokeEvent( IterationEvent() ); } diff --git a/Source/MessageExchangeDefinition/gdcmDIMSE.h b/Source/MessageExchangeDefinition/gdcmDIMSE.h index bd4f852921f..74bfaeca722 100644 --- a/Source/MessageExchangeDefinition/gdcmDIMSE.h +++ b/Source/MessageExchangeDefinition/gdcmDIMSE.h @@ -76,9 +76,9 @@ class CEchoRSP public: /* Message ID M U -Message ID Being Responded To  M +Message ID Being Responded To M Affected SOP Class UID M U(=) -Status  M +Status M */ }; diff --git a/Source/MessageExchangeDefinition/gdcmNormalizedNetworkFunctions.cxx b/Source/MessageExchangeDefinition/gdcmNormalizedNetworkFunctions.cxx index d5a0e350b67..9b2f3ead1b4 100644 --- a/Source/MessageExchangeDefinition/gdcmNormalizedNetworkFunctions.cxx +++ b/Source/MessageExchangeDefinition/gdcmNormalizedNetworkFunctions.cxx @@ -132,7 +132,7 @@ namespace gdcm gdcmErrorMacro( "Failed to GetResponses." ); return false; } - assert( theResponses.size() >= 1 ); + assert( !theResponses.empty() ); // take the last one: const DataSet &ds = theResponses[ theResponses.size() - 1 ]; // FIXME assert ( ds.FindDataElement(Tag(0x0, 0x0900)) ); @@ -243,7 +243,7 @@ namespace gdcm gdcmErrorMacro( "Failed to GetResponses." ); return false; } - assert( theResponses.size() >= 1 ); + assert( !theResponses.empty() ); // take the last one: const DataSet &ds = theResponses[ theResponses.size() - 1 ]; // FIXME assert ( ds.FindDataElement(Tag(0x0, 0x0900)) ); diff --git a/Source/MessageExchangeDefinition/gdcmPDUFactory.cxx b/Source/MessageExchangeDefinition/gdcmPDUFactory.cxx index f289fa6953c..3ffc8c6b82e 100644 --- a/Source/MessageExchangeDefinition/gdcmPDUFactory.cxx +++ b/Source/MessageExchangeDefinition/gdcmPDUFactory.cxx @@ -21,7 +21,7 @@ this way, the event loop doesn't have to know about all the different PDU types. name and date: 25 Sept 2010 mmr -Updte on 27 sept 2010 mmr: since this is where all PDUs are included, also use this +Update on 27 sept 2010 mmr: since this is where all PDUs are included, also use this class to construct specific instances of PDUs, and return the BasePDU class. */ #include "gdcmPDUFactory.h" diff --git a/Source/MessageExchangeDefinition/gdcmPresentationDataValue.cxx b/Source/MessageExchangeDefinition/gdcmPresentationDataValue.cxx index fd028ad9884..5e83c175b96 100644 --- a/Source/MessageExchangeDefinition/gdcmPresentationDataValue.cxx +++ b/Source/MessageExchangeDefinition/gdcmPresentationDataValue.cxx @@ -165,7 +165,7 @@ DataSet PresentationDataValue::ConcatenatePDVBlobs(const std::vectormConnection; - if (mConnection) - { - delete mConnection; - } + delete mConnection; + Internals->mConnection = new ULConnection(connectInfo); Internals->mConnection->GetTimer().SetTimeout(Internals->timeout); @@ -328,7 +326,7 @@ bool ServiceClassUser::SendFind(const BaseRootQuery* query, std::vector std::vector const & theResponses = theCallback.GetResponses(); bool ret = false; // by default an error - assert( theResponses.size() >= 1 ); + assert( !theResponses.empty() ); // take the last one: const DataSet &ds = theResponses[ theResponses.size() - 1 ]; // FIXME assert ( ds.FindDataElement(Tag(0x0, 0x0900)) ); @@ -404,10 +402,8 @@ bool ServiceClassUser::SendMove(const BaseRootQuery* query, const char *outputdi // let's start the secondary connection ULConnection* mSecondaryConnection = Internals->mSecondaryConnection; - if (mSecondaryConnection) - { - delete mSecondaryConnection; - } + delete mSecondaryConnection; + Internals->mSecondaryConnection = new ULConnection(connectInfo2); Internals->mSecondaryConnection->GetTimer().SetTimeout(Internals->timeout); @@ -439,10 +435,8 @@ bool ServiceClassUser::SendMove(const BaseRootQuery* query, std::vector // let's start the secondary connection ULConnection* mSecondaryConnection = Internals->mSecondaryConnection; - if (mSecondaryConnection) - { - delete mSecondaryConnection; - } + delete mSecondaryConnection; + Internals->mSecondaryConnection = new ULConnection(connectInfo2); Internals->mSecondaryConnection->GetTimer().SetTimeout(Internals->timeout); @@ -773,7 +767,7 @@ EStateID ServiceClassUser::RunEventLoop(network::ULEvent& currentEvent, EStateID ServiceClassUser::RunMoveEventLoop(ULEvent& currentEvent, ULConnectionCallback* inCallback){ EStateID theState = eStaDoesNotExist; - bool waitingForEvent; + bool waitingForEvent = false; EEventID raisedEvent; bool receivingData = false; diff --git a/Source/MessageExchangeDefinition/gdcmULActionAE.cxx b/Source/MessageExchangeDefinition/gdcmULActionAE.cxx index e222e3e580e..b8245fac76b 100644 --- a/Source/MessageExchangeDefinition/gdcmULActionAE.cxx +++ b/Source/MessageExchangeDefinition/gdcmULActionAE.cxx @@ -158,7 +158,7 @@ EStateID ULActionAE6::PerformAction(Subject *, ULEvent& inEvent, ULConnection& i acceptable = false; //can't accept an empty set of pdus. //also, requrie little endian, not sure how to set that, but it should be here. } - AAssociateRQPDU* rqpdu; + AAssociateRQPDU* rqpdu = nullptr; if (acceptable){ rqpdu = dynamic_cast(inEvent.GetPDUs()[0]); if (rqpdu == nullptr){ diff --git a/Source/MessageExchangeDefinition/gdcmULActionDT.cxx b/Source/MessageExchangeDefinition/gdcmULActionDT.cxx index 2b262b04bb5..a96897672c0 100644 --- a/Source/MessageExchangeDefinition/gdcmULActionDT.cxx +++ b/Source/MessageExchangeDefinition/gdcmULActionDT.cxx @@ -27,7 +27,6 @@ each class have its own file for the sake of brevity of the number of files. #include "gdcmARTIMTimer.h" #include "gdcmPDataTFPDU.h" -#include "gdcmPDataTFPDU.h" #include "gdcmAttribute.h" #include "gdcmProgressEvent.h" #include "gdcmFile.h" @@ -44,7 +43,7 @@ namespace gdcm { namespace network { -#if USE_PROCESS_INPUT +#if defined(USE_PROCESS_INPUT) && USE_PROCESS_INPUT static void process_input(iosockinet& sio) { uint8_t itemtype = 0x0; @@ -259,7 +258,7 @@ EStateID ULActionDT1::PerformAction(Subject *s, ULEvent& inEvent, ULConnection& // another channel (technically this is send to an SCP) // in our case we use another port to receive it. -#if USE_PROCESS_INPUT +#if defined(USE_PROCESS_INPUT) && USE_PROCESS_INPUT //wait for the user to try to send some data. sockinetbuf sin (sockbuf::sock_stream); diff --git a/Source/MessageExchangeDefinition/gdcmULConnectionManager.cxx b/Source/MessageExchangeDefinition/gdcmULConnectionManager.cxx index 8533a013b44..9ea5bc98efb 100644 --- a/Source/MessageExchangeDefinition/gdcmULConnectionManager.cxx +++ b/Source/MessageExchangeDefinition/gdcmULConnectionManager.cxx @@ -80,16 +80,13 @@ bool ULConnectionManager::EstablishConnection(const std::string& inAETitle, return false; } - if (mConnection != nullptr) - { - delete mConnection; - } + delete mConnection; mConnection = new ULConnection(connectInfo); mConnection->GetTimer().SetTimeout(inTimeout); // Warning PresentationContextID is important - // this is a sort of uniq key used by the recevier. Eg. + // this is a sort of uniq key used by the receiver. Eg. // if one push_pack // (1, Secondary) // (1, Verification) @@ -274,7 +271,7 @@ bool ULConnectionManager::EstablishConnectionMove(const std::string& inAETitle, // Warning PresentationContextID is important - // this is a sort of uniq key used by the recevier. Eg. + // this is a sort of uniq key used by the receiver. Eg. // if one push_pack // (1, Secondary) // (1, Verification) @@ -336,7 +333,7 @@ bool ULConnectionManager::EstablishConnectionMove(const std::string& inAETitle, std::vector::iterator itor; for (itor = thePDUs.begin(); itor != thePDUs.end(); itor++) { - if (*itor == NULL) continue; //can have a nulled pdu, apparently + if (*itor == nullptr) continue; //can have a nulled pdu, apparently (*itor)->Print(Trace::GetStream()); } } @@ -565,7 +562,7 @@ void ULConnectionManager::BreakConnectionNow(){ EStateID ULConnectionManager::RunMoveEventLoop(ULEvent& currentEvent, ULConnectionCallback* inCallback){ gdcmDebugMacro( "Start RunMoveEventLoop" ); EStateID theState = eStaDoesNotExist; - bool waitingForEvent; + bool waitingForEvent = false; EEventID raisedEvent; bool receivingData = false; diff --git a/Source/MessageExchangeDefinition/gdcmULConnectionManager.h b/Source/MessageExchangeDefinition/gdcmULConnectionManager.h index bae2bbbdf14..b112705ba88 100644 --- a/Source/MessageExchangeDefinition/gdcmULConnectionManager.h +++ b/Source/MessageExchangeDefinition/gdcmULConnectionManager.h @@ -70,7 +70,7 @@ namespace gdcm { ULConnectionManager(); ~ULConnectionManager() override; - // NOTE: (MM) The following two functions are difficults to use, therefore marking + // NOTE: (MM) The following two functions are difficult to use, therefore marking // them as internal for now. // \internal diff --git a/Source/MessageExchangeDefinition/gdcmULEvent.h b/Source/MessageExchangeDefinition/gdcmULEvent.h index df3846e0f94..87c0fca4292 100644 --- a/Source/MessageExchangeDefinition/gdcmULEvent.h +++ b/Source/MessageExchangeDefinition/gdcmULEvent.h @@ -42,9 +42,9 @@ class ULEvent { void DeletePDUVector(){ std::vector::iterator baseItor; for (baseItor = mBasePDU.begin(); baseItor < mBasePDU.end(); baseItor++){ - if (*baseItor != NULL){ + if (*baseItor != nullptr){ delete *baseItor; - *baseItor = NULL; + *baseItor = nullptr; } } } diff --git a/Source/MessageExchangeDefinition/gdcmWLMFindQuery.cxx b/Source/MessageExchangeDefinition/gdcmWLMFindQuery.cxx index 88faba9ce63..68a6d4ec771 100644 --- a/Source/MessageExchangeDefinition/gdcmWLMFindQuery.cxx +++ b/Source/MessageExchangeDefinition/gdcmWLMFindQuery.cxx @@ -46,8 +46,8 @@ WLMFindQuery::ValidateQuery(bool inStrict) const const DataSet &ds = GetQueryDataSet(); if (ds.Size() == 0) return false; - // in Query somme tags are required other are optional - // lets check that we have required one's + // in Query some tags are required, others are optional + // lets check that we have required ones bool theReturn = true ; DataSet validDs = GetValidDataSet(); diff --git a/Utilities/gdcm_expat.h b/Utilities/gdcm_expat.h index 8d23e18bf95..6449ba349ff 100644 --- a/Utilities/gdcm_expat.h +++ b/Utilities/gdcm_expat.h @@ -19,7 +19,7 @@ #ifdef GDCM_USE_SYSTEM_EXPAT # include #else -# include +# include "gdcmexpat/lib/expat.h" #endif #endif diff --git a/Utilities/gdcm_md5.h b/Utilities/gdcm_md5.h index 0f15f88876f..a4802654ed8 100644 --- a/Utilities/gdcm_md5.h +++ b/Utilities/gdcm_md5.h @@ -19,7 +19,7 @@ #ifdef GDCM_USE_SYSTEM_MD5 # include #else -# include +# include "gdcmmd5/md5.h" #endif #endif diff --git a/Utilities/gdcm_openjpeg.h b/Utilities/gdcm_openjpeg.h index 7b1dfc714cc..8c2f22b9f41 100644 --- a/Utilities/gdcm_openjpeg.h +++ b/Utilities/gdcm_openjpeg.h @@ -19,7 +19,7 @@ #ifdef GDCM_USE_SYSTEM_OPENJPEG #include #else -#include +#include "gdcmopenjpeg/src/lib/openjp2/openjpeg.h" #endif #endif diff --git a/Utilities/gdcm_uuid.h b/Utilities/gdcm_uuid.h index 053c96797b7..344836e0723 100644 --- a/Utilities/gdcm_uuid.h +++ b/Utilities/gdcm_uuid.h @@ -19,7 +19,7 @@ #ifdef GDCM_USE_SYSTEM_UUID # include #else -# include +# include "gdcmuuid/uuid.h" #endif #endif diff --git a/Utilities/gdcm_zlib.h b/Utilities/gdcm_zlib.h index 8cd617bf7a4..02d3d3043cd 100644 --- a/Utilities/gdcm_zlib.h +++ b/Utilities/gdcm_zlib.h @@ -21,7 +21,7 @@ // zlib1g-dev: /usr/include/zlib.h # include #else -# include +# include "gdcmzlib/zlib.h" #endif #endif diff --git a/Utilities/gdcmcharls/interface.cpp b/Utilities/gdcmcharls/interface.cpp index b95fe35cd24..ee78e606d46 100644 --- a/Utilities/gdcmcharls/interface.cpp +++ b/Utilities/gdcmcharls/interface.cpp @@ -272,10 +272,10 @@ extern "C" vector rgbyteCompressed(compressedLength + 16); - memcpy(&rgbyteCompressed[0], compressedData, compressedLength); + memcpy(rgbyteCompressed.data(), compressedData, compressedLength); writer.EnableCompare(true); - writer.Write(FromByteArray(&rgbyteCompressed[0], rgbyteCompressed.size())); + writer.Write(FromByteArray(rgbyteCompressed.data(), rgbyteCompressed.size())); ClearErrorMessage(errorMessage); return ApiResult::OK; } diff --git a/Utilities/gdcmcharls/jpegstreamreader.cpp b/Utilities/gdcmcharls/jpegstreamreader.cpp index ca4b58a26b7..71bbe460812 100644 --- a/Utilities/gdcmcharls/jpegstreamreader.cpp +++ b/Utilities/gdcmcharls/jpegstreamreader.cpp @@ -374,7 +374,7 @@ int JpegStreamReader::ReadColorXForm() vector sourceTag; ReadNBytes(sourceTag, 4); - if (strncmp(&sourceTag[0], "mrfx", 4) != 0) + if (strncmp(sourceTag.data(), "mrfx", 4) != 0) return 4; auto xform = static_cast(ReadByte()); diff --git a/Utilities/gdcmext/csa.c b/Utilities/gdcmext/csa.c new file mode 100644 index 00000000000..ad95a6eca42 --- /dev/null +++ b/Utilities/gdcmext/csa.c @@ -0,0 +1,323 @@ +/*========================================================================= + + Program: GDCM (Grassroots DICOM). A DICOM library + + Copyright (c) 2006-2011 Mathieu Malaterre + All rights reserved. + See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include +#include +#include +#include +#include /* realloc */ +#include /* memcpy */ + +struct stream { + const void *start; + const void *end; + void *cur; + size_t (*read)(void *ptr, size_t size, size_t nmemb, struct stream *in); + size_t (*write)(const void *ptr, size_t size, size_t nmemb, + struct stream *outstream); +}; + +static size_t stream_read(void *ptr, size_t size, size_t nmemb, + struct stream *in) { + char *cur = (char *)in->cur; + const char *end = (const char *)in->end; + const size_t len = size * nmemb; + if (cur + len <= end) { + memcpy(ptr, cur, len); + in->cur = cur + len; + } else { + in->cur = NULL; + return 0; + } + return nmemb; +} + +static size_t stream_write(const void *ptr, size_t size, size_t nmemb, + struct stream *out) { + char *cur = (char *)out->cur; + const char *end = (const char *)out->end; + const size_t len = size * nmemb; + if (cur + len <= end) { + memcpy(cur, ptr, len); + out->cur = cur + len; + } else { + out->cur = NULL; + return 0; + } + return nmemb; +} + +enum CSA_TYPE { INVALID = 0, NOMAGIC = 1, SV10 = 2 }; + +struct app { + struct stream *in; + struct stream *out; + uint32_t nelements; + enum CSA_TYPE csa_type; +}; + +static struct app *create_app(struct app *self, struct stream *in, + struct stream *out) { + self->in = in; + self->out = out; + self->nelements = 0; + self->csa_type = INVALID; + + return self; +} + +static void setup_buffer(struct app *self, void *output, const void *input, + size_t len) { + self->in->cur = (char *)input; + self->in->start = input; + self->in->end = (char *)input + len; + self->in->read = stream_read; + self->out->cur = output; + self->out->start = output; + self->out->end = (char *)output + len; + self->out->write = stream_write; +} + +#define ERROR_RETURN(X, Y) \ + if ((X) != (Y)) return false + +static size_t fread_mirror(void *ptr, size_t size, size_t nmemb, + struct app *self) { + struct stream *instream = self->in; + struct stream *outstream = self->out; + + size_t s = instream->read(ptr, size, nmemb, instream); + if (s == nmemb) { + s = outstream->write(ptr, size, nmemb, outstream); + if (s == nmemb) return nmemb; + } + return 0; +} + +static size_t fread_mirror_clean(void *ptr, size_t size, size_t nmemb, + struct app *self) { + struct stream *instream = self->in; + struct stream *outstream = self->out; + + if (nmemb != 64) return 0; + size_t s = instream->read(ptr, size, nmemb, instream); + if (s == nmemb) { + char *str = (char *)ptr; + const size_t len = strnlen(str, nmemb); + assert(len < nmemb); + size_t i; + for (i = len; i < nmemb; ++i) { + str[i] = 0; + } + s = outstream->write(ptr, size, nmemb, outstream); + if (s == nmemb) return nmemb; + } + return 0; +} + +static bool read_magic(struct app *self) { + enum CSA_TYPE magic = INVALID; + uint32_t n; + size_t s = fread_mirror(&n, sizeof n, 1, self); + ERROR_RETURN(s, 1); + uint32_t unused; + s = fread_mirror(&unused, sizeof unused, 1, self); + ERROR_RETURN(s, 1); + + // Handle very special case hopefully no conflict with case of no-magic + if (n == 0x30315653 && unused == 0x01020304) { // aka 'SV10' + // SIEMENS_CSA2.dcm + s = fread_mirror(&n, sizeof n, 1, self); + ERROR_RETURN(s, 1); + ERROR_RETURN(n < 0x100, true); + s = fread_mirror(&unused, sizeof unused, 1, self); + ERROR_RETURN(s, 1); + ERROR_RETURN(unused, 0x4d); // 'M' + magic = SV10; + } else if (n < 0x100 && unused == 0x4d) { // 'M' + // SIEMENS_Sonata-16-MONO2-Value_Multiplicity.dcm + magic = NOMAGIC; + } else { + return false; + } + self->nelements = n; + self->csa_type = magic; + return true; +} + +static bool write_trailer(struct app *self) { + size_t s; + // trailing byte in SV10 + if (self->csa_type == SV10) { + uint32_t unused; + s = fread_mirror(&unused, sizeof unused, 1, self); + ERROR_RETURN(s, 1); + ERROR_RETURN(unused, 0); + } else if (self->csa_type == NOMAGIC) { + // no magic. seems to contains some kind of data, hopefully no PHI +#if 1 + uint32_t i; + for (i = 0; i < 28u; ++i) { + uint32_t unused; + s = fread_mirror(&unused, sizeof unused, 1, self); + ERROR_RETURN(s, 1); + } +#else + char unused[28 * 4]; + s = fread_mirror(unused, sizeof *unused, sizeof unused / sizeof *unused, + self); + ERROR_RETURN(s, 28 * 4); + int i; + for (i = 0; i < 4 * 28; ++i) { + const char c = unused[i]; + assert(c == 0x0 || c == ' ' || c == '.' || (c >= '0' && c <= '9')); + } +#endif + } else { + assert(0); + return false; + } + return true; +} + +struct csa_info { + char name[64]; + uint32_t vm; + char vr[4]; + int32_t syngodt; + uint32_t nitems; +}; + +struct csa_item_data { + uint32_t len; + char *buffer; +}; + +static bool read_info(struct app *self, struct csa_info *i) { + // name. This is 64bytes string. It is assumed that there will be a trailing + // \0 + size_t s = fread_mirror_clean(i->name, sizeof *i->name, + sizeof i->name / sizeof *i->name, self); + ERROR_RETURN(s, 64); + // vm + s = fread_mirror(&i->vm, sizeof i->vm, 1, self); + ERROR_RETURN(s, 1); + // vm == 115301884 seems to be ok... + assert(i->vm < 0x6df5dfd); + // vr + s = fread_mirror(i->vr, sizeof *i->vr, sizeof i->vr / sizeof *i->vr, self); + ERROR_RETURN(s, 4); + { + const char *s = i->vr; + assert(s[0] >= 'A' && s[0] <= 'Z'); + assert(s[1] >= 'A' && s[1] <= 'Z'); + assert(s[2] == 0); + if (self->csa_type == SV10) assert(s[3] == 0); + } + // syngodt (signed) + s = fread_mirror(&i->syngodt, sizeof i->syngodt, 1, self); + ERROR_RETURN(s, 1); + // numer of items + s = fread_mirror(&i->nitems, sizeof i->nitems, 1, self); + if (self->csa_type == SV10) assert(i->nitems % 6 == 0); + ERROR_RETURN(s, 1); + { + uint32_t unused; + s = fread_mirror(&unused, sizeof unused, 1, self); + ERROR_RETURN(s, 1); + ERROR_RETURN(unused == 0x4d || unused == 0xcd, true); + } + + return true; +} + +static bool read_data(struct app *self, struct csa_item_data *d) { + size_t s = fread_mirror(&d->len, sizeof d->len, 1, self); + ERROR_RETURN(s, 1); + int j; + for (j = 0; j < 3; j++) { + uint32_t unused; + s = fread_mirror(&unused, sizeof unused, 1, self); + ERROR_RETURN(s, 1); + assert(unused == d->len || unused == 0x4d || unused == 0xcd); + } + + if (d->len != 0) { + const uint32_t padding_len = (4 - d->len % 4) % 4; + const uint32_t padded_len = ((d->len + 3u) / 4u) * 4u; // (len + 3) & ~0x03 + assert(padded_len == d->len + padding_len); // programmer error + d->buffer = (char *)realloc(d->buffer, padded_len); + assert(padded_len != 0); + ERROR_RETURN(d->buffer != NULL, true); + s = fread_mirror(d->buffer, sizeof *d->buffer, padded_len, self); + ERROR_RETURN(s, padded_len); + } + + return true; +} + +#undef ERROR_RETURN + +static bool csa_scrub(void *output, const void *input, size_t len) { + if (!input || !output) return false; + struct stream sin; + struct stream sout; + struct app a; + struct app *self = create_app(&a, &sin, &sout); + setup_buffer(self, output, input, len); + if (!read_magic(self)) return false; + + bool good = true; + struct csa_info info; + struct csa_item_data data; + data.len = 0; + data.buffer = NULL; + uint32_t element; + for (element = 0; good && element < self->nelements; ++element) { + // read csa key info + if (!read_info(self, &info)) { + good = false; + break; + } + // read all csa item data: + uint32_t item; + for (item = 0; good && item < info.nitems; ++item) { + if (!read_data(self, &data)) { + good = false; + break; + } + } // end for items + } + // release memory: + free(data.buffer); + if (!good) return false; + + // write trailer: + if (!write_trailer(self)) { + return false; + } + + // make sure the whole input was processed: + assert(self->in->cur <= self->in->end); + if (self->in->cur < self->in->end) { + return false; + } + assert(self->out->cur == self->out->end); // programmer error + return true; +} + +void *csa_memcpy(void *dest, const void *src, size_t n) { + const bool b = csa_scrub(dest, src, n); + return b ? dest : NULL; +} diff --git a/Utilities/gdcmext/csa.h b/Utilities/gdcmext/csa.h new file mode 100644 index 00000000000..cb4b0cf9dcc --- /dev/null +++ b/Utilities/gdcmext/csa.h @@ -0,0 +1,29 @@ +/*========================================================================= + + Program: GDCM (Grassroots DICOM). A DICOM library + + Copyright (c) 2006-2011 Mathieu Malaterre + All rights reserved. + See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef CSA_H +#define CSA_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void *csa_memcpy(void *dest, const void *src, size_t n); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif // CSA_H diff --git a/Utilities/gdcmext/mec_mr3.c b/Utilities/gdcmext/mec_mr3.c new file mode 100644 index 00000000000..ca32fd8a7b7 --- /dev/null +++ b/Utilities/gdcmext/mec_mr3.c @@ -0,0 +1,446 @@ +/*========================================================================= + + Program: GDCM (Grassroots DICOM). A DICOM library + + Copyright (c) 2006-2011 Mathieu Malaterre + All rights reserved. + See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include +#include +#include +#include +#include /* realloc */ +#include /* memcpy */ + +struct stream { + const void *start; + const void *end; + void *cur; + size_t (*read)(void *ptr, size_t size, size_t nmemb, struct stream *in); + size_t (*write)(const void *ptr, size_t size, size_t nmemb, + struct stream *outstream); +}; + +static size_t stream_read(void *ptr, size_t size, size_t nmemb, + struct stream *in) { + char *cur = (char *)in->cur; + const char *end = (const char *)in->end; + const size_t len = size * nmemb; + if (cur + len <= end) { + memcpy(ptr, cur, len); + in->cur = cur + len; + } else { + in->cur = NULL; + return 0; + } + return nmemb; +} + +static size_t stream_write(const void *ptr, size_t size, size_t nmemb, + struct stream *out) { + char *cur = (char *)out->cur; + const char *end = (const char *)out->end; + const size_t len = size * nmemb; + if (cur + len <= end) { + memcpy(cur, ptr, len); + out->cur = cur + len; + } else { + out->cur = NULL; + return 0; + } + return nmemb; +} + +struct app { + struct stream *in; + struct stream *out; +}; + +static struct app *create_app(struct app *self, struct stream *in, + struct stream *out) { + self->in = in; + self->out = out; + + return self; +} + +static void setup_buffer(struct app *self, void *output, const void *input, + size_t len) { + self->in->cur = (char *)input; + self->in->start = input; + self->in->end = (char *)input + len; + self->in->read = stream_read; + self->out->cur = output; + self->out->start = output; + self->out->end = (char *)output + len; + self->out->write = stream_write; +} + +#define ERROR_RETURN(X, Y) \ + if ((X) != (Y)) return false + +static size_t fread_mirror(void *ptr, size_t size, size_t nmemb, + struct app *self) { + struct stream *instream = self->in; + struct stream *outstream = self->out; + + size_t s = instream->read(ptr, size, nmemb, instream); + if (s == nmemb) { + s = outstream->write(ptr, size, nmemb, outstream); + if (s == nmemb) return nmemb; + } + return 0; +} + +// uncomment the following to validate the parser: +//#define NOOP + +static void clean_buffer(char *str, size_t buf_len) { +#ifndef NOOP + size_t i; + const size_t len = strnlen(str, buf_len); + for (i = 0; i < len; ++i) { + str[i] = ' '; + } +#endif +} + +struct buffer19 { + char sig1[0x3]; + unsigned char len2; + char sig2; + unsigned char len3; + char sig3; + char iso[0x9]; + char sig4; + unsigned char len4; + char sig5; +}; + +static size_t fread_mirror_clean_iso(void *ptr, size_t size, size_t nmemb, + struct app *self) { + struct stream *instream = self->in; + struct stream *outstream = self->out; + + size_t s = instream->read(ptr, size, nmemb, instream); + if (s == nmemb) { + static const char magic[] = {0xdf, 0xff, 0x79}; + if (nmemb >= sizeof magic && memcmp(ptr, magic, sizeof(magic)) == 0) { + // iso + struct buffer19 b19; + if (nmemb < sizeof b19) return 0; + memcpy(&b19, ptr, sizeof b19); + if (b19.sig2 != 0x1 || b19.sig3 != 0x0 || b19.sig4 != 0x2 || + b19.sig5 != 0x0) + return 0; + const size_t diff = nmemb - sizeof b19; + if (b19.len2 != nmemb - 4 || b19.len3 != 9 || b19.len4 != diff) return 0; + if (strncmp(b19.iso, "ISO8859-1", 9) != 0) return 0; + char *str = (char *)ptr + sizeof b19; + clean_buffer(str, b19.len4); + } else { + // raw string buffer + clean_buffer(ptr, nmemb); + } + s = outstream->write(ptr, size, nmemb, outstream); + if (s == nmemb) return nmemb; + } + return 0; +} + +typedef char str16[16 + 1]; +typedef char str64[64 + 1]; + +struct buffer436 { + uint32_t zero; + char iver[0x45]; + char buf3[0x100]; // phi + str64 buf4; + str16 buf5; + char modality[0x15]; + uint32_t val; +}; +struct buffer516 { + str64 zero; + char buf2[0x15]; + char buf3[0x100]; // phi + str16 buf4; + str64 buf5; + str64 buf6; + uint32_t bools[6]; +}; +struct buffer325 { + str64 array[5]; +}; + +static size_t fread_mirror_clean_struct(void *ptr, size_t size, size_t nmemb, + struct app *self) { + struct stream *instream = self->in; + struct stream *outstream = self->out; + + size_t s = instream->read(ptr, size, nmemb, instream); + if (s == nmemb) { + if (s == 436) { + struct buffer436 b436; + memcpy(&b436, ptr, nmemb); + clean_buffer(b436.buf3, sizeof b436.buf3); + memcpy(ptr, &b436, nmemb); + } else if (s == 516) { + struct buffer516 b516; + memcpy(&b516, ptr, nmemb); + clean_buffer(b516.buf3, sizeof b516.buf3); + memcpy(ptr, &b516, nmemb); + } else if (s == 325) { + struct buffer325 b325; + memcpy(&b325, ptr, nmemb); + int a; + for (a = 0; a < 5; ++a) { + clean_buffer(b325.array[a], sizeof b325.array[a]); + } + memcpy(ptr, &b325, nmemb); + } else { + assert(0); // programmer error + return 0; + } + s = outstream->write(ptr, size, nmemb, outstream); + if (s == nmemb) return nmemb; + } + return 0; +} + +static size_t fread_mirror_clean_shift_jis(void *ptr, size_t size, size_t nmemb, + struct app *self) { + struct stream *instream = self->in; + struct stream *outstream = self->out; + + size_t s = instream->read(ptr, size, nmemb, instream); + if (s == nmemb) { + clean_buffer(ptr, nmemb); + s = outstream->write(ptr, size, nmemb, outstream); + if (s == nmemb) return nmemb; + } + return 0; +} + +static bool read_magic(struct app *self) { + (void)self; + return true; +} + +static bool write_trailer(struct app *self) { + assert(self->in->cur <= self->in->end); + if (self->in->cur == self->in->end) return true; + // else it is missing one byte (nul byte): + char padding; + size_t s = fread_mirror(&padding, sizeof padding, 1, self); + ERROR_RETURN(s, 1); + ERROR_RETURN(padding, 0); + + return true; +} + +struct mec_mr3_info { + uint32_t key; + uint32_t type; +}; + +struct mec_mr3_item_data { + uint32_t len; + char *buffer; +}; + +static const uint32_t magic2[] = {0, 0, 12, 0, 0}; + +static bool read_info(struct app *self, struct mec_mr3_info *info) { + // read key and type at once: + size_t s = fread_mirror(info, sizeof *info, 1, self); + ERROR_RETURN(s, 1); + ERROR_RETURN(info->type & 0x00ff, 0x0); + + return true; +} + +static const uint32_t with_phi[] = { + 0x000055f2, /* !!!charset!!! */ + 0x000055f3, /* */ + 0x000055fc, /* */ + 0x0000560c, /* !!!charset!!! */ + 0x0000560d, /* */ + 0x00005612, /* */ + 0x00006d77, /* */ + 0x00006d80, /* buffer */ + 0x00006d83, /* buffer */ + 0x00006d8a, /* */ +}; + +static bool key_is_phi(const uint32_t val) { + unsigned int i; + for (i = 0; i < sizeof(with_phi) / sizeof(*with_phi); i++) { + if (with_phi[i] == val) return true; + } + return false; +} + +enum Type { + ISO_8859_1_STRING = + 0x00000300, // ASCII string / or struct with 'ISO-8859-1' marker + STRUCT_436 = + 0x001f4300, // Fixed struct 436 bytes (struct with ASCII strings) + STRUCT_516 = + 0x001f4400, // Fixed struct 516 bytes (struct with ASCII strings) + STRUCT_325 = + 0x001f4600, // Fixed struct 325 bytes (struct with ASCII strings) + SHIFT_JIS_STRING = (int)0xff002c00, // SHIFT-JIS string +}; + +enum SignatureType { SIG_UNK = 0, SIG_SIMPLE = 1, SIG_COMPLEX = 2 }; +static enum SignatureType compute_signature(const uint32_t sig[5]) { + // fast path: {0, 0, 12, 0, 0} + const int b = memcmp(sig, magic2, sizeof(magic2)); + if (b == 0) return SIG_SIMPLE; + // check the complex one: + // [0,67937544,12,0,235348672] #20 + // [0,226469240,12,0,235348704] #20 + const bool sig_complex = sig[0] == 0 && sig[2] == 12 && sig[3] == 0; + if (sig_complex) return SIG_COMPLEX; + return SIG_UNK; +} + +static bool read_data(struct app *self, const struct mec_mr3_info *info, + struct mec_mr3_item_data *data) { + size_t s = fread_mirror(&data->len, sizeof data->len, 1, self); + ERROR_RETURN(s, 1); + // in the wild we have: data->len <= 9509 + uint32_t separator[5]; + s = fread_mirror(separator, sizeof *separator, + sizeof separator / sizeof *separator, self); + ERROR_RETURN(s, sizeof separator / sizeof *separator); + const enum SignatureType sig_ok = compute_signature(separator); + ERROR_RETURN(sig_ok != SIG_UNK, true); + data->buffer = (char *)realloc(data->buffer, data->len); + if (data->len != 0 && data->buffer == NULL) { + return false; + } + + if (key_is_phi(info->key)) { + // found a key indicating potential phi + switch (info->type) { + // clean string depending on its type: + case ISO_8859_1_STRING: + s = fread_mirror_clean_iso(data->buffer, 1, data->len, self); + break; + case STRUCT_436: + case STRUCT_516: + case STRUCT_325: + s = fread_mirror_clean_struct(data->buffer, 1, data->len, self); + break; + case SHIFT_JIS_STRING: + s = fread_mirror_clean_shift_jis(data->buffer, 1, data->len, self); + break; + default: + assert(0); // programmer error + return false; + } + } else { + s = fread_mirror(data->buffer, 1, data->len, self); + } + ERROR_RETURN(s, data->len); + + return true; +} + +static bool read_group(struct app *self, uint32_t nitems, + struct mec_mr3_info *info, + struct mec_mr3_item_data *data) { + bool good = true; + uint32_t i; + for (i = 0; i < nitems && good; ++i) { + good = good && read_info(self, info); + // lazy evaluation: + good = good && read_data(self, info, data); + } + return good; +} + +#undef ERROR_RETURN + +// If the number of element read is below the magic value, this indicate the +// last groups of elements: +#define MAGIC_NUM_ELEMENTS 5 + +static bool mec_mr3_scrub(void *output, const void *input, size_t len) { + if (!input || !output) return false; + struct stream sin; + struct stream sout; + struct app a; + struct app *self = create_app(&a, &sin, &sout); + setup_buffer(self, output, input, len); + if (!read_magic(self)) return false; + + bool good = true; + struct mec_mr3_info info; + struct mec_mr3_item_data data; + data.len = 0; + data.buffer = NULL; + + uint32_t remain = 1; + size_t s; + bool last_groups = false; + // read until last set of groups found: + while (!last_groups && good) { + uint32_t nitems; + s = fread_mirror(&nitems, sizeof nitems, 1, self); + if (s != 1 || nitems == 0) { + good = false; + } + assert(nitems < 512); + if (good && nitems <= MAGIC_NUM_ELEMENTS) { + // special case to handle last groups + remain = nitems; + last_groups = true; + s = fread_mirror(&nitems, sizeof nitems, 1, self); + if (s != 1 || nitems == 0) { + good = false; + } + } + // lazy evaluation + good = good && read_group(self, nitems, &info, &data); + } + // read remaining groups: + while (good && --remain != 0) { + uint32_t nitems; + s = fread_mirror(&nitems, sizeof nitems, 1, self); + if (s != 1 || nitems <= MAGIC_NUM_ELEMENTS) { + good = false; + } + good = good && read_group(self, nitems, &info, &data); + } + // release memory: + free(data.buffer); + if (!good) return false; + + // write trailer: + if (!write_trailer(self)) { + return false; + } + + // make sure the whole input was processed: + assert(self->in->cur <= self->in->end); // programmer error + if (self->in->cur < self->in->end) { + return false; + } + assert(self->out->cur == self->out->end); // programmer error + return true; +} + +void *mec_mr3_memcpy(void *dest, const void *src, size_t n) { + const bool b = mec_mr3_scrub(dest, src, n); + return b ? dest : NULL; +} diff --git a/Utilities/gdcmext/mec_mr3.h b/Utilities/gdcmext/mec_mr3.h new file mode 100644 index 00000000000..929e29b563d --- /dev/null +++ b/Utilities/gdcmext/mec_mr3.h @@ -0,0 +1,29 @@ +/*========================================================================= + + Program: GDCM (Grassroots DICOM). A DICOM library + + Copyright (c) 2006-2011 Mathieu Malaterre + All rights reserved. + See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef MEC_MR3_H +#define MEC_MR3_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void *mec_mr3_memcpy(void *dest, const void *src, size_t n); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif // MEC_MR3_H diff --git a/Utilities/gdcmext/mec_mr3_dict.c b/Utilities/gdcmext/mec_mr3_dict.c new file mode 100644 index 00000000000..006ebd21bd5 --- /dev/null +++ b/Utilities/gdcmext/mec_mr3_dict.c @@ -0,0 +1,868 @@ +/*========================================================================= + + Program: GDCM (Grassroots DICOM). A DICOM library + + Copyright (c) 2006-2011 Mathieu Malaterre + All rights reserved. + See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "mec_mr3_dict.h" + +#include +#include + +struct mec_mr3_dict { + uint8_t group; + uint32_t key; + uint32_t type; + const char *name; +}; + +static const struct mec_mr3_dict dict[] = { + {0x01, 0x00000001, 0xfff00200, ""}, // + {0x01, 0x0000006d, 0xff002400, ""}, // + {0x01, 0x00001004, 0xff002400, ""}, // + {0x01, 0x00001005, 0xff002400, ""}, // + {0x01, 0x000013ec, 0xff002900, "Imaging Frequency"}, // + {0x01, 0x00004e23, 0xff002c00, "Software Version"}, // + {0x01, 0x000055f0, 0x0007d000, ""}, // + {0x01, 0x000055f1, 0x00000300, "Patient ID"}, // + {0x01, 0x000055f2, 0x00000300, "Patient Name Ideographic"}, // + {0x01, 0x000055f3, 0x00000300, "Patient Name Alphabetic"}, // + {0x01, 0x000055f6, 0x00000200, ""}, // + {0x01, 0x000055f7, 0xff000400, ""}, // + {0x01, 0x000055f8, 0xff000800, "Patient Size (cm)"}, // + {0x01, 0x000055f9, 0xff000800, "Patient Weight"}, // + {0x01, 0x000055fa, 0x00000300, "Patient Comments"}, // + {0x01, 0x000055fb, 0x00000300, "Name of Physician Reading Study"}, // + {0x01, 0x000055fc, 0x00000300, "Referring Physician Name"}, // + {0x01, 0x000055fd, 0x00000300, "Department Name (surgery)"}, // + {0x01, 0x000055fe, 0x00000300, "Operator Name"}, // + {0x01, 0x000055ff, 0x00000100, ""}, // + {0x01, 0x00005601, 0x00000300, "Study Description"}, // + {0x01, 0x00005602, 0x00000300, ""}, // + {0x01, 0x00005603, 0x00000100, ""}, // + {0x01, 0x00005604, 0xff000400, ""}, // + {0x01, 0x00005606, 0x00000300, "Institution Name"}, // + {0x01, 0x0000560a, 0xff002c00, "Patient Age"}, // + {0x01, 0x0000560b, 0xff002c00, "Patient ID"}, // + {0x01, 0x0000560c, 0xff002c00, "Patient Name Ideographic"}, // + {0x01, 0x0000560d, 0xff002c00, "Patient Name Alphabetic"}, // + {0x01, 0x00005610, 0xff002c00, "Patient Comments"}, // + {0x01, 0x00005611, 0xff002c00, "Name of Physician Reading Study"}, // + {0x01, 0x00005612, 0xff002c00, "Referring Physician Name"}, // + {0x01, 0x00005613, 0xff002c00, "Department Name (surgery)"}, // + {0x01, 0x00005614, 0xff002c00, "Operator Name"}, // + {0x01, 0x00005616, 0xff002c00, "Study Description"}, // + {0x01, 0x00005617, 0xff002c00, ""}, // + {0x01, 0x00005618, 0xff002c00, "Institution Name"}, // + {0x01, 0x00005619, 0xff002c00, ""}, // + {0x01, 0x0000561a, 0x00000e00, "Study DateTime"}, // + {0x01, 0x0000561b, 0x00000e00, "Study Date"}, // + {0x01, 0x000059d8, 0xff002400, ""}, // + {0x01, 0x00006d61, 0xff002c00, "Requested Procedure ID"}, // + {0x01, 0x00006d62, 0xff002c00, ""}, // + {0x01, 0x00006d63, 0xff002c00, + "Procedure Code Sequence: Coding Scheme Designator"}, // + {0x01, 0x00006d64, 0xff002c00, "Procedure Code Sequence: Code Meaning"}, // + {0x01, 0x00006d65, 0xff002c00, "Study Instance UID"}, // + {0x01, 0x00006d66, 0xff002c00, "Stentor Remote AETitle Element"}, // + {0x01, 0x00006d67, 0xff002c00, "Scheduled Procedure Step Description"}, // + {0x01, 0x00006d68, 0xff002c00, "Scheduled Procedure Step ID"}, // + {0x01, 0x00006d69, 0xff002c00, "Requested Procedure ID"}, // + {0x01, 0x00006d71, 0xff002c00, ""}, // + {0x01, 0x00006d72, 0xff002c00, "Procedure Code Sequence: Code Value"}, // + {0x01, 0x00006d73, 0xff002c00, + "Procedure Code Sequence: Coding Scheme Designator"}, // + {0x01, 0x00006d74, 0xff002c00, "Procedure Code Sequence: Code Meaning"}, // + {0x01, 0x00006d75, 0xff002c00, ""}, // + {0x01, 0x00006d76, 0xff002c00, "Scheduled Procedure Step Description"}, // + {0x01, 0x00006d77, 0xff002c00, "Referring Physician Name"}, // + {0x01, 0x00006d78, 0xff002c00, "DetachedStudyManagement UID"}, // + {0x01, 0x00006d79, 0xff002c00, "Referenced Study Instance UID"}, // + {0x01, 0x00006d80, 0x001f4400, ""}, // + {0x01, 0x00006d81, 0x001f4000, ""}, // + {0x01, 0x00006d82, 0x001f4100, ""}, // + {0x01, 0x00006d83, 0x001f4300, ""}, // + {0x01, 0x00006d84, 0x001f4000, ""}, // + {0x01, 0x00006d87, 0xff002400, ""}, // + {0x01, 0x00006d8a, 0x001f4600, ""}, // + {0x01, 0x00006d8b, 0xff002400, ""}, // + {0x01, 0x0000ac09, 0xff002400, ""}, // + {0x02, 0x00000002, 0xfff00200, ""}, // + {0x02, 0x00000007, 0xfff00200, ""}, // + {0x02, 0x0000000b, 0xfff00200, ""}, // + {0x02, 0x0000006e, 0xff002400, ""}, // + {0x02, 0x00000070, 0xff002400, ""}, // + {0x02, 0x00001006, 0xff002800, ""}, // + {0x02, 0x00001007, 0xff002800, ""}, // + {0x02, 0x000017d4, 0xff002a00, ""}, // + {0x02, 0x000017d5, 0xff002a00, ""}, // + {0x02, 0x000017d6, 0xff002a00, ""}, // + {0x02, 0x000017d7, 0xff002a00, ""}, // + {0x02, 0x000017d8, 0xff002a00, ""}, // + {0x02, 0x000017d9, 0xff002a00, ""}, // + {0x02, 0x000017da, 0xff002a00, ""}, // + {0x02, 0x000017db, 0xff002a00, ""}, // + {0x02, 0x000017dc, 0xff002a00, ""}, // + {0x02, 0x000017dd, 0xff002a00, ""}, // + {0x02, 0x000017de, 0xff002400, ""}, // + {0x02, 0x000017df, 0x00177000, ""}, // + {0x02, 0x000017e0, 0x00177000, ""}, // + {0x02, 0x000017e1, 0x00177000, ""}, // + {0x02, 0x000017e2, 0xff002a00, ""}, // + {0x02, 0x000017e3, 0xff002a00, ""}, // + {0x02, 0x000017e4, 0x00177200, ""}, // + {0x02, 0x000017e5, 0xff002400, ""}, // + {0x02, 0x000017e6, 0xff002400, ""}, // + {0x02, 0x000017e7, 0xff002400, ""}, // + {0x02, 0x000017e8, 0xff002400, ""}, // + {0x02, 0x000017e9, 0xff002400, ""}, // + {0x02, 0x000017ea, 0xff002400, ""}, // + {0x02, 0x000017eb, 0xff002400, ""}, // + {0x02, 0x000017ec, 0xff002400, ""}, // + {0x02, 0x000017ed, 0xff002400, ""}, // + {0x02, 0x000017ee, 0xff002400, ""}, // + {0x02, 0x000017f0, 0xff002400, ""}, // + {0x02, 0x000017f1, 0xff002a00, ""}, // + {0x02, 0x000017f2, 0xff002300, ""}, // + {0x02, 0x000017f4, 0xff002400, ""}, // + {0x02, 0x000017f5, 0xff002400, ""}, // + {0x02, 0x000017f6, 0xff002400, ""}, // + {0x02, 0x000017f7, 0xff003200, ""}, // + {0x02, 0x000017f8, 0xff002800, ""}, // + {0x02, 0x000017f9, 0xff002800, ""}, // + {0x02, 0x000017fa, 0xff003200, ""}, // + {0x02, 0x000017fc, 0xff003200, ""}, // + {0x02, 0x000017fd, 0xff002800, ""}, // + {0x02, 0x000017fe, 0xff002800, ""}, // + {0x02, 0x000017ff, 0xff002800, ""}, // + {0x02, 0x00001800, 0xff002800, ""}, // + {0x02, 0x00001816, 0xff002400, ""}, // + {0x02, 0x00001817, 0xff002400, ""}, // + {0x02, 0x00001818, 0xff002400, ""}, // + {0x02, 0x00001838, 0xff002400, ""}, // + {0x02, 0x00001839, 0xff002400, ""}, // + {0x02, 0x0000183a, 0xff002800, ""}, // + {0x02, 0x0000183b, 0xff002400, ""}, // + {0x02, 0x0000183c, 0xff002800, ""}, // + {0x02, 0x0000183d, 0xff002800, ""}, // + {0x02, 0x0000183e, 0xff002800, ""}, // + {0x02, 0x0000183f, 0xff002800, ""}, // + {0x02, 0x00001840, 0xff002800, ""}, // + {0x02, 0x00001841, 0xff002800, ""}, // + {0x02, 0x00001842, 0xff002800, ""}, // + {0x02, 0x00001843, 0xff002a00, ""}, // + {0x02, 0x00001844, 0xff002400, ""}, // + {0x02, 0x00001845, 0xff002400, ""}, // + {0x02, 0x00001848, 0xff002a00, ""}, // + {0x02, 0x00001849, 0xff002a00, ""}, // + {0x02, 0x0000184a, 0xff002800, ""}, // + {0x02, 0x0000185f, 0xff002400, ""}, // + {0x02, 0x00001860, 0xff002400, ""}, // + {0x02, 0x00001861, 0xff003200, ""}, // + {0x02, 0x00001862, 0xff002400, ""}, // + {0x02, 0x00001863, 0xff002400, ""}, // + {0x02, 0x00001864, 0xff002400, ""}, // + {0x02, 0x00001865, 0xff002400, ""}, // + {0x02, 0x00001866, 0xff002400, ""}, // + {0x02, 0x00001867, 0xff002400, ""}, // + {0x02, 0x00005600, 0x00000300, ""}, // + {0x02, 0x00005615, 0xff002c00, ""}, // + {0x02, 0x00009c41, 0xff002c00, "Manufacturer Model Name"}, // + {0x02, 0x0000a7f8, 0xff002c00, "Sequence Name"}, // + {0x02, 0x0000a7f9, 0xff002c00, "Sequence Name Extended"}, // + {0x02, 0x0000a7fb, 0xff002400, ""}, // + {0x02, 0x0000a7fd, 0xff003200, ""}, // + {0x02, 0x0000a7fe, 0xff002400, ""}, // + {0x02, 0x0000a7ff, 0xff002800, "Echo Time (/1000)"}, // + {0x02, 0x0000a800, 0xff002400, ""}, // + {0x02, 0x0000a801, 0xff002800, "Spacing Between Slices (/1000)"}, // + {0x02, 0x0000a802, 0xff002800, ""}, // + {0x02, 0x0000a803, 0xff002400, ""}, // + {0x02, 0x0000a804, 0xff002400, ""}, // + {0x02, 0x0000a805, 0xff003200, ""}, // + {0x02, 0x0000a806, 0x00000500, "FOV"}, // + {0x02, 0x0000a807, 0x00000500, "Image Matrix"}, // + {0x02, 0x0000a808, 0xff002400, ""}, // + {0x02, 0x0000a809, 0xff003200, ""}, // + {0x02, 0x0000a80a, 0x000bb800, ""}, // + {0x02, 0x0000a80b, 0x000bb900, ""}, // + {0x02, 0x0000a80c, 0xff002a00, ""}, // + {0x02, 0x0000a80d, 0xff002800, "Repetition Time (/1000)"}, // + {0x02, 0x0000a80e, 0xff002800, ""}, // + {0x02, 0x0000a80f, 0xff002400, ""}, // + {0x02, 0x0000a810, 0xff002400, ""}, // + {0x02, 0x0000a813, 0xff002400, ""}, // + {0x02, 0x0000a814, 0xff002800, ""}, // + {0x02, 0x0000a815, 0xff002400, ""}, // + {0x02, 0x0000a816, 0xff002400, ""}, // + {0x02, 0x0000a817, 0xff002400, ""}, // + {0x02, 0x0000a819, 0xff002400, ""}, // + {0x02, 0x0000a81b, 0xff002400, ""}, // + {0x02, 0x0000a81c, 0xff003200, ""}, // + {0x02, 0x0000a81d, 0xff002a00, ""}, // + {0x02, 0x0000a822, 0x00000500, ""}, // + {0x02, 0x0000a823, 0xff002c00, "MR Acquition Type"}, // + {0x02, 0x0000a824, 0xff002400, ""}, // + {0x02, 0x0000a825, 0xff002400, ""}, // + {0x02, 0x0000a826, 0xff003200, ""}, // + {0x02, 0x0000a827, 0xff002400, ""}, // + {0x02, 0x0000a828, 0xff002400, ""}, // + {0x02, 0x0000a82c, 0xff002400, ""}, // + {0x02, 0x0000a82d, 0x000bbb00, ""}, // + {0x02, 0x0000a82e, 0xff002400, ""}, // + {0x02, 0x0000a82f, 0xff002a00, ""}, // + {0x02, 0x0000a830, 0xff002800, ""}, // + {0x02, 0x0000a832, 0xff002a00, ""}, // + {0x02, 0x0000a834, 0xff002800, ""}, // + {0x02, 0x0000a835, 0xff003200, ""}, // + {0x02, 0x0000a836, 0xff002400, ""}, // + {0x02, 0x0000a837, 0xff002400, "Echo Train Length"}, // + {0x02, 0x0000a838, 0xff002400, ""}, // + {0x02, 0x0000a839, 0xff002400, ""}, // + {0x02, 0x0000a83a, 0xff002400, ""}, // + {0x02, 0x0000a83b, 0xff002400, ""}, // + {0x02, 0x0000a83c, 0xff002400, ""}, // + {0x02, 0x0000a83d, 0xff002400, ""}, // + {0x02, 0x0000a844, 0xff002c00, ""}, // + {0x02, 0x0000a846, 0xff002400, ""}, // + {0x02, 0x0000a847, 0xff002400, ""}, // + {0x02, 0x0000a848, 0xff002800, ""}, // + {0x02, 0x0000a849, 0xff002800, ""}, // + {0x02, 0x0000a84a, 0xff002a00, ""}, // + {0x02, 0x0000a84b, 0xff002400, ""}, // + {0x02, 0x0000a84c, 0xff002400, ""}, // + {0x02, 0x0000a84d, 0xff002400, ""}, // + {0x02, 0x0000a84e, 0xff002400, ""}, // + {0x02, 0x0000a84f, 0xff002800, ""}, // + {0x02, 0x0000a850, 0xff002800, ""}, // + {0x02, 0x0000a851, 0xff002800, ""}, // + {0x02, 0x0000a852, 0xff002400, ""}, // + {0x02, 0x0000a853, 0xff002400, ""}, // + {0x02, 0x0000a854, 0xff002400, ""}, // + {0x02, 0x0000a85d, 0xff002a00, ""}, // + {0x02, 0x0000a85e, 0xff003200, ""}, // + {0x02, 0x0000a864, 0xff002400, ""}, // + {0x02, 0x0000a865, 0xff002400, ""}, // + {0x02, 0x0000a866, 0xff002800, ""}, // + {0x02, 0x0000a867, 0xff002800, ""}, // + {0x02, 0x0000a868, 0xff002800, ""}, // + {0x02, 0x0000a869, 0xff002400, ""}, // + {0x02, 0x0000a86a, 0xff002400, ""}, // + {0x02, 0x0000a86b, 0xff002400, ""}, // + {0x02, 0x0000a86c, 0xff002400, ""}, // + {0x02, 0x0000a86d, 0xff002400, ""}, // + {0x02, 0x0000a86e, 0xff002400, ""}, // + {0x02, 0x0000a86f, 0xff002800, ""}, // + {0x02, 0x0000a870, 0xff002400, ""}, // + {0x02, 0x0000a8c1, 0xff002c00, "Protocol Name"}, // + {0x02, 0x0000a8c2, 0xff002a00, ""}, // + {0x02, 0x0000a8c3, 0xff003200, ""}, // + {0x02, 0x0000a8c4, 0xff002400, ""}, // + {0x02, 0x0000a8c5, 0xff002400, ""}, // + {0x02, 0x0000a8c6, 0xff002400, ""}, // + {0x02, 0x0000a8c7, 0x000bba00, ""}, // + {0x02, 0x0000a8c8, 0x00000400, ""}, // + {0x02, 0x0000a8c9, 0xff002400, ""}, // + {0x02, 0x0000a8ca, 0xff002400, ""}, // + {0x02, 0x0000a8cb, 0x00000400, ""}, // + {0x02, 0x0000a8cc, 0x00000400, ""}, // + {0x02, 0x0000a8cd, 0x00000400, ""}, // + {0x02, 0x0000a8ce, 0x00000400, ""}, // + {0x02, 0x0000a8cf, 0x00000400, ""}, // + {0x02, 0x0000a8d0, 0xff002400, ""}, // + {0x02, 0x0000a8d1, 0xff002400, ""}, // + {0x02, 0x0000a8d6, 0xff002400, ""}, // + {0x02, 0x0000a8d7, 0xff002400, ""}, // + {0x02, 0x0000a8d8, 0xff002a00, ""}, // + {0x02, 0x0000a8d9, 0xff002400, ""}, // + {0x02, 0x0000a8da, 0xff002c00, "Protocol Name"}, // + {0x02, 0x0000a8db, 0xff002400, ""}, // + {0x02, 0x0000a8dc, 0xff002400, ""}, // + {0x02, 0x0000a8dd, 0xff002800, ""}, // + {0x02, 0x0000a8de, 0xff002400, ""}, // + {0x02, 0x0000a8df, 0xff002800, ""}, // + {0x02, 0x0000a8e0, 0xff002400, ""}, // + {0x02, 0x0000a8e1, 0xff002400, ""}, // + {0x02, 0x0000a8e2, 0xff002800, ""}, // + {0x02, 0x0000a8e3, 0xff002800, ""}, // + {0x02, 0x0000a8e4, 0xff002800, ""}, // + {0x02, 0x0000a8e6, 0xff002400, ""}, // + {0x02, 0x0000a8e7, 0xff002400, ""}, // + {0x02, 0x0000a8e8, 0xff002400, ""}, // + {0x02, 0x0000a8e9, 0xff003200, ""}, // + {0x02, 0x0000a8ea, 0xff003200, ""}, // + {0x02, 0x0000a8eb, 0xff002400, ""}, // + {0x02, 0x0000a8ef, 0xff002800, ""}, // + {0x02, 0x0000a8f2, 0xff002400, ""}, // + {0x02, 0x0000a8f3, 0xff002400, ""}, // + {0x02, 0x0000a8f5, 0xff003200, ""}, // + {0x02, 0x0000a8f6, 0xff002400, ""}, // + {0x02, 0x0000a8f7, 0xff002400, ""}, // + {0x02, 0x0000a8f8, 0xff002400, ""}, // + {0x02, 0x0000a8fa, 0xff002400, ""}, // + {0x02, 0x0000a8fb, 0xff002400, ""}, // + {0x02, 0x0000a8fd, 0x00000600, ""}, // + {0x02, 0x0000a8fe, 0x00000600, ""}, // + {0x02, 0x0000a8ff, 0xff003200, ""}, // + {0x02, 0x0000a900, 0xff002400, ""}, // + {0x02, 0x0000a901, 0xff002400, ""}, // + {0x02, 0x0000a902, 0xff002400, ""}, // + {0x02, 0x0000a903, 0xff002400, ""}, // + {0x02, 0x0000a904, 0xff002400, ""}, // + {0x02, 0x0000a905, 0xff002800, ""}, // + {0x02, 0x0000a906, 0xff002400, ""}, // + {0x02, 0x0000a907, 0xff002400, ""}, // + {0x02, 0x0000a908, 0xff002400, ""}, // + {0x02, 0x0000a909, 0xff002400, ""}, // + {0x02, 0x0000a90a, 0xff002400, ""}, // + {0x02, 0x0000a90b, 0xff002400, ""}, // + {0x02, 0x0000a90c, 0xff002400, ""}, // + {0x02, 0x0000a90e, 0xff002a00, ""}, // + {0x02, 0x0000a915, 0xff002400, ""}, // + {0x02, 0x0000a916, 0xff002400, ""}, // + {0x02, 0x0000a917, 0xff002400, ""}, // + {0x02, 0x0000a918, 0xff003200, ""}, // + {0x02, 0x0000a919, 0xff003200, ""}, // + {0x02, 0x0000a91a, 0xff002400, ""}, // + {0x02, 0x0000a91b, 0xff002400, ""}, // + {0x02, 0x0000a91c, 0x000bbb00, ""}, // + {0x02, 0x0000a91d, 0xff002400, ""}, // + {0x02, 0x0000a920, 0xff002400, ""}, // + {0x02, 0x0000a921, 0xff002400, ""}, // + {0x02, 0x0000a922, 0xff002400, ""}, // + {0x02, 0x0000a923, 0xff002400, ""}, // + {0x02, 0x0000a924, 0xff002400, ""}, // + {0x02, 0x0000a925, 0xff002400, ""}, // + {0x02, 0x0000a926, 0xff002400, ""}, // + {0x02, 0x0000a927, 0xff002400, ""}, // + {0x02, 0x0000a928, 0xff002400, ""}, // + {0x02, 0x0000a929, 0xff002400, ""}, // + {0x02, 0x0000a92a, 0xff002400, ""}, // + {0x02, 0x0000a92b, 0xff002400, ""}, // + {0x02, 0x0000a92c, 0x000bbb00, ""}, // + {0x02, 0x0000a92d, 0x00000600, ""}, // + {0x02, 0x0000a92f, 0xff002400, ""}, // + {0x02, 0x0000a930, 0xff002400, ""}, // + {0x02, 0x0000a931, 0xff002400, ""}, // + {0x02, 0x0000a932, 0xff002400, ""}, // + {0x02, 0x0000a934, 0xff002a00, ""}, // + {0x02, 0x0000a935, 0xff002400, ""}, // + {0x02, 0x0000a936, 0xff002400, ""}, // + {0x02, 0x0000a937, 0xff002800, ""}, // + {0x02, 0x0000a938, 0x00000600, ""}, // + {0x02, 0x0000a93a, 0xff002400, ""}, // + {0x02, 0x0000a93c, 0xff002400, ""}, // + {0x02, 0x0000a93d, 0xff002400, ""}, // + {0x02, 0x0000a93e, 0xff002800, ""}, // + {0x02, 0x0000a940, 0xff002800, ""}, // + {0x02, 0x0000a941, 0xff002400, ""}, // + {0x02, 0x0000a942, 0xff002400, ""}, // + {0x02, 0x0000a943, 0xff002400, ""}, // + {0x02, 0x0000a944, 0xff002400, ""}, // + {0x02, 0x0000a945, 0xff002400, ""}, // + {0x02, 0x0000a946, 0xff002400, ""}, // + {0x02, 0x0000a947, 0xff002800, ""}, // + {0x02, 0x0000a948, 0xff002400, ""}, // + {0x02, 0x0000a949, 0xff002400, ""}, // + {0x02, 0x0000a94a, 0xff002400, ""}, // + {0x02, 0x0000a94b, 0xff002800, ""}, // + {0x02, 0x0000a94c, 0xff002400, ""}, // + {0x02, 0x0000a94d, 0xff002400, ""}, // + {0x02, 0x0000a94e, 0xff002800, ""}, // + {0x02, 0x0000a94f, 0xff002400, ""}, // + {0x02, 0x0000a95b, 0xff002800, ""}, // + {0x02, 0x0000a95c, 0xff002400, ""}, // + {0x02, 0x0000a95d, 0xff002400, ""}, // + {0x02, 0x0000a95e, 0xff002400, ""}, // + {0x02, 0x0000a95f, 0xff002400, ""}, // + {0x02, 0x0000a960, 0xff002800, ""}, // + {0x02, 0x0000a961, 0xff002400, ""}, // + {0x02, 0x0000a962, 0xff002400, ""}, // + {0x02, 0x0000a964, 0xff002400, ""}, // + {0x02, 0x0000a965, 0x000bc100, ""}, // + {0x02, 0x0000a966, 0x000bc200, ""}, // + {0x02, 0x0000a96a, 0x000bc300, ""}, // + {0x02, 0x0000a96b, 0xff002400, ""}, // + {0x02, 0x0000a96c, 0xff002400, ""}, // + {0x02, 0x0000a96d, 0xff002a00, ""}, // + {0x02, 0x0000a96e, 0x000bc200, ""}, // + {0x02, 0x0000a96f, 0xff002400, ""}, // + {0x02, 0x0000a970, 0xff002400, ""}, // + {0x02, 0x0000a971, 0xff002400, ""}, // + {0x02, 0x0000a972, 0xff002400, ""}, // + {0x02, 0x0000a973, 0xff002800, ""}, // + {0x02, 0x0000a974, 0xff002c00, "Body Part Examined"}, // + {0x02, 0x0000a975, 0x00000600, ""}, // + {0x02, 0x0000a976, 0xff002400, ""}, // + {0x02, 0x0000a977, 0xff002400, ""}, // + {0x02, 0x0000a978, 0xff002400, ""}, // + {0x02, 0x0000a979, 0xff002400, ""}, // + {0x02, 0x0000a980, 0xff002800, ""}, // + {0x02, 0x0000a987, 0xff002400, ""}, // + {0x02, 0x0000a988, 0xff002400, ""}, // + {0x02, 0x0000a989, 0xff002400, ""}, // + {0x02, 0x0000a98a, 0x00000f00, ""}, // + {0x02, 0x0000a98b, 0xff002400, ""}, // + {0x02, 0x0000a98c, 0xff002400, ""}, // + {0x02, 0x0000a98d, 0x000bc100, ""}, // + {0x02, 0x0000a98e, 0x000bc200, ""}, // + {0x02, 0x0000a98f, 0xff002400, ""}, // + {0x02, 0x0000a990, 0xff002400, ""}, // + {0x02, 0x0000a991, 0xff002400, ""}, // + {0x02, 0x0000a992, 0xff002400, ""}, // + {0x02, 0x0000a993, 0xff002400, ""}, // + {0x02, 0x0000abe0, 0xff002c00, ""}, // + {0x02, 0x0000abe1, 0xff002c00, ""}, // + {0x02, 0x0000abe2, 0xff002c00, ""}, // + {0x02, 0x0000abe3, 0xff002400, ""}, // + {0x02, 0x0000abe4, 0xff002800, ""}, // + {0x02, 0x0000abe5, 0xff002c00, ""}, // + {0x02, 0x0000abe6, 0xff002c00, ""}, // + {0x02, 0x0000abe8, 0xff002c00, ""}, // + {0x02, 0x0000abe9, 0xff002c00, ""}, // + {0x02, 0x0000abeb, 0xff002800, "Repetition Time (/1000)"}, // + {0x02, 0x0000abec, 0xff002800, ""}, // + {0x02, 0x0000abed, 0xff002800, ""}, // + {0x02, 0x0000abee, 0xff002400, ""}, // + {0x02, 0x0000abf2, 0xff002400, ""}, // + {0x02, 0x0000abf3, 0xff002400, ""}, // + {0x02, 0x0000abf5, 0xff002a00, ""}, // + {0x02, 0x0000abf6, 0xff002400, ""}, // + {0x02, 0x0000abf7, 0xff002400, ""}, // + {0x02, 0x0000abf8, 0xff002400, ""}, // + {0x02, 0x0000abf9, 0xff002400, ""}, // + {0x02, 0x0000abfa, 0xff002400, ""}, // + {0x02, 0x0000abfb, 0xff002400, ""}, // + {0x02, 0x0000abfc, 0xff002400, ""}, // + {0x02, 0x0000abfd, 0xff002400, ""}, // + {0x02, 0x0000abfe, 0xff002400, ""}, // + {0x02, 0x0000ac00, 0xff002800, ""}, // + {0x02, 0x0000ac01, 0xff002800, ""}, // + {0x02, 0x0000ac09, 0xff002400, ""}, // + {0x02, 0x0000ac0a, 0xff002a00, ""}, // + {0x02, 0x0000ac0b, 0x00000500, "Image Matrix"}, // + {0x02, 0x0000ac0c, 0x00000400, ""}, // + {0x02, 0x0000ac0d, 0xff002a00, ""}, // + {0x02, 0x0000ac0e, 0xff002800, "Repetition Time (/1000)"}, // + {0x02, 0x0000ac0f, 0xff002400, ""}, // + {0x02, 0x0000ac10, 0xff002400, ""}, // + {0x02, 0x0000ac11, 0xff002400, ""}, // + {0x02, 0x0000ac12, 0xff002400, ""}, // + {0x02, 0x0000ac13, 0xff002400, ""}, // + {0x02, 0x0000ac14, 0xff002400, ""}, // + {0x02, 0x0000ac15, 0xff002400, ""}, // + {0x02, 0x0000ac16, 0xff002400, ""}, // + {0x02, 0x0000ac17, 0xff002400, ""}, // + {0x02, 0x0000ac18, 0xff002400, ""}, // + {0x02, 0x0000ac19, 0x00000400, ""}, // + {0x02, 0x0000ac1a, 0xff002400, ""}, // + {0x02, 0x0000ac1b, 0xff002400, ""}, // + {0x02, 0x0000ac1c, 0xff002400, ""}, // + {0x02, 0x0000ac1d, 0xff002400, ""}, // + {0x02, 0x0000ac1e, 0xff002400, ""}, // + {0x02, 0x0000ac1f, 0xff002400, ""}, // + {0x02, 0x0000ac20, 0xff003100, ""}, // + {0x02, 0x0000ac21, 0xff002800, ""}, // + {0x02, 0x0000ac22, 0xff002400, ""}, // + {0x02, 0x0000ac23, 0xff002800, ""}, // + {0x02, 0x0000ac24, 0xff002800, ""}, // + {0x02, 0x0000ac25, 0xff002400, ""}, // + {0x02, 0x0000ac26, 0xff003100, ""}, // + {0x02, 0x0000ac27, 0xff002400, ""}, // + {0x02, 0x0000ac28, 0xff003100, ""}, // + {0x02, 0x0000ac29, 0xff002800, ""}, // + {0x02, 0x0000ac2a, 0xff002400, ""}, // + {0x02, 0x0000ac2b, 0xff002400, ""}, // + {0x02, 0x0000ac2d, 0xff002800, ""}, // + {0x02, 0x0000ac2e, 0xff002400, ""}, // + {0x02, 0x0000ac2f, 0x00000600, ""}, // + {0x02, 0x0000ac30, 0xff002400, ""}, // + {0x02, 0x0000ac31, 0xff002400, ""}, // + {0x02, 0x0000ac32, 0xff002400, ""}, // + {0x02, 0x0000ac33, 0xff002400, ""}, // + {0x02, 0x0000ac34, 0xff002400, ""}, // + {0x02, 0x0000ac35, 0xff002800, ""}, // + {0x02, 0x0000ac36, 0xff002400, ""}, // + {0x02, 0x0000ac37, 0xff002400, ""}, // + {0x02, 0x0000ac38, 0xff002800, ""}, // + {0x02, 0x0000ac39, 0xff002400, ""}, // + {0x02, 0x0000ac3a, 0xff002400, ""}, // + {0x02, 0x0000ac3c, 0xff002800, ""}, // + {0x02, 0x0000ac3d, 0xff002400, ""}, // + {0x02, 0x0000ac3e, 0xff002800, ""}, // + {0x02, 0x0000ac3f, 0xff002400, ""}, // + {0x02, 0x0000ac40, 0xff002400, ""}, // + {0x02, 0x0000ac41, 0xff002400, ""}, // + {0x02, 0x0000ac42, 0xff002800, ""}, // + {0x02, 0x0000ac43, 0xff002400, ""}, // + {0x02, 0x0000ac44, 0xff002c00, ""}, // + {0x02, 0x0000afc8, 0xff002400, ""}, // + {0x02, 0x0000afc9, 0xff002900, "Imaging Frequency"}, // + {0x02, 0x0000afca, 0xff002400, ""}, // + {0x02, 0x0000afcc, 0xff002800, ""}, // + {0x02, 0x0000afce, 0xff002800, ""}, // + {0x02, 0x0000afcf, 0xff002400, ""}, // + {0x02, 0x0000afd0, 0xff002c00, ""}, // + {0x02, 0x0000afd1, 0xff002800, ""}, // + {0x02, 0x0000afd2, 0xff002800, ""}, // + {0x02, 0x0000afd5, 0xff002400, ""}, // + {0x02, 0x0000afd6, 0xff002400, "Frame of Reference Index"}, // + {0x02, 0x0000afd8, 0xff002a00, ""}, // + {0x02, 0x0000afd9, 0xff002200, ""}, // + {0x02, 0x0000afda, 0xff002800, ""}, // + {0x02, 0x0000afde, 0xff002400, ""}, // + {0x02, 0x0000afdf, 0xff002800, ""}, // + {0x02, 0x0000afe0, 0xff002c00, ""}, // + {0x02, 0x0000afe1, 0xff002400, ""}, // + {0x02, 0x0000afe2, 0xff002800, ""}, // + {0x02, 0x0000afe4, 0xff002400, ""}, // + {0x02, 0x0000afe5, 0xff002800, ""}, // + {0x02, 0x0000afe6, 0xff002800, ""}, // + {0x02, 0x0000afe7, 0xff002800, ""}, // + {0x02, 0x0000afe8, 0xff002800, ""}, // + {0x02, 0x0000afe9, 0xff002400, ""}, // + {0x02, 0x0000afea, 0xff002800, ""}, // + {0x02, 0x0000afeb, 0xff002800, ""}, // + {0x02, 0x0000aff0, 0xff002400, ""}, // + {0x02, 0x0000aff5, 0xff002800, ""}, // + {0x02, 0x0000aff6, 0xff002800, ""}, // + {0x02, 0x0000aff7, 0xff002400, ""}, // + {0x02, 0x0000affa, 0xff002500, ""}, // + {0x02, 0x0000affc, 0xff002400, ""}, // + {0x02, 0x0000affd, 0xff002400, ""}, // + {0x02, 0x0000afff, 0xff002200, ""}, // + {0x02, 0x0000b002, 0xff002400, ""}, // + {0x02, 0x0000b004, 0xff002400, ""}, // + {0x02, 0x0000b005, 0xff002400, ""}, // + {0x02, 0x0000b006, 0x00000500, ""}, // + {0x02, 0x0000b007, 0xff002800, ""}, // + {0x02, 0x0000b008, 0xff002800, ""}, // + {0x02, 0x0000b009, 0xff002800, ""}, // + {0x02, 0x0000b00a, 0xff002800, ""}, // + {0x02, 0x0000b010, 0x00000f00, ""}, // + {0x02, 0x0000b011, 0xff002800, ""}, // + {0x02, 0x0000b012, 0xff002800, ""}, // + {0x02, 0x0000b3b0, 0xff002800, ""}, // + {0x02, 0x0000b3b1, 0xff002400, ""}, // + {0x02, 0x0000b3b2, 0xff002400, ""}, // + {0x02, 0x0000b3b3, 0xff002300, ""}, // + {0x02, 0x0000b3b4, 0x00000b00, ""}, // + {0x02, 0x0000b3b5, 0xff002400, ""}, // + {0x02, 0x0000b3b7, 0xff002400, ""}, // + {0x02, 0x0000b3b9, 0xff002500, ""}, // + {0x02, 0x0000b3ba, 0xff002800, ""}, // + {0x02, 0x0000b3bb, 0xff002400, ""}, // + {0x02, 0x0000b3c2, 0xff002400, ""}, // + {0x02, 0x0000b3c3, 0xff002400, ""}, // + {0x02, 0x0000b3c4, 0xff002800, ""}, // + {0x02, 0x0000b3c5, 0xff002400, ""}, // + {0x02, 0x0000b3c6, 0xff002400, ""}, // + {0x02, 0x0000b3c7, 0xff002800, ""}, // + {0x02, 0x0000b3c8, 0xff002400, ""}, // + {0x02, 0x0000b3c9, 0xff002400, ""}, // + {0x02, 0x0000b3ca, 0xff003200, ""}, // + {0x02, 0x0000b3cb, 0xff003200, ""}, // + {0x02, 0x0000b3cc, 0xff003200, ""}, // + {0x02, 0x0000b3cd, 0xff002400, ""}, // + {0x02, 0x0000b3ce, 0xff002400, ""}, // + {0x02, 0x0000b3d0, 0xff002500, ""}, // + {0x02, 0x0000b3d1, 0xff002400, ""}, // + {0x02, 0x0000b3d2, 0xff002800, ""}, // + {0x02, 0x0000b3d3, 0xff002800, ""}, // + {0x02, 0x0000b3d4, 0xff002800, ""}, // + {0x02, 0x0000b3d5, 0xff002c00, ""}, // + {0x02, 0x0000b3d6, 0xff002800, ""}, // + {0x02, 0x0000b3d7, 0xff002400, ""}, // + {0x02, 0x0000b3d9, 0xff002400, ""}, // + {0x02, 0x0000b3da, 0xff002400, ""}, // + {0x02, 0x0000b3db, 0xff003200, ""}, // + {0x02, 0x0000b3dd, 0xff002400, ""}, // + {0x02, 0x0000b3de, 0x00000600, ""}, // + {0x02, 0x0000b3df, 0xff002400, ""}, // + {0x02, 0x0000b3e0, 0xff002800, ""}, // + {0x02, 0x0000b3e1, 0xff003200, ""}, // + {0x02, 0x0000b3e2, 0xff002400, ""}, // + {0x02, 0x0000b3e3, 0xff002800, ""}, // + {0x02, 0x0000b3e4, 0xff002400, ""}, // + {0x02, 0x0000b3e5, 0xff002400, ""}, // + {0x02, 0x0000b3e6, 0xff002400, ""}, // + {0x02, 0x0000b3e7, 0xff002400, ""}, // + {0x02, 0x0000b3e8, 0xff002400, ""}, // + {0x02, 0x0000b3e9, 0xff002400, ""}, // + {0x02, 0x0000b3ea, 0xff002400, ""}, // + {0x02, 0x0000b3eb, 0xff002400, ""}, // + {0x02, 0x0000b3ec, 0xff002400, ""}, // + {0x02, 0x0000b3ee, 0xff002400, ""}, // + {0x02, 0x0000b3ef, 0xff002400, ""}, // + {0x02, 0x0000b3f0, 0xff002400, ""}, // + {0x02, 0x0000b3f1, 0xff002400, ""}, // + {0x02, 0x0000b3f2, 0xff002800, ""}, // + {0x02, 0x0000b3f3, 0xff002800, ""}, // + {0x02, 0x0000b3f4, 0xff002800, ""}, // + {0x02, 0x0000b3f5, 0xff003200, ""}, // + {0x02, 0x0000b3f6, 0xff002400, ""}, // + {0x02, 0x0000b3f7, 0xff002400, ""}, // + {0x02, 0x0000b3f8, 0xff002400, ""}, // + {0x02, 0x0000b3f9, 0xff002400, ""}, // + {0x02, 0x0000b3fa, 0xff002400, ""}, // + {0x02, 0x0000b3fd, 0xff002400, ""}, // + {0x02, 0x0000b3fe, 0xff002400, ""}, // + {0x02, 0x0000b3ff, 0xff002400, ""}, // + {0x02, 0x0000b400, 0xff002800, ""}, // + {0x02, 0x0000b401, 0xff002400, ""}, // + {0x02, 0x0000b404, 0xff002400, ""}, // + {0x02, 0x0000b405, 0xff002400, ""}, // + {0x02, 0x0000b406, 0xff002400, ""}, // + {0x02, 0x0000b407, 0xff002400, ""}, // + {0x02, 0x0000b798, 0xff002c00, ""}, // + {0x02, 0x0000b799, 0xff002c00, "Coil"}, // + {0x02, 0x0000b79a, 0xff002c00, "Coil"}, // + {0x02, 0x0000fa09, 0xff002800, ""}, // + {0x02, 0x0000fa0b, 0xff002800, ""}, // + {0x02, 0x0000fa0d, 0xff002800, ""}, // + {0x02, 0x0000fa13, 0xff002800, ""}, // + {0x02, 0x0000fa14, 0xff003100, ""}, // + {0x02, 0x0000fa15, 0xff003100, ""}, // + {0x02, 0x0000fa16, 0xff003100, ""}, // + {0x02, 0x0000fa17, 0xff003100, ""}, // + {0x02, 0x0000fa1a, 0xff002800, ""}, // + {0x02, 0x0000fa1b, 0xff003100, ""}, // + {0x02, 0x0000fa22, 0xff002800, ""}, // + {0x02, 0x0000fa23, 0xff003100, ""}, // + {0x02, 0x0000fa25, 0xff003100, ""}, // + {0x02, 0x0000fa26, 0xff002800, ""}, // + {0x02, 0x0000fa29, 0xff003100, ""}, // + {0x02, 0x0000fa2a, 0xff002800, ""}, // + {0x02, 0x0000fa2d, 0xff003100, ""}, // + {0x02, 0x0000fa2e, 0xff002800, ""}, // + {0x02, 0x0000fa37, 0xff002800, ""}, // + {0x02, 0x0000fa38, 0xff003100, ""}, // + {0x02, 0x0000fa3c, 0xff002800, ""}, // + {0x02, 0x0000fa3d, 0xff002800, ""}, // + {0x02, 0x0000fa3e, 0xff003100, ""}, // + {0x02, 0x0000fa3f, 0xff003100, ""}, // + {0x02, 0x0000fa4b, 0xff002800, ""}, // + {0x02, 0x0000fa4c, 0xff002800, ""}, // + {0x02, 0x0000fa4d, 0xff003100, ""}, // + {0x02, 0x0000fa4e, 0xff003100, ""}, // + {0x02, 0x00023283, 0x00000400, ""}, // + {0x03, 0x00000008, 0xfff00200, ""}, // + {0x03, 0x00000065, 0xff002400, ""}, // + {0x03, 0x00000066, 0xff002400, ""}, // + {0x03, 0x0000006f, 0xff002400, ""}, // + {0x03, 0x000017d5, 0xff002a00, ""}, // + {0x03, 0x000017d7, 0xff002a00, ""}, // + {0x03, 0x000017d8, 0xff002a00, ""}, // + {0x03, 0x000017da, 0xff002a00, ""}, // + {0x03, 0x000017db, 0xff002a00, ""}, // + {0x03, 0x000017dd, 0xff002a00, ""}, // + {0x03, 0x000017de, 0xff002400, ""}, // + {0x03, 0x000017df, 0x00177000, ""}, // + {0x03, 0x000017e0, 0x00177000, ""}, // + {0x03, 0x000017e1, 0x00177000, ""}, // + {0x03, 0x000017e2, 0xff002a00, ""}, // + {0x03, 0x000017ef, 0xff002c00, ""}, // + {0x03, 0x000017f0, 0xff002400, ""}, // + {0x03, 0x000017f4, 0xff002400, ""}, // + {0x03, 0x000017f5, 0xff002400, ""}, // + {0x03, 0x0000180a, 0xff002100, ""}, // + {0x03, 0x00001838, 0xff002400, ""}, // + {0x03, 0x00001839, 0xff002400, ""}, // + {0x03, 0x0000183b, 0xff002400, ""}, // + {0x03, 0x0000183d, 0xff002800, ""}, // + {0x03, 0x00001843, 0xff002a00, ""}, // + {0x03, 0x00001844, 0xff002400, ""}, // + {0x03, 0x00001845, 0xff002400, ""}, // + {0x03, 0x00001862, 0xff002400, ""}, // + {0x03, 0x00001863, 0xff002400, ""}, // + {0x03, 0x00001864, 0xff002400, ""}, // + {0x03, 0x00001865, 0xff002400, ""}, // + {0x03, 0x0000a832, 0xff002a00, ""}, // + {0x03, 0x0000afd1, 0xff002800, ""}, // + {0x03, 0x0000afea, 0xff002800, ""}, // + {0x03, 0x0000afeb, 0xff002800, ""}, // + {0x03, 0x0000aff5, 0xff002800, ""}, // + {0x03, 0x0000aff6, 0xff002800, ""}, // + {0x03, 0x0000b3c1, 0xff002400, ""}, // + {0x03, 0x0000b3cf, 0xff002400, ""}, // + {0x03, 0x0000b3e4, 0xff002400, ""}, // + {0x03, 0x0000b3ee, 0xff002400, ""}, // + {0x03, 0x0000b3ef, 0xff002400, ""}, // + {0x03, 0x0000b3f0, 0xff002400, ""}, // + {0x03, 0x0000b3f1, 0xff002400, ""}, // + {0x03, 0x0000fde8, 0x00000100, ""}, // + {0x03, 0x0000fe02, 0x00000e00, "Series DateTime"}, // + {0x03, 0x00023a50, 0xff002400, ""}, // + {0x03, 0x00023a5c, 0xff002400, ""}, // + {0x03, 0x00023a5d, 0xff002400, ""}, // + {0x03, 0x00023a5e, 0xff002100, ""}, // + {0x03, 0x00023a60, 0xff002c00, ""}, // + {0x03, 0x00023a61, 0xff002400, ""}, // + {0x03, 0x00023a62, 0xff002c00, ""}, // + {0x03, 0x00023a79, 0xff002400, ""}, // + {0x03, 0x00023a7a, 0xff002400, ""}, // + {0x03, 0x00023a7b, 0xff002400, ""}, // + {0x03, 0x00023a7c, 0xff002400, ""}, // + {0x04, 0x00000009, 0xfff00200, ""}, // + {0x04, 0x00000067, 0xff002400, "Rows,Columns"}, // + {0x04, 0x00000068, 0xff002400, ""}, // + {0x04, 0x0000006b, 0xff002800, ""}, // + {0x04, 0x0000006c, 0xff002800, ""}, // + {0x04, 0x000017e3, 0xff002400, ""}, // + {0x04, 0x00001808, 0xff002400, ""}, // + {0x04, 0x00001809, 0xff002400, ""}, // + {0x04, 0x00001bc4, 0xff002400, ""}, // + {0x04, 0x00001bc5, 0xff002400, ""}, // + {0x04, 0x00001bcc, 0xff002c00, ""}, // + {0x04, 0x0000a806, 0x00000500, "FOV"}, // + {0x04, 0x0000b3b4, 0x00000b00, ""}, // + {0x04, 0x0000fa06, 0xff002400, ""}, // + {0x04, 0x00014438, 0x00000600, "Orientation Vector 1"}, // + {0x04, 0x00014439, 0x00000600, "Orientation Vector 2"}, // + {0x04, 0x0001443a, 0x00000600, "Orientation Vector 3"}, // + {0x04, 0x0001443b, 0xff002800, "Slice Thickness (meter)"}, // + {0x04, 0x0001e078, 0xff002800, "Echo Time (/1000)"}, // + {0x04, 0x0001e464, 0xff002400, ""}, // + {0x04, 0x0001e465, 0xff002400, ""}, // + {0x04, 0x0001e466, 0xff002400, ""}, // + {0x04, 0x00023a5a, 0xff002400, ""}, // + {0x04, 0x00028873, 0xff002800, "Spacing Between Slices (meter)"}, // + {0x04, 0x00028876, 0x00000400, ""}, // + {0x04, 0x00028877, 0xff002800, "FOV"}, // + {0x04, 0x00028878, 0xff002400, ""}, // + {0x04, 0x00028879, 0xff002400, ""}, // + {0x04, 0x0002887a, 0xff002a00, ""}, // + {0x04, 0x0002887b, 0xff002400, ""}, // + {0x04, 0x0002887c, 0xff002400, ""}, // + {0x05, 0x00000069, 0xff002800, ""}, // + {0x05, 0x0000006b, 0xff002800, ""}, // + {0x05, 0x0000006c, 0xff002800, ""}, // + {0x05, 0x00001bc3, 0xff002200, ""}, // + {0x05, 0x00005603, 0x00000100, ""}, // + {0x05, 0x0000a819, 0xff002400, ""}, // + {0x05, 0x0000fdea, 0xff002400, ""}, // + {0x05, 0x0002bf20, 0xff002a00, ""}, // + {0x05, 0x0002c6f0, 0x00000100, ""}, // + {0x05, 0x0002d691, 0xff002800, "Slice Location (/1000)"}, // + {0x05, 0x0002d695, 0xff002400, "Instance Number"}, // + {0x05, 0x0002d696, 0xff002400, "Instance Number"}, // + {0x05, 0x0002da78, 0x001b5e00, ""}, // + {0x05, 0x0002da79, 0x001b5f00, ""}, // + {0x05, 0x0002da7a, 0xff002000, ""}, // + {0x06, 0x00000c1d, 0xff002400, "Item Index"}, // + {0x06, 0x00036718, 0xff002400, ""}, // + {0x06, 0x00036719, 0x00000600, "Orientation Vector 1"}, // + {0x06, 0x0003671a, 0x00000600, "Orientation Vector 2"}, // + {0x06, 0x0003671b, 0x00000600, "Orientation Vector 3"}, // + {0x06, 0x00036721, 0xff002400, ""}, // + {0x06, 0x00036722, 0xff002a00, ""}, // + {0x06, 0x00036725, 0xff002400, ""}, // + {0x06, 0x0003672a, 0xff002400, ""}, // + {0x07, 0x00000c1d, 0xff002400, ""}, // + {0x07, 0x00036718, 0xff002400, ""}, // + {0x07, 0x00036719, 0x00000600, ""}, // + {0x07, 0x0003671a, 0x00000600, ""}, // + {0x07, 0x0003671b, 0x00000600, ""}, // + {0x07, 0x0003671c, 0xff002800, ""}, // + {0x07, 0x0003671e, 0xff002a00, ""}, // + {0x07, 0x00036721, 0xff002400, ""}, // + {0x07, 0x00036722, 0xff002a00, ""}, // + {0x07, 0x00036723, 0x00000600, ""}, // + {0x07, 0x00036724, 0x00000600, ""}, // + {0x07, 0x00036725, 0xff002400, ""}, // + {0x07, 0x00036727, 0xff002400, ""}, // + {0x07, 0x00036728, 0xff002400, ""}, // + {0x07, 0x0003672a, 0xff002400, ""}, // + {0x07, 0x0003672b, 0x00000600, ""}, // + {0x08, 0x00000c1d, 0xff002400, ""}, // + {0x08, 0x00036718, 0xff002400, ""}, // + {0x08, 0x00036719, 0x00000600, ""}, // + {0x08, 0x0003671a, 0x00000600, ""}, // + {0x08, 0x0003671b, 0x00000600, ""}, // + {0x08, 0x0003671c, 0xff002800, ""}, // + {0x08, 0x0003671e, 0xff002a00, ""}, // + {0x08, 0x00036721, 0xff002400, ""}, // + {0x08, 0x00036722, 0xff002a00, ""}, // + {0x08, 0x00036723, 0x00000600, ""}, // + {0x08, 0x00036724, 0x00000600, ""}, // + {0x08, 0x00036725, 0xff002400, ""}, // + {0x08, 0x00036727, 0xff002400, ""}, // + {0x08, 0x00036728, 0xff002400, ""}, // + {0x08, 0x0003672a, 0xff002400, ""}, // + {0x08, 0x0003672b, 0x00000600, ""}, // + {0x09, 0x00000c1d, 0xff002400, ""}, // + {0x09, 0x00036718, 0xff002400, ""}, // + {0x09, 0x00036719, 0x00000600, ""}, // + {0x09, 0x0003671a, 0x00000600, ""}, // + {0x09, 0x0003671b, 0x00000600, ""}, // + {0x09, 0x0003671c, 0xff002800, ""}, // + {0x09, 0x0003671e, 0xff002a00, ""}, // + {0x09, 0x00036721, 0xff002400, ""}, // + {0x09, 0x00036722, 0xff002a00, ""}, // + {0x09, 0x00036723, 0x00000600, ""}, // + {0x09, 0x00036724, 0x00000600, ""}, // + {0x09, 0x00036725, 0xff002400, ""}, // + {0x09, 0x00036727, 0xff002400, ""}, // + {0x09, 0x00036728, 0xff002400, ""}, // + {0x09, 0x0003672a, 0xff002400, ""}, // + {0x09, 0x0003672b, 0x00000600, ""}, // + {0x0a, 0x00036723, 0x00000600, ""}, // + {0x0a, 0x00036724, 0x00000600, ""}, // + {0x0a, 0x0003672a, 0xff002400, ""}, // + {0x0a, 0x0003672b, 0x00000600, ""}, // + {0x0a, 0x00036722, 0xff002a00, ""}, // + {0x0a, 0x0003671e, 0xff002a00, ""}, // + {0x0a, 0x00036728, 0xff002400, ""}, // + {0x0a, 0x0003671c, 0xff002800, ""}, // + {0x0a, 0x00036727, 0xff002400, ""}, // +}; + +static const uint32_t dict_size = sizeof(dict) / sizeof(*dict); + +void check_mec_mr3_dict() { + const struct mec_mr3_dict *prev = dict + 0; + for (uint32_t i = 1; i < dict_size; ++i) { + const struct mec_mr3_dict *next = dict + i; + if (next->group == prev->group) + assert(next->key > prev->key); + else + assert(next->group > prev->group); + prev = next; + } +} + +bool check_mec_mr3_info(const uint8_t group, const uint32_t key, + const uint32_t type) { + assert(group > 0x0 && group < 0x9); + assert((key & 0xfff00000) == 0x0); + assert((type & 0x000000ff) == 0x0); + const uint32_t sign = type >> 24u; + assert(sign == 0x0 || sign == 0xff); + bool found = false; + for (uint32_t i = 0; i < dict_size; ++i) { + const struct mec_mr3_dict *d = dict + i; + if (group == d->group && key == d->key) { + assert(d->type == type); + found = true; + } + } + return found; +} + +const char *get_mec_mr3_info_name(const uint8_t group, const uint32_t key) { + const char *ret = NULL; + for (uint32_t i = 0; i < dict_size; ++i) { + const struct mec_mr3_dict *d = dict + i; + if (group == d->group && key == d->key) { + ret = d->name; + } + } + return ret; +} diff --git a/Utilities/gdcmext/mec_mr3_dict.h b/Utilities/gdcmext/mec_mr3_dict.h new file mode 100644 index 00000000000..062a71c1f3f --- /dev/null +++ b/Utilities/gdcmext/mec_mr3_dict.h @@ -0,0 +1,32 @@ +/*========================================================================= + + Program: GDCM (Grassroots DICOM). A DICOM library + + Copyright (c) 2006-2011 Mathieu Malaterre + All rights reserved. + See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef MEC_MR3_DICT_H +#define MEC_MR3_DICT_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void check_mec_mr3_dict(void); +bool check_mec_mr3_info(uint8_t group, uint32_t key, uint32_t type); +const char *get_mec_mr3_info_name(uint8_t group, uint32_t key); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif // MEC_MR3_DICT_H diff --git a/Utilities/gdcmext/mec_mr3_io.c b/Utilities/gdcmext/mec_mr3_io.c new file mode 100644 index 00000000000..ff396833bc8 --- /dev/null +++ b/Utilities/gdcmext/mec_mr3_io.c @@ -0,0 +1,862 @@ +/*========================================================================= + + Program: GDCM (Grassroots DICOM). A DICOM library + + Copyright (c) 2006-2011 Mathieu Malaterre + All rights reserved. + See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +#include "mec_mr3_io.h" + +#include "mec_mr3_dict.h" + +#include +#include +#include +#include +#include +#include + +#ifndef _MSC_VER +#include +#endif +#if defined(_MSC_VER) && (_MSC_VER < 1900) +#define snprintf _snprintf +#endif + +struct stream { + const void *start; + const void *end; + void *cur; + size_t (*read)(void *ptr, size_t size, size_t nmemb, struct stream *in); +}; + +static size_t stream_read(void *ptr, size_t size, size_t nmemb, + struct stream *in) { + char *cur = (char *)in->cur; + const char *end = (const char *)in->end; + const size_t len = size * nmemb; + if (cur + len <= end) { + memcpy(ptr, cur, len); + in->cur = cur + len; + } else { + in->cur = NULL; + return 0; + } + return nmemb; +} + +struct app { + struct stream *in; +#ifndef _MSC_VER + iconv_t conv; +#endif + void *shift_jis_buffer; +}; + +static struct app *create_app(struct app *self, struct stream *in) { + self->in = in; +#ifndef _MSC_VER + self->conv = iconv_open("utf-8", "shift-jis"); + assert(self->conv != (iconv_t)-1); +#endif + self->shift_jis_buffer = NULL; + + return self; +} + +static void setup_buffer(struct app *self, const void *input, size_t len) { + self->in->cur = (char *)input; + self->in->start = input; + self->in->end = (char *)input + len; + self->in->read = stream_read; +} + +#define ERROR_RETURN(X, Y) \ + if ((X) != (Y)) return false + +static size_t fread_mirror(void *ptr, size_t size, size_t nmemb, + struct app *self) { + struct stream *instream = self->in; + + size_t s = instream->read(ptr, size, nmemb, instream); + if (s == nmemb) { + return nmemb; + } + assert(0); + return s; +} + +static bool write_trailer(struct app *self) { + assert(self->in->cur <= self->in->end); + if (self->in->cur == self->in->end) return true; + // else it is missing one byte (nul byte): + char padding; + size_t s = fread_mirror(&padding, sizeof padding, 1, self); + ERROR_RETURN(s, 1); + ERROR_RETURN(padding, 0); + + return true; +} + +struct mec_mr3_info { + uint32_t key; + uint32_t type; +}; + +struct mec_mr3_item_data { + uint32_t len; + void *buffer; + size_t size; // aligned/realloc implementation detail +}; + +static const uint32_t magic2[] = {0, 0, 12, 0, 0}; + +static bool read_info(struct app *self, const uint8_t group, + struct mec_mr3_info *info) { + // read key and type at once: + size_t s = fread_mirror(info, sizeof *info, 1, self); + ERROR_RETURN(s, 1); +#ifdef MEC_MR3_IO_DEBUG + bool found = check_mec_mr3_info(group, info->key, info->type); + ERROR_RETURN(found, true); +#endif + + return true; +} + +static void *aligned_alloc_impl(size_t alignment, size_t size) { +#ifdef _MSC_VER + return _aligned_malloc(size, alignment); +#else + // return aligned_alloc(alignment, size); + void *allocPtr; + int error = posix_memalign(&allocPtr, alignment, size); + // posix_memalign() returns zero on success + return error == 0 ? allocPtr : NULL; +#endif +} + +static struct mec_mr3_item_data *mec_mr3_aligned_realloc( + struct mec_mr3_item_data *data, size_t size) { + if (!data) return NULL; + // fast path + if (size <= data->size) { + return data; + } + // else need to reallocate + const size_t guesstimate = size < 4096 ? 4096 : 2 * size; + void *buffer = aligned_alloc_impl(64u, guesstimate); + if (data->buffer) free(data->buffer); + if (!buffer) return NULL; + data->buffer = buffer; + data->size = guesstimate; + return data; +} + +static bool is_aligned(const void *pointer, size_t byte_count) { + // https://stackoverflow.com/questions/1898153/how-to-determine-if-memory-is-aligned + return (uintptr_t)pointer % byte_count == 0; +} + +enum SignatureType { SIG_UNK = 0, SIG_SIMPLE = 1, SIG_COMPLEX = 2 }; +static enum SignatureType compute_signature(const uint32_t sig[5]) { + // fast path: {0, 0, 12, 0, 0} + const int b = memcmp(sig, magic2, sizeof(magic2)); + if (b == 0) return SIG_SIMPLE; + // check the complex one: + // [0,67937544,12,0,235348672] #20 + // [0,226469240,12,0,235348704] #20 + const bool sig_complex = sig[0] == 0 && sig[2] == 12 && sig[3] == 0; + if (sig_complex) return SIG_COMPLEX; + return SIG_UNK; +} + +static bool read_data(struct app *self, const uint8_t group, + const struct mec_mr3_info *info, + struct mec_mr3_item_data *data) { + (void)group; + (void)info; + size_t s = fread_mirror(&data->len, sizeof data->len, 1, self); + ERROR_RETURN(s, 1); + // in the wild we have: data->len <= 9509 + uint32_t separator[5]; + s = fread_mirror(separator, sizeof *separator, + sizeof separator / sizeof *separator, self); + ERROR_RETURN(s, sizeof separator / sizeof *separator); + const enum SignatureType sig_ok = compute_signature(separator); + ERROR_RETURN(sig_ok != SIG_UNK, true); + data = mec_mr3_aligned_realloc(data, data->len); + if (data == NULL) { + return false; + } + + s = fread_mirror(data->buffer, 1, data->len, self); + ERROR_RETURN(s, data->len); + + return true; +} + +enum Type { + ISO_8859_1_STRING = + 0x00000300, // ASCII string / or struct with 'ISO-8859-1' marker + FLOAT32_VM2N = 0x00000500, // float/32bits VM:2n + FLOAT32_VM3N = 0x00000600, // float/32bits VM:3n + DATETIME = 0x00000e00, // Date/Time stored as ASCII VM:1 + STRUCT_136 = + 0x001f4100, // Fixed struct 136 bytes (struct with ASCII strings) + STRUCT_436 = + 0x001f4300, // Fixed struct 436 bytes (struct with ASCII strings) + STRUCT_516 = + 0x001f4400, // Fixed struct 516 bytes (struct with ASCII strings) + STRUCT_325 = + 0x001f4600, // Fixed struct 325 bytes (struct with ASCII strings) + UINT32_VM1 = (int)0xff000400, // uint32_t, range [0, 4] VM:1 + FLOAT32_VM1 = (int)0xff000800, // float/32bits VM:1 + INT32_VM1N = (int)0xff002400, // int32_t (signed) VM:1n + FLOAT32_VM1N = (int)0xff002800, // float/32bits VM:1n + FLOAT64_VM1 = (int)0xff002900, // float/64bits VM:1 + BOOL32_VM1 = (int)0xff002a00, // bool/32bits VM:1 + UNICODE_STRING = (int)0xff002c00, // ASCII, UTF-8 or SHIFT-JIS string +}; + +struct buffer19 { + char sig1[0x3]; + unsigned char len2; + char sig2; + unsigned char len3; + char sig3; + char iso[0x9]; + char sig4; + unsigned char len4; + char sig5; +}; + +#if 0 +static void dump2file(const char *in, int len) { + static int debug = 0; + char buffer[512]; + sprintf(buffer, "out%04d", debug); + ++debug; + FILE *f = fopen(buffer, "wb"); + fwrite(in, 1, len, f); + fclose(f); +} +#endif + +// https://stackoverflow.com/questions/28270310/how-to-easily-detect-utf8-encoding-in-the-string +static bool is_valid_utf8(const char *string) { + if (!string) return true; + + const unsigned char *bytes = (const unsigned char *)string; + unsigned int cp; + int num; + + while (*bytes != 0x00) { + if ((*bytes & 0x80) == 0x00) { + // U+0000 to U+007F + cp = (*bytes & 0x7F); + num = 1; + } else if ((*bytes & 0xE0) == 0xC0) { + // U+0080 to U+07FF + cp = (*bytes & 0x1F); + num = 2; + } else if ((*bytes & 0xF0) == 0xE0) { + // U+0800 to U+FFFF + cp = (*bytes & 0x0F); + num = 3; + } else if ((*bytes & 0xF8) == 0xF0) { + // U+10000 to U+10FFFF + cp = (*bytes & 0x07); + num = 4; + } else + return false; + + bytes += 1; + for (int i = 1; i < num; ++i) { + if ((*bytes & 0xC0) != 0x80) return false; + cp = (cp << 6) | (*bytes & 0x3F); + bytes += 1; + } + + if ((cp > 0x10FFFF) || ((cp >= 0xD800) && (cp <= 0xDFFF)) || + ((cp <= 0x007F) && (num != 1)) || + ((cp >= 0x0080) && (cp <= 0x07FF) && (num != 2)) || + ((cp >= 0x0800) && (cp <= 0xFFFF) && (num != 3)) || + ((cp >= 0x10000) && (cp <= 0x1FFFFF) && (num != 4))) + return false; + } + + return true; +} + +// return -1 to indicate error: +static int remove_control_character_utf8(char *string) { + if (!string) return 0; + + unsigned char *bytes = (unsigned char *)string; + unsigned int cp; + int num; + int modified = 0; + + while (*bytes != 0x00) { + if ((*bytes & 0x80) == 0x00) { + // U+0000 to U+007F + cp = (*bytes & 0x7F); + num = 1; + } else if ((*bytes & 0xE0) == 0xC0) { + // U+0080 to U+07FF + cp = (*bytes & 0x1F); + num = 2; + } else if ((*bytes & 0xF0) == 0xE0) { + // U+0800 to U+FFFF + cp = (*bytes & 0x0F); + num = 3; + } else if ((*bytes & 0xF8) == 0xF0) { + // U+10000 to U+10FFFF + cp = (*bytes & 0x07); + num = 4; + } else + return -1; + + bytes += 1; + for (int i = 1; i < num; ++i) { + if ((*bytes & 0xC0) != 0x80) return -1; + cp = (cp << 6) | (*bytes & 0x3F); + bytes += 1; + } + + if ((cp > 0x10FFFF) || ((cp >= 0xD800) && (cp <= 0xDFFF)) || + ((cp <= 0x007F) && (num != 1)) || + ((cp >= 0x0080) && (cp <= 0x07FF) && (num != 2)) || + ((cp >= 0x0800) && (cp <= 0xFFFF) && (num != 3)) || + ((cp >= 0x10000) && (cp <= 0x1FFFFF) && (num != 4))) + return -1; + + if (cp <= 0x001F && num == 1) { + bytes[-1] = '.'; + modified++; + } else if (cp == 0x007F && num == 1) { + bytes[-1] = '?'; + modified++; + } + } + + return modified; +} + +static char *shift_jis_to_utf8(char *str, size_t len, struct app *self) { + if (len == 0) { + return ""; + } + const size_t guesstimate = len < 128 ? 128 : len * 2; + self->shift_jis_buffer = realloc(self->shift_jis_buffer, guesstimate); + char *dest_str = self->shift_jis_buffer; +#ifndef _MSC_VER + char *in_str = str; + char *out_str = dest_str; + size_t inbytes = len; + size_t outbytes = guesstimate; + if (iconv(self->conv, &in_str, &inbytes, &out_str, &outbytes) == (size_t)-1) { +#if 0 + // at this point both gbk_str & inbytes have been modified, prefer original + // values: + dump2file(str, len); + printf("[%.*s]", (int)len, str); + fflush(stdout); +#endif + return NULL; + } + dest_str[guesstimate - outbytes] = 0; +#else + // guesstimate imply at least 128 bytes: + strcpy(dest_str, "No iconv support"); +#endif + assert(is_valid_utf8(dest_str)); + return dest_str; +} + +static bool print_iso(void *ptr, size_t size, size_t nmemb, struct app *self) { + assert(size == 1); + static const char magic[] = {0xdf, 0xff, 0x79}; + if (nmemb >= sizeof magic && memcmp(ptr, magic, sizeof(magic)) == 0) { + // iso + struct buffer19 b19; + if (nmemb < sizeof b19) return 0; + memcpy(&b19, ptr, sizeof b19); + if (b19.sig2 != 0x1 || b19.sig3 != 0x0 || b19.sig4 != 0x2 || + b19.sig5 != 0x0) + return 0; + const size_t diff = nmemb - sizeof b19; + if (b19.len2 != nmemb - 4 || b19.len3 != 9 || b19.len4 != diff) return 0; + if (strncmp(b19.iso, "ISO8859-1", 9) != 0) return 0; + char *str = (char *)ptr + sizeof b19; + { + char *dest_str = shift_jis_to_utf8(str, b19.len4, self); + assert(dest_str != NULL); + const int modified = remove_control_character_utf8(dest_str); + assert(modified == 0); + printf("{%.*s : %s}", 9, b19.iso, dest_str); + } + } else { + // raw string buffer + printf("\"%.*s\"", (int)nmemb, (char *)ptr); + } + return true; +} + +static bool print_datetime(void *ptr, size_t size, size_t nmemb, + struct app *self) { + // 11/12/2002,11:27:32 + assert(size == 1); + (void)self; + assert(nmemb == 19 || nmemb == 20); + char *str = (char *)ptr; + size_t i; + const size_t len = strnlen(str, nmemb); + assert(len == 19); + for (i = 0; i < len; ++i) { + assert((str[i] >= '0' && str[i] <= '9') || str[i] == '/' || str[i] == ',' || + str[i] == ':'); + } + + printf("\"%.*s\"", (int)nmemb, str); + return true; +} + +typedef char str16[16 + 1]; +typedef char str64[64 + 1]; + +struct buffer136 { + uint32_t zero1; + str64 + uid1; // Detached Study Management SOP Class (1.2.840.10008.3.1.2.3.1) ? + str64 uid2; // 1.2.840.113745.101000.1098000.X.Y.Z + uint16_t zero2; +}; + +void print_buffer136(struct buffer136 *b136) { + assert(b136->zero1 == 0); + assert(b136->zero2 == 0); + printf("{%u,%s,%s,%hu}", b136->zero1, b136->uid1, b136->uid2, b136->zero2); +} + +struct buffer436 { + uint32_t zero; + char iver[0x45]; + char buf3[0x100]; // phi + str64 buf4; + str16 buf5; + char modality[0x15]; + uint32_t val; +}; + +static void print_buffer436(struct buffer436 *b436) { +#if 0 + static const char vers1[] = "TM_MR_DCM_V1.0"; + static const char vers2[] = "TM_MR_DCM_V2.0"; + static const char vers3[] = "TM_MR_DCM_V1.0_3"; + static const char vers4[] = "TM_MR1_DCM_V1.0"; + assert(strcmp(b436->iver, vers1) == 0 || strcmp(b436->iver, vers2) == 0 || + strcmp(b436->iver, vers3) == 0 || strcmp(b436->iver, vers4) == 0); +#endif + assert(b436->zero == 0); + assert(strcmp(b436->modality, "MR") == 0); +#if 0 + assert(b436->val == 0 || b436->val == 1 || b436->val == 3 || b436->val == 4); +#endif + printf("{%u;%s;%s;%s;%s;%s;%u}", b436->zero, b436->iver, b436->buf3, + b436->buf4, b436->buf5, b436->modality, b436->val); +} + +struct buffer516 { + str64 zero; // aka 'none' + char buf2[0x15]; + char buf3[0x100]; // phi + str16 buf4; + str64 buf5; // Study Instance UID + str64 buf6; + uint32_t bools[6]; +}; + +static void print_buffer516(struct buffer516 *b516) { + printf("{%s;%s;%s;%s;%s;%s", b516->zero, b516->buf2, b516->buf3, b516->buf4, + b516->buf5, b516->buf6); + uint32_t c; + for (c = 0; c < 6; ++c) { + assert(b516->bools[c] == c % 2); +#if 0 + if (c) + printf(","); + printf("%d", b516->bools[c]); +#endif + } + printf("}"); +} + +struct buffer325 { + str64 array[5]; +}; + +static void print_buffer325(struct buffer325 *b325) { + int c; + printf("{"); + for (c = 0; c < 5; ++c) { + if (c) printf(";"); + printf("%s", b325->array[c]); + } + printf("}"); +} + +static bool print_struct(void *ptr, size_t size, size_t nmemb, + struct app *self) { + (void)self; + assert(size == 1); + const size_t s = nmemb; + if (s == 136) { + struct buffer136 b136; + memcpy(&b136, ptr, nmemb); + print_buffer136(&b136); + } else if (s == 436) { + struct buffer436 b436; + memcpy(&b436, ptr, nmemb); + print_buffer436(&b436); + } else if (s == 516) { + struct buffer516 b516; + memcpy(&b516, ptr, nmemb); + print_buffer516(&b516); + } else if (s == 325) { + struct buffer325 b325; + memcpy(&b325, ptr, nmemb); + print_buffer325(&b325); + } else { + assert(0); // programmer error + return 0; + } + return true; +} + +static bool print_shift_jis(void *ptr, size_t size, size_t nmemb, + struct app *self) { + assert(size == 1); + char *dest_str = shift_jis_to_utf8(ptr, nmemb, self); + if (dest_str) { + const int modified = remove_control_character_utf8(dest_str); + assert(modified >= 0); + printf("|%sSJIS| \"%s\"", modified > 0 ? "?-" : "", dest_str); + } else { + char *str = ptr; + const size_t len = strlen(str); + assert(len == nmemb || (len + 1 == nmemb && str[len] == 0)); + const bool ok = is_valid_utf8(str); + if (ok) { + const int modified = remove_control_character_utf8(str); + assert(modified >= 0); + printf("|%sUTF-8| \"%s\"", modified > 0 ? "?-" : "", str); + } else { + printf("|FIXME: Invalid SHIFT-JIS/UTF-8|"); + } + } + return true; +} + +static void print_int(const int32_t *buffer, int len) { + const int m = sizeof(int32_t); + assert(is_aligned(buffer, m)); + assert(len % m == 0); + int i; + printf("["); + for (i = 0; i < len / m; i++) { + if (i) printf(","); + int32_t cur = -1; + memcpy(&cur, buffer + i, sizeof cur); + printf("%d", cur); + } + printf("]"); +} + +static void print_float(const float *buffer, int len) { + const int m = sizeof(float); + assert(is_aligned(buffer, m)); + assert(len % m == 0); + int i; + printf("["); + for (i = 0; i < len / m; i++) { + if (i) printf(","); + float cur = -1; + memcpy(&cur, buffer + i, sizeof cur); + assert(isfinite(cur) && !isnan(cur)); + printf("%f", cur); + } + printf("]"); +} + +static void print_double(const double *buffer, int len) { + const int m = sizeof(double); + assert(is_aligned(buffer, m)); + assert(len % m == 0); + int i; + printf("["); + for (i = 0; i < len / m; i++) { + if (i) printf(","); + const double cur = buffer[i]; + assert(isfinite(cur) && !isnan(cur)); + printf("%g", cur); + } + printf("]"); +} + +static bool print_int32(void *ptr, size_t size, size_t nmemb, + struct app *self) { + assert(size == 1); + (void)self; + // assert(nmemb == 4 || nmemb == 8 || nmemb == 12 || nmembnmemb == 24 || nmemb + // == 32 || nmemb == 48); + assert(nmemb % 4 == 0); + print_int(ptr, nmemb); + + return true; +} + +static bool print_float32(void *ptr, size_t size, size_t nmemb, + struct app *self) { + assert(size == 1); + (void)self; + assert(nmemb == 4); + print_float(ptr, nmemb); + + return true; +} + +static bool print_float32_vm1n(void *ptr, size_t size, size_t nmemb, + struct app *self) { + assert(size == 1); + (void)self; + assert(nmemb % 4 == 0); + print_float(ptr, nmemb); + + return true; +} + +static bool print_float32_vm2n(void *ptr, size_t size, size_t nmemb, + struct app *self) { + assert(size == 1); + (void)self; + assert((nmemb / 4) % 2 == 0); + assert(nmemb == 8 || nmemb == 40 || nmemb == 80 || nmemb == 88); + // FIXME: low/high value for nmemb==40&80 makes them look like double... + print_float(ptr, nmemb); + + return true; +} + +static bool print_float32_vm3n(void *ptr, size_t size, size_t nmemb, + struct app *self) { + assert(size == 1); + (void)self; + assert((nmemb / 4) % 3 == 0); + assert(nmemb == 12 || nmemb == 36); + print_float(ptr, nmemb); + + return true; +} + +static bool print_float64(void *ptr, size_t size, size_t nmemb, + struct app *self) { + assert(size == 1); + (void)self; + assert(nmemb == 8); + print_double(ptr, nmemb); + return true; +} + +static bool print_uint32(void *ptr, size_t size, size_t nmemb, + struct app *self) { + assert(size == 1); + assert(is_aligned(ptr, 4)); + (void)self; + assert(nmemb == 4); + uint32_t u; + memcpy(&u, ptr, nmemb); + assert(u == 0x0 || u == 0x1 || u == 0x4); + printf("%u", u); + return true; +} + +static bool print_bool32(void *ptr, size_t size, size_t nmemb, + struct app *self) { + assert(size == 1); + assert(is_aligned(ptr, 4)); + (void)self; + assert(nmemb == 4); + uint32_t u; + memcpy(&u, ptr, nmemb); + assert(u == 0x0 || u == 0x1); + printf("%s", u ? "true" : "false"); + return true; +} + +static bool print(struct app *self, const uint8_t group, + const struct mec_mr3_info *info, + struct mec_mr3_item_data *data) { + const char *name = get_mec_mr3_info_name(group, info->key); + const uint32_t sign = info->type >> 24; + const char symb = sign ? '_' : ' '; + + bool ret = true; + uint32_t mult = 1; + // print info + printf("(%01x,%05x) %c%04x ", group, info->key, symb, + (info->type & 0x00ffff00) >> 8); + // print data: + switch (info->type) { + case ISO_8859_1_STRING: + ret = print_iso(data->buffer, 1, data->len, self); + break; + case FLOAT32_VM2N: + ret = print_float32_vm2n(data->buffer, 1, data->len, self); + break; + case FLOAT32_VM3N: + ret = print_float32_vm3n(data->buffer, 1, data->len, self); + break; + case DATETIME: + ret = print_datetime(data->buffer, 1, data->len, self); + break; + case STRUCT_136: + case STRUCT_436: + case STRUCT_516: + case STRUCT_325: + ret = print_struct(data->buffer, 1, data->len, self); + break; + case UNICODE_STRING: + ret = print_shift_jis(data->buffer, 1, data->len, self); + break; + case FLOAT32_VM1: + ret = print_float32(data->buffer, 1, data->len, self); + break; + case INT32_VM1N: + ret = print_int32(data->buffer, 1, data->len, self); + break; + case FLOAT32_VM1N: + ret = print_float32_vm1n(data->buffer, 1, data->len, self); + break; + case FLOAT64_VM1: + ret = print_float64(data->buffer, 1, data->len, self); + break; + case UINT32_VM1: + ret = print_uint32(data->buffer, 1, data->len, self); + break; + case BOOL32_VM1: + ret = print_bool32(data->buffer, 1, data->len, self); + break; + default: + printf("|NotImplemented|"); + ret = true; + } + // print key name + if (!name) { + static char buf[512]; + snprintf(buf, sizeof buf, "Missing: {0x%02x, 0x%08x, 0x%08x, \"\"}, //", + group, info->key, info->type); + name = buf; + } + printf(" # %u,%u %s\n", data->len, mult, name); + + return ret; +} + +static bool read_group(struct app *self, uint8_t group, uint32_t nitems, + struct mec_mr3_info *info, + struct mec_mr3_item_data *data) { + bool good = true; + uint32_t i; + for (i = 0; i < nitems && good; ++i) { + good = good && read_info(self, group, info); + // lazy evaluation: + good = good && read_data(self, group, info, data); + good = good && print(self, group, info, data); + } + return good; +} + +// If the number of element read is below the magic value, this indicate the +// last groups of elements: +#define MAGIC_NUM_ELEMENTS 5 + +bool mec_mr3_print(const void *input, size_t len) { + if (!input) return false; + struct stream sin; + struct app a; + struct app *self = create_app(&a, &sin); + setup_buffer(self, input, len); + + bool good = true; + struct mec_mr3_info info; + struct mec_mr3_item_data data; + data.size = data.len = 0; + data.buffer = NULL; + + uint32_t remain = 1; + size_t s; + bool last_groups = false; + uint8_t group = 0; + // read until last set of groups found: + while (!last_groups && good) { + uint32_t nitems; + s = fread_mirror(&nitems, sizeof nitems, 1, self); + if (s != 1 || nitems == 0) { + good = false; + } + if (good && nitems <= MAGIC_NUM_ELEMENTS) { + // special case to handle last groups + remain = nitems; + last_groups = true; + s = fread_mirror(&nitems, sizeof nitems, 1, self); + if (s != 1 || nitems == 0) { + good = false; + } + } + // lazy evaluation + ++group; + good = good && read_group(self, group, nitems, &info, &data); + } + // read remaining groups: + while (good && --remain != 0) { + uint32_t nitems; + s = fread_mirror(&nitems, sizeof nitems, 1, self); + if (s != 1 || nitems <= MAGIC_NUM_ELEMENTS) { + good = false; + } + ++group; + good = good && read_group(self, group, nitems, &info, &data); + } + // release memory: +#ifdef _MSC_VER + _aligned_free(data.buffer); +#else + free(data.buffer); +#endif +#ifndef _MSC_VER + iconv_close(self->conv); +#endif + free(self->shift_jis_buffer); + if (!good) return false; + + // write trailer: + if (!write_trailer(self)) { + return false; + } + + // make sure the whole input was processed: + assert(self->in->cur <= self->in->end); // programmer error + if (self->in->cur < self->in->end) { + return false; + } + return true; +} diff --git a/Utilities/gdcmext/mec_mr3_io.h b/Utilities/gdcmext/mec_mr3_io.h new file mode 100644 index 00000000000..1e13853a818 --- /dev/null +++ b/Utilities/gdcmext/mec_mr3_io.h @@ -0,0 +1,30 @@ +/*========================================================================= + + Program: GDCM (Grassroots DICOM). A DICOM library + + Copyright (c) 2006-2011 Mathieu Malaterre + All rights reserved. + See Copyright.txt or http://gdcm.sourceforge.net/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#ifndef MEC_MR3_IO_H +#define MEC_MR3_IO_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +bool mec_mr3_print(const void *input, size_t len); + +#ifdef __cplusplus +} /* end extern "C" */ +#endif + +#endif // MEC_MR3_IO_H diff --git a/Utilities/gdcmrle/rle.cxx b/Utilities/gdcmrle/rle.cxx index 143827d25c0..a6a1d11caaa 100644 --- a/Utilities/gdcmrle/rle.cxx +++ b/Utilities/gdcmrle/rle.cxx @@ -117,7 +117,7 @@ bool rle_encoder::write_header( dest & d ) const int nsegs = pt.compute_num_segments(); internals->invalues.resize( w * nsegs ); - char * buffer = &internals->invalues[0]; + char * buffer = internals->invalues.data(); size_t buflen = internals->invalues.size(); header & rh = internals->rh; @@ -269,21 +269,21 @@ int rle_encoder::encode_row( dest & d ) internals->invalues.resize( w * numsegs ); internals->outvalues.resize( w * 2 ); // worse possible case ? - src->read_into_segments( &internals->invalues[0], internals->invalues.size(), internals->img ); + src->read_into_segments( internals->invalues.data(), internals->invalues.size(), internals->img ); header::ul *comp_pos = internals->comp_pos; int n = 0; for( int s = 0; s < numsegs; ++s ) { const int ret = encode_row_internal( - &internals->outvalues[0], internals->outvalues.size(), - &internals->invalues[0] + s * w, w ); + internals->outvalues.data(), internals->outvalues.size(), + internals->invalues.data() + s * w, w ); if( ret < 0 ) return -1; n += ret; const bool b = d.seek( comp_pos[s] ); if( !b ) return -1; - if( d.write( &internals->outvalues[0], ret ) < 0 ) return -1; + if( d.write( internals->outvalues.data(), ret ) < 0 ) return -1; comp_pos[s] += ret; } @@ -513,7 +513,7 @@ int rle_decoder::decode_row( dest & d ) const size_t scanlen = internals->img.get_width() * nsegs; internals->scanline.resize( scanlen ); - char * scanbuf = &internals->scanline[0]; + char * scanbuf = internals->scanline.data(); int numOutBytesFull = 0; for( int c = 0; c < nc; ++c ) diff --git a/Utilities/gdcmutfcpp/README.GDCM.txt b/Utilities/gdcmutfcpp/README.GDCM.txt index c9420f21b31..36d9195bf0b 100644 --- a/Utilities/gdcmutfcpp/README.GDCM.txt +++ b/Utilities/gdcmutfcpp/README.GDCM.txt @@ -11,3 +11,7 @@ http://sourceforge.net/projects/utfcpp/files/utf8cpp_2x/Release%202.3.4/utf8_v2_ SHA 256 checksum: 3373cebb25d88c662a2b960c4d585daf9ae7b396031ecd786e7bb31b15d010ef + +New location is: + +* https://github.com/nemtrif/utfcpp diff --git a/Utilities/gdcmuuid/CMakeLists.txt b/Utilities/gdcmuuid/CMakeLists.txt index b4503396ab3..cd3083bf656 100644 --- a/Utilities/gdcmuuid/CMakeLists.txt +++ b/Utilities/gdcmuuid/CMakeLists.txt @@ -25,7 +25,9 @@ include_regular_expression("^.*$") set(UUID_SRCS compare.c +copy.c gen_uuid.c +isnull.c pack.c parse.c unpack.c diff --git a/Utilities/gdcmuuid/COPYING b/Utilities/gdcmuuid/COPYING index 8dcc0ee95c3..2f17068367d 100644 --- a/Utilities/gdcmuuid/COPYING +++ b/Utilities/gdcmuuid/COPYING @@ -1,31 +1,25 @@ -/* - * Copyright (C) 1996, 1997 Theodore Ts'o. - * - * %Begin-Header% - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, and the entire permission notice in its entirety, - * including the disclaimer of warranties. - * 2. 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. - * 3. The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF - * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 NOT ADVISED OF THE POSSIBILITY OF SUCH - * DAMAGE. - * %End-Header% - */ +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, and the entire permission notice in its entirety, + including the disclaimer of warranties. +2. 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. +3. The name of the author may not be used to endorse or promote + products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF +WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 NOT ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. diff --git a/Utilities/gdcmuuid/compare.c b/Utilities/gdcmuuid/compare.c index b2c0d3a00b5..d5fc5037a1d 100644 --- a/Utilities/gdcmuuid/compare.c +++ b/Utilities/gdcmuuid/compare.c @@ -1,4 +1,3 @@ -/* vi: set sw=4 ts=4: */ /* * compare.c --- compare whether or not two UUID's are the same * @@ -35,6 +34,7 @@ * %End-Header% */ +#include "config.h" #include "uuidP.h" #include @@ -42,14 +42,15 @@ int uuid_compare(const uuid_t uu1, const uuid_t uu2) { - struct uuid uuid1, uuid2; + struct uuid uuid1, uuid2; - uuid_unpack(uu1, &uuid1); - uuid_unpack(uu2, &uuid2); + uuid_unpack(uu1, &uuid1); + uuid_unpack(uu2, &uuid2); - UUCMP(uuid1.time_low, uuid2.time_low); - UUCMP(uuid1.time_mid, uuid2.time_mid); - UUCMP(uuid1.time_hi_and_version, uuid2.time_hi_and_version); - UUCMP(uuid1.clock_seq, uuid2.clock_seq); - return memcmp(uuid1.node, uuid2.node, 6); + UUCMP(uuid1.time_low, uuid2.time_low); + UUCMP(uuid1.time_mid, uuid2.time_mid); + UUCMP(uuid1.time_hi_and_version, uuid2.time_hi_and_version); + UUCMP(uuid1.clock_seq, uuid2.clock_seq); + return memcmp(uuid1.node, uuid2.node, 6); } + diff --git a/Utilities/gdcmuuid/config.h b/Utilities/gdcmuuid/config.h new file mode 100644 index 00000000000..ae561f3588c --- /dev/null +++ b/Utilities/gdcmuuid/config.h @@ -0,0 +1 @@ +/* No content required. File created so that it can be included as expected from other .c files. */ diff --git a/Utilities/gdcmuuid/copy.c b/Utilities/gdcmuuid/copy.c new file mode 100644 index 00000000000..32e6f502d12 --- /dev/null +++ b/Utilities/gdcmuuid/copy.c @@ -0,0 +1,46 @@ +/* + * copy.c --- copy UUIDs + * + * Copyright (C) 1996, 1997 Theodore Ts'o. + * + * %Begin-Header% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 NOT ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * %End-Header% + */ + +#include "config.h" +#include "uuidP.h" + +void uuid_copy(uuid_t dst, const uuid_t src) +{ + unsigned char *cp1; + const unsigned char *cp2; + int i; + + for (i=0, cp1 = dst, cp2 = src; i < 16; i++) + *cp1++ = *cp2++; +} diff --git a/Utilities/gdcmuuid/gen_uuid.c b/Utilities/gdcmuuid/gen_uuid.c index f6ee8bcb498..14c98eb4af6 100644 --- a/Utilities/gdcmuuid/gen_uuid.c +++ b/Utilities/gdcmuuid/gen_uuid.c @@ -1,4 +1,3 @@ -/* vi: set sw=4 ts=4: */ /* * gen_uuid.c --- generate a DCE-compatible uuid * @@ -38,7 +37,15 @@ * gcc-wall wall mode */ #define _SVID_SOURCE +#define _DEFAULT_SOURCE /* since glibc 2.20 _SVID_SOURCE is deprecated */ +#include "config.h" + +#ifdef _WIN32 +#define _WIN32_WINNT 0x0500 +#include +#define UUID MYUUID +#endif #include #ifdef HAVE_UNISTD_H #include @@ -48,22 +55,30 @@ #endif #include #include -#include #include #include +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_SYS_WAIT_H +#include +#endif #include #ifdef HAVE_SYS_FILE_H #include #endif -#if HAVE_SYS_TIME_H -#include -#endif #ifdef HAVE_SYS_IOCTL_H #include #endif +#ifdef HAVE_SYS_RANDOM_H +#include +#endif #ifdef HAVE_SYS_SOCKET_H #include #endif +#ifdef HAVE_SYS_UN_H +#include +#endif #ifdef HAVE_SYS_SOCKIO_H #include #endif @@ -76,82 +91,83 @@ #ifdef HAVE_NET_IF_DL_H #include #endif -#ifdef HAVE_WINSOCK_H -#include /* timeval */ +#if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H) +#include +#endif +#ifdef HAVE_SYS_RESOURCE_H +#include #endif #include "uuidP.h" +#include "uuidd.h" #ifdef HAVE_SRANDOM -#define srand(x) srandom(x) -#define rand() random() +#define srand(x) srandom(x) +#define rand() random() #endif -#if defined(_WIN32) -/* offer a limited gettimeofday on Win32 system */ -#include -static int gettimeofday(struct timeval *tv, struct timezone *tz) -{ - FILETIME ft; - const uint64_t c1 = 27111902; - const uint64_t c2 = 3577643008UL; - const uint64_t OFFSET = (c1 << 32) + c2; - uint64_t filetime; - GetSystemTimeAsFileTime(&ft); - - filetime = ft.dwHighDateTime; - filetime = filetime << 32; - filetime += ft.dwLowDateTime; - filetime -= OFFSET; - - memset(tv,0, sizeof(*tv)); - assert( sizeof(*tv) == sizeof(struct timeval)); - tv->tv_sec = (time_t)(filetime / 10000000); /* seconds since epoch */ - tv->tv_usec = (uint32_t)((filetime % 10000000) / 10); - - return 0; -} -/* provide unimplemented open call */ -#define O_NONBLOCK 0 -int open(const char *pathname, int flags) -{ - return -1; -} -typedef int pid_t; -pid_t getpid(void) -{ - return 0; -} -typedef int uid_t; -uid_t getuid(void) -{ - return 0; -} -typedef int ssize_t; -ssize_t read(int fd, void *buf, size_t count) +#ifdef TLS +#define THREAD_LOCAL static TLS +#else +#define THREAD_LOCAL static +#endif + +#if defined(__linux__) && defined(__NR_gettid) && defined(HAVE_JRAND48) +#define DO_JRAND_MIX +THREAD_LOCAL unsigned short jrand_seed[3]; +#endif + +#ifdef _WIN32 +#ifndef USE_MINGW +static void gettimeofday (struct timeval *tv, void *dummy) { - return -1; + FILETIME ftime; + uint64_t n; + + GetSystemTimeAsFileTime (&ftime); + n = (((uint64_t) ftime.dwHighDateTime << 32) + + (uint64_t) ftime.dwLowDateTime); + if (n) { + n /= 10; + n -= ((369 * 365 + 89) * (uint64_t) 86400) * 1000000; + } + + tv->tv_sec = n / 1000000; + tv->tv_usec = n % 1000000; } #endif +#endif static int get_random_fd(void) { - struct timeval tv; - static int fd = -2; - int i; - - if (fd == -2) { - gettimeofday(&tv, 0); - fd = open("/dev/urandom", O_RDONLY); - if (fd == -1) - fd = open("/dev/random", O_RDONLY | O_NONBLOCK); - srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec); - } - /* Crank the random number generator a few times */ - gettimeofday(&tv, 0); - for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--) - rand(); - return fd; + struct timeval tv; + static int fd = -2; + int i; + + if (fd == -2) { + gettimeofday(&tv, 0); +#ifndef _WIN32 + fd = open("/dev/urandom", O_RDONLY); + if (fd == -1) + fd = open("/dev/random", O_RDONLY | O_NONBLOCK); + if (fd >= 0) { + i = fcntl(fd, F_GETFD); + if (i >= 0) + fcntl(fd, F_SETFD, i | FD_CLOEXEC); + } +#endif + srand(((unsigned)getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec); +#ifdef DO_JRAND_MIX + jrand_seed[0] = getpid() ^ (tv.tv_sec & 0xFFFF); + jrand_seed[1] = getppid() ^ (tv.tv_usec & 0xFFFF); + jrand_seed[2] = (tv.tv_sec ^ tv.tv_usec) >> 16; +#endif + } + /* Crank the random number generator a few times */ + gettimeofday(&tv, 0); + for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--) + rand(); + return fd; } @@ -161,94 +177,76 @@ static int get_random_fd(void) */ static void get_random_bytes(void *buf, int nbytes) { - int i, n = nbytes, fd = get_random_fd(); - int lose_counter = 0; - unsigned char *cp = (unsigned char *) buf; - - if (fd >= 0) { - while (n > 0) { - i = read(fd, cp, n); - if (i <= 0) { - if (lose_counter++ > 16) - break; - continue; - } - n -= i; - cp += i; - lose_counter = 0; - } - } - - /* - * We do this all the time, but this is the only source of - * randomness if /dev/random/urandom is out to lunch. - */ - for (cp = buf, i = 0; i < nbytes; i++) - *cp++ ^= (rand() >> 7) & 0xFF; -} - -#if defined(_WIN32) -#include /* very important */ - -#include /* remember to link w/ iphlpapi.lib */ -#if defined(uuid_t) -#undef uuid_t + int i, n = nbytes, fd; + int lose_counter = 0; + unsigned char *cp = buf; + +#ifdef HAVE_GETRANDOM + i = getrandom(buf, nbytes, 0); + if (i == nbytes) + return; +#endif +#ifdef HAVE_GETENTROPY + if (getentropy(buf, nbytes) == 0) + return; #endif + fd = get_random_fd(); + if (fd >= 0) { + while (n > 0) { + i = read(fd, cp, n); + if (i <= 0) { + if (lose_counter++ > 16) + break; + continue; + } + n -= i; + cp += i; + lose_counter = 0; + } + } + + /* + * We do this all the time, but this is the only source of + * randomness if /dev/random/urandom is out to lunch. + */ + for (cp = buf, i = 0; i < nbytes; i++) + *cp++ ^= (rand() >> 7) & 0xFF; +#ifdef DO_JRAND_MIX + { + unsigned short tmp_seed[3]; + + memcpy(tmp_seed, jrand_seed, sizeof(tmp_seed)); + jrand_seed[2] = jrand_seed[2] ^ syscall(__NR_gettid); + for (cp = buf, i = 0; i < nbytes; i++) + *cp++ ^= (jrand48(tmp_seed) >> 7) & 0xFF; + memcpy(jrand_seed, tmp_seed, + sizeof(jrand_seed) - sizeof(unsigned short)); + } +#endif -#define IP_LOCALHOST 0x0100007F - -static int get_node_id(unsigned char *byMAC) -{ - DWORD i, dwSize; - PMIB_IPADDRTABLE pAddr = NULL; - MIB_IFROW iInfo; - PFIXED_INFO pFI = NULL; - - /* Get all IP addresses held by this machine; if it's connected to a network, there's at least one - that's not localhost */ - dwSize = 0; - GetIpAddrTable(NULL, &dwSize, TRUE); - pAddr = (PMIB_IPADDRTABLE)malloc(sizeof(unsigned char) * dwSize); - if (!GetIpAddrTable(pAddr, &dwSize, TRUE)) - { - for (i = 0; i < pAddr->dwNumEntries; ++i) - { - if (IP_LOCALHOST != pAddr->table[i].dwAddr) - { - /* Not localhost, so get the interface */ - memset(&iInfo, 0, sizeof(MIB_IFROW)); - iInfo.dwIndex = pAddr->table[i].dwIndex; - GetIfEntry(&iInfo); - - if (MIB_IF_TYPE_ETHERNET == iInfo.dwType) - { - /*iInfo.bPhysAddr contains the MAC address of this interface*/ - memcpy(byMAC, iInfo.bPhysAddr, iInfo.dwPhysAddrLen); - free(pAddr); - return 1; - } - } - } - } - free(pAddr); - return 0; + return; } -#else + /* * Get the ethernet hardware address, if we can find it... + * + * XXX for a windows version, probably should use GetAdaptersInfo: + * http://www.codeguru.com/cpp/i-n/network/networkinformation/article.php/c5451 + * commenting out get_node_id just to get gen_uuid to compile under windows + * is not the right way to go! */ static int get_node_id(unsigned char *node_id) { #ifdef HAVE_NET_IF_H - int sd; - struct ifreq ifr, *ifrp; - struct ifconf ifc; - char buf[1024]; - int n, i; - unsigned char *a; + int sd; + struct ifreq ifr, *ifrp; + struct ifconf ifc; + char buf[1024]; + int n, i; + unsigned char *a; #ifdef HAVE_NET_IF_DL_H - struct sockaddr_dl *sdlp; + struct sockaddr_dl *sdlp; #endif /* @@ -267,151 +265,431 @@ static int get_node_id(unsigned char *node_id) #define ifreq_size(i) sizeof(struct ifreq) #endif /* HAVE_SA_LEN*/ - sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); - if (sd < 0) { - return -1; - } - memset(buf, 0, sizeof(buf)); - ifc.ifc_len = sizeof(buf); - ifc.ifc_buf = buf; - if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) { - close(sd); - return -1; - } - n = ifc.ifc_len; - for (i = 0; i < n; i+= ifreq_size(*ifrp) ) { - ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i); - strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ); + sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP); + if (sd < 0) { + return -1; + } + memset(buf, 0, sizeof(buf)); + ifc.ifc_len = sizeof(buf); + ifc.ifc_buf = buf; + if (ioctl (sd, SIOCGIFCONF, (char *)&ifc) < 0) { + close(sd); + return -1; + } + n = ifc.ifc_len; + for (i = 0; i < n; i+= ifreq_size(*ifrp) ) { + ifrp = (struct ifreq *)((char *) ifc.ifc_buf+i); + strncpy(ifr.ifr_name, ifrp->ifr_name, IFNAMSIZ); #ifdef SIOCGIFHWADDR - if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0) - continue; - a = (unsigned char *) &ifr.ifr_hwaddr.sa_data; + if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0) + continue; + a = (unsigned char *) &ifr.ifr_hwaddr.sa_data; #else #ifdef SIOCGENADDR - if (ioctl(sd, SIOCGENADDR, &ifr) < 0) - continue; - a = (unsigned char *) ifr.ifr_enaddr; + if (ioctl(sd, SIOCGENADDR, &ifr) < 0) + continue; + a = (unsigned char *) ifr.ifr_enaddr; #else #ifdef HAVE_NET_IF_DL_H - sdlp = (struct sockaddr_dl *) &ifrp->ifr_addr; - if ((sdlp->sdl_family != AF_LINK) || (sdlp->sdl_alen != 6)) - continue; - a = (unsigned char *) &sdlp->sdl_data[sdlp->sdl_nlen]; + sdlp = (struct sockaddr_dl *) &ifrp->ifr_addr; + if ((sdlp->sdl_family != AF_LINK) || (sdlp->sdl_alen != 6)) + continue; + a = (unsigned char *) &sdlp->sdl_data[sdlp->sdl_nlen]; #else - /* - * XXX we don't have a way of getting the hardware - * address - */ - close(sd); - return 0; + /* + * XXX we don't have a way of getting the hardware + * address + */ + close(sd); + return 0; #endif /* HAVE_NET_IF_DL_H */ #endif /* SIOCGENADDR */ #endif /* SIOCGIFHWADDR */ - if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5]) - continue; - if (node_id) { - memcpy(node_id, a, 6); - close(sd); - return 1; - } - } - close(sd); -#endif - return 0; -} -#endif /*defined(_WIN32)*/ - -/* Expose get_node_id to API */ -int uuid_get_node_id(unsigned char *node_id) -{ - return get_node_id(node_id); + if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5]) + continue; + if (node_id) { + memcpy(node_id, a, 6); + close(sd); + return 1; + } + } + close(sd); +#endif + return 0; } - /* Assume that the gettimeofday() has microsecond granularity */ #define MAX_ADJUSTMENT 10 static int get_clock(uint32_t *clock_high, uint32_t *clock_low, - uint16_t *ret_clock_seq) + uint16_t *ret_clock_seq, int *num) { - static int adjustment = 0; - static struct timeval last = {0, 0}; - static uint16_t clock_seq; - struct timeval tv; - uint64_t clock_reg; + THREAD_LOCAL int adjustment = 0; + THREAD_LOCAL struct timeval last = {0, 0}; + THREAD_LOCAL int state_fd = -2; + THREAD_LOCAL FILE *state_f; + THREAD_LOCAL uint16_t clock_seq; + struct timeval tv; +#ifndef _WIN32 + struct flock fl; +#endif + uint64_t clock_reg; + mode_t save_umask; + int len; + + if (state_fd == -2) { + save_umask = umask(0); + state_fd = open("/var/lib/libuuid/clock.txt", + O_RDWR|O_CREAT, 0660); + (void) umask(save_umask); + if (state_fd >= 0) { + state_f = fdopen(state_fd, "r+"); + if (!state_f) { + close(state_fd); + state_fd = -1; + } + } + } +#ifndef _WIN32 + fl.l_type = F_WRLCK; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; + fl.l_pid = 0; + if (state_fd >= 0) { + rewind(state_f); + while (fcntl(state_fd, F_SETLKW, &fl) < 0) { + if ((errno == EAGAIN) || (errno == EINTR)) + continue; + fclose(state_f); + state_fd = -1; + break; + } + } +#endif + if (state_fd >= 0) { + unsigned int cl; + unsigned long tv1, tv2; + int a; + + if (fscanf(state_f, "clock: %04x tv: %lu %lu adj: %d\n", + &cl, &tv1, &tv2, &a) == 4) { + clock_seq = cl & 0x3FFF; + last.tv_sec = tv1; + last.tv_usec = tv2; + adjustment = a; + } + } + + if ((last.tv_sec == 0) && (last.tv_usec == 0)) { + get_random_bytes(&clock_seq, sizeof(clock_seq)); + clock_seq &= 0x3FFF; + gettimeofday(&last, 0); + last.tv_sec--; + } try_again: - gettimeofday(&tv, 0); - if ((last.tv_sec == 0) && (last.tv_usec == 0)) { - get_random_bytes(&clock_seq, sizeof(clock_seq)); - clock_seq &= 0x3FFF; - last = tv; - last.tv_sec--; - } - if ((tv.tv_sec < last.tv_sec) || - ((tv.tv_sec == last.tv_sec) && - (tv.tv_usec < last.tv_usec))) { - clock_seq = (clock_seq+1) & 0x3FFF; - adjustment = 0; - last = tv; - } else if ((tv.tv_sec == last.tv_sec) && - (tv.tv_usec == last.tv_usec)) { - if (adjustment >= MAX_ADJUSTMENT) - goto try_again; - adjustment++; - } else { - adjustment = 0; - last = tv; - } - - clock_reg = tv.tv_usec*10 + adjustment; - clock_reg += ((uint64_t) tv.tv_sec)*10000000; - clock_reg += (((uint64_t) 0x01B21DD2) << 32) + 0x13814000; - - *clock_high = clock_reg >> 32; - *clock_low = clock_reg; - *ret_clock_seq = clock_seq; - return 0; + gettimeofday(&tv, 0); + if ((tv.tv_sec < last.tv_sec) || + ((tv.tv_sec == last.tv_sec) && + (tv.tv_usec < last.tv_usec))) { + clock_seq = (clock_seq+1) & 0x3FFF; + adjustment = 0; + last = tv; + } else if ((tv.tv_sec == last.tv_sec) && + (tv.tv_usec == last.tv_usec)) { + if (adjustment >= MAX_ADJUSTMENT) + goto try_again; + adjustment++; + } else { + adjustment = 0; + last = tv; + } + + clock_reg = tv.tv_usec*10 + adjustment; + clock_reg += ((uint64_t) tv.tv_sec)*10000000; + clock_reg += (((uint64_t) 0x01B21DD2) << 32) + 0x13814000; + + if (num && (*num > 1)) { + adjustment += *num - 1; + last.tv_usec += adjustment / 10; + adjustment = adjustment % 10; + last.tv_sec += last.tv_usec / 1000000; + last.tv_usec = last.tv_usec % 1000000; + } + + if (state_fd > 0) { + rewind(state_f); + len = fprintf(state_f, + "clock: %04x tv: %016lu %08lu adj: %08d\n", + clock_seq, (unsigned long)last.tv_sec, + (unsigned long)last.tv_usec, adjustment); + fflush(state_f); + if (ftruncate(state_fd, len) < 0) { + fprintf(state_f, " \n"); + fflush(state_f); + } + rewind(state_f); +#ifndef _WIN32 + fl.l_type = F_UNLCK; + if (fcntl(state_fd, F_SETLK, &fl) < 0) { + fclose(state_f); + state_fd = -1; + } +#endif + } + + *clock_high = clock_reg >> 32; + *clock_low = clock_reg; + *ret_clock_seq = clock_seq; + return 0; +} + +#if defined(USE_UUIDD) && defined(HAVE_SYS_UN_H) +static ssize_t read_all(int fd, char *buf, size_t count) +{ + ssize_t ret; + ssize_t c = 0; + int tries = 0; + + memset(buf, 0, count); + while (count > 0) { + ret = read(fd, buf, count); + if (ret <= 0) { + if ((errno == EAGAIN || errno == EINTR || ret == 0) && + (tries++ < 5)) + continue; + return c ? c : -1; + } + if (ret > 0) + tries = 0; + count -= ret; + buf += ret; + c += ret; + } + return c; +} + +/* + * Close all file descriptors + */ +static void close_all_fds(void) +{ + int i, max; + +#if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX) + max = sysconf(_SC_OPEN_MAX); +#elif defined(HAVE_GETDTABLESIZE) + max = getdtablesize(); +#elif defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE) + struct rlimit rl; + + getrlimit(RLIMIT_NOFILE, &rl); + max = rl.rlim_cur; +#else + max = OPEN_MAX; +#endif + + for (i=0; i < max; i++) { + close(i); + if (i <= 2) + open("/dev/null", O_RDWR); + } +} +#endif /* defined(USE_UUIDD) && defined(HAVE_SYS_UN_H) */ + +#if __GNUC_PREREQ (4, 6) +#pragma GCC diagnostic push +#if !defined(USE_UUIDD) || !defined(HAVE_SYS_UN_H) +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif +#endif +/* + * Try using the uuidd daemon to generate the UUID + * + * Returns 0 on success, non-zero on failure. + */ +static int get_uuid_via_daemon(int op, uuid_t out, int *num) +{ +#if defined(USE_UUIDD) && defined(HAVE_SYS_UN_H) + char op_buf[64]; + int op_len; + int s; + ssize_t ret; + int32_t reply_len = 0, expected = 16; + struct sockaddr_un srv_addr; + struct stat st; + pid_t pid; + static const char *uuidd_path = UUIDD_PATH; + static int access_ret = -2; + static int start_attempts = 0; + + if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) + return -1; + + srv_addr.sun_family = AF_UNIX; + strcpy(srv_addr.sun_path, UUIDD_SOCKET_PATH); + + if (connect(s, (const struct sockaddr *) &srv_addr, + sizeof(struct sockaddr_un)) < 0) { + if (access_ret == -2) + access_ret = access(uuidd_path, X_OK); + if (access_ret == 0) + access_ret = stat(uuidd_path, &st); + if (access_ret == 0 && (st.st_mode & (S_ISUID | S_ISGID)) == 0) + access_ret = access(UUIDD_DIR, W_OK); + if (access_ret == 0 && start_attempts++ < 5) { + if ((pid = fork()) == 0) { + close_all_fds(); + execl(uuidd_path, "uuidd", "-qT", "300", + (char *) NULL); + exit(1); + } + (void) waitpid(pid, 0, 0); + if (connect(s, (const struct sockaddr *) &srv_addr, + sizeof(struct sockaddr_un)) < 0) + goto fail; + } else + goto fail; + } + op_buf[0] = op; + op_len = 1; + if (op == UUIDD_OP_BULK_TIME_UUID) { + memcpy(op_buf+1, num, sizeof(*num)); + op_len += sizeof(*num); + expected += sizeof(*num); + } + + ret = write(s, op_buf, op_len); + if (ret < 1) + goto fail; + + ret = read_all(s, (char *) &reply_len, sizeof(reply_len)); + if (ret < 0) + goto fail; + + if (reply_len != expected) + goto fail; + + ret = read_all(s, op_buf, reply_len); + + if (op == UUIDD_OP_BULK_TIME_UUID) + memcpy(op_buf+16, num, sizeof(int)); + + memcpy(out, op_buf, 16); + + close(s); + return ((ret == expected) ? 0 : -1); + +fail: + close(s); +#endif + return -1; +} +#if __GNUC_PREREQ (4, 6) +#pragma GCC diagnostic pop +#endif + +void uuid__generate_time(uuid_t out, int *num) +{ + static unsigned char node_id[6]; + static int has_init = 0; + struct uuid uu; + uint32_t clock_mid; + + if (!has_init) { + if (get_node_id(node_id) <= 0) { + get_random_bytes(node_id, 6); + /* + * Set multicast bit, to prevent conflicts + * with IEEE 802 addresses obtained from + * network cards + */ + node_id[0] |= 0x01; + } + has_init = 1; + } + get_clock(&clock_mid, &uu.time_low, &uu.clock_seq, num); + uu.clock_seq |= 0x8000; + uu.time_mid = (uint16_t) clock_mid; + uu.time_hi_and_version = ((clock_mid >> 16) & 0x0FFF) | 0x1000; + memcpy(uu.node, node_id, 6); + uuid_pack(&uu, out); } void uuid_generate_time(uuid_t out) { - static unsigned char node_id[6]; - static int has_init = 0; - struct uuid uu; - uint32_t clock_mid; - - if (!has_init) { - if (get_node_id(node_id) <= 0) { - get_random_bytes(node_id, 6); - /* - * Set multicast bit, to prevent conflicts - * with IEEE 802 addresses obtained from - * network cards - */ - node_id[0] |= 0x01; - } - has_init = 1; - } - get_clock(&clock_mid, &uu.time_low, &uu.clock_seq); - uu.clock_seq |= 0x8000; - uu.time_mid = (uint16_t) clock_mid; - uu.time_hi_and_version = ((clock_mid >> 16) & 0x0FFF) | 0x1000; - memcpy(uu.node, node_id, 6); - uuid_pack(&uu, out); +#ifdef TLS + THREAD_LOCAL int num = 0; + THREAD_LOCAL struct uuid uu; + THREAD_LOCAL time_t last_time = 0; + time_t now; + + if (num > 0) { + now = time(0); + if (now > last_time+1) + num = 0; + } + if (num <= 0) { + num = 1000; + if (get_uuid_via_daemon(UUIDD_OP_BULK_TIME_UUID, + out, &num) == 0) { + last_time = time(0); + uuid_unpack(out, &uu); + num--; + return; + } + num = 0; + } + if (num > 0) { + uu.time_low++; + if (uu.time_low == 0) { + uu.time_mid++; + if (uu.time_mid == 0) + uu.time_hi_and_version++; + } + num--; + uuid_pack(&uu, out); + return; + } +#else + if (get_uuid_via_daemon(UUIDD_OP_TIME_UUID, out, 0) == 0) + return; +#endif + + uuid__generate_time(out, 0); +} + + +void uuid__generate_random(uuid_t out, int *num) +{ + uuid_t buf; + struct uuid uu; + int i, n; + + if (!num || !*num) + n = 1; + else + n = *num; + + for (i = 0; i < n; i++) { + get_random_bytes(buf, sizeof(buf)); + uuid_unpack(buf, &uu); + + uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000; + uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) + | 0x4000; + uuid_pack(&uu, out); + out += sizeof(uuid_t); + } } void uuid_generate_random(uuid_t out) { - uuid_t buf; - struct uuid uu; - - get_random_bytes(buf, sizeof(buf)); - uuid_unpack(buf, &uu); + int num = 1; + /* No real reason to use the daemon for random uuid's -- yet */ - uu.clock_seq = (uu.clock_seq & 0x3FFF) | 0x8000; - uu.time_hi_and_version = (uu.time_hi_and_version & 0x0FFF) | 0x4000; - uuid_pack(&uu, out); + uuid__generate_random(out, &num); } @@ -423,8 +701,8 @@ void uuid_generate_random(uuid_t out) */ void uuid_generate(uuid_t out) { - if (get_random_fd() >= 0) - uuid_generate_random(out); - else - uuid_generate_time(out); + if (get_random_fd() >= 0) + uuid_generate_random(out); + else + uuid_generate_time(out); } diff --git a/Utilities/gdcmuuid/isnull.c b/Utilities/gdcmuuid/isnull.c new file mode 100644 index 00000000000..170c9a20d42 --- /dev/null +++ b/Utilities/gdcmuuid/isnull.c @@ -0,0 +1,49 @@ +/* + * isnull.c --- Check whether or not the UUID is null + * + * Copyright (C) 1996, 1997 Theodore Ts'o. + * + * %Begin-Header% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 NOT ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * %End-Header% + */ + +#include "config.h" +#include "uuidP.h" + +/* Returns 1 if the uuid is the NULL uuid */ +int uuid_is_null(const uuid_t uu) +{ + const unsigned char *cp; + int i; + + for (i=0, cp = uu; i < 16; i++) + if (*cp++) + return 0; + return 1; +} + diff --git a/Utilities/gdcmuuid/pack.c b/Utilities/gdcmuuid/pack.c index b166c2afe09..3db21aef691 100644 --- a/Utilities/gdcmuuid/pack.c +++ b/Utilities/gdcmuuid/pack.c @@ -1,4 +1,3 @@ -/* vi: set sw=4 ts=4: */ /* * Internal routine for packing UUID's * @@ -33,37 +32,39 @@ * %End-Header% */ +#include "config.h" #include #include "uuidP.h" void uuid_pack(const struct uuid *uu, uuid_t ptr) { - uint32_t tmp; - unsigned char *out = ptr; + uint32_t tmp; + unsigned char *out = ptr; - tmp = uu->time_low; - out[3] = (unsigned char) tmp; - tmp >>= 8; - out[2] = (unsigned char) tmp; - tmp >>= 8; - out[1] = (unsigned char) tmp; - tmp >>= 8; - out[0] = (unsigned char) tmp; + tmp = uu->time_low; + out[3] = (unsigned char) tmp; + tmp >>= 8; + out[2] = (unsigned char) tmp; + tmp >>= 8; + out[1] = (unsigned char) tmp; + tmp >>= 8; + out[0] = (unsigned char) tmp; - tmp = uu->time_mid; - out[5] = (unsigned char) tmp; - tmp >>= 8; - out[4] = (unsigned char) tmp; + tmp = uu->time_mid; + out[5] = (unsigned char) tmp; + tmp >>= 8; + out[4] = (unsigned char) tmp; - tmp = uu->time_hi_and_version; - out[7] = (unsigned char) tmp; - tmp >>= 8; - out[6] = (unsigned char) tmp; + tmp = uu->time_hi_and_version; + out[7] = (unsigned char) tmp; + tmp >>= 8; + out[6] = (unsigned char) tmp; - tmp = uu->clock_seq; - out[9] = (unsigned char) tmp; - tmp >>= 8; - out[8] = (unsigned char) tmp; + tmp = uu->clock_seq; + out[9] = (unsigned char) tmp; + tmp >>= 8; + out[8] = (unsigned char) tmp; - memcpy(out+10, uu->node, 6); + memcpy(out+10, uu->node, 6); } + diff --git a/Utilities/gdcmuuid/parse.c b/Utilities/gdcmuuid/parse.c index 1b50035fc3c..4c0857dfb38 100644 --- a/Utilities/gdcmuuid/parse.c +++ b/Utilities/gdcmuuid/parse.c @@ -1,4 +1,3 @@ -/* vi: set sw=4 ts=4: */ /* * parse.c --- UUID parsing * @@ -33,6 +32,7 @@ * %End-Header% */ +#include "config.h" #include #include #include @@ -42,39 +42,39 @@ int uuid_parse(const char *in, uuid_t uu) { - struct uuid uuid; - int i; - const char *cp; - char buf[3]; + struct uuid uuid; + int i; + const char *cp; + char buf[3]; - if (strlen(in) != 36) - return -1; - for (i=0, cp = in; i <= 36; i++,cp++) { - if ((i == 8) || (i == 13) || (i == 18) || - (i == 23)) { - if (*cp == '-') - continue; - else - return -1; - } - if (i== 36) - if (*cp == 0) - continue; - if (!isxdigit(*cp)) - return -1; - } - uuid.time_low = strtoul(in, NULL, 16); - uuid.time_mid = strtoul(in+9, NULL, 16); - uuid.time_hi_and_version = strtoul(in+14, NULL, 16); - uuid.clock_seq = strtoul(in+19, NULL, 16); - cp = in+24; - buf[2] = 0; - for (i=0; i < 6; i++) { - buf[0] = *cp++; - buf[1] = *cp++; - uuid.node[i] = strtoul(buf, NULL, 16); - } + if (strlen(in) != 36) + return -1; + for (i=0, cp = in; i <= 36; i++,cp++) { + if ((i == 8) || (i == 13) || (i == 18) || + (i == 23)) { + if (*cp == '-') + continue; + else + return -1; + } + if (i== 36) + if (*cp == 0) + continue; + if (!isxdigit(*cp)) + return -1; + } + uuid.time_low = strtoul(in, NULL, 16); + uuid.time_mid = strtoul(in+9, NULL, 16); + uuid.time_hi_and_version = strtoul(in+14, NULL, 16); + uuid.clock_seq = strtoul(in+19, NULL, 16); + cp = in+24; + buf[2] = 0; + for (i=0; i < 6; i++) { + buf[0] = *cp++; + buf[1] = *cp++; + uuid.node[i] = strtoul(buf, NULL, 16); + } - uuid_pack(&uuid, uu); - return 0; + uuid_pack(&uuid, uu); + return 0; } diff --git a/Utilities/gdcmuuid/unpack.c b/Utilities/gdcmuuid/unpack.c index f9cd4e8596b..2c8043dfe0c 100644 --- a/Utilities/gdcmuuid/unpack.c +++ b/Utilities/gdcmuuid/unpack.c @@ -1,4 +1,3 @@ -/* vi: set sw=4 ts=4: */ /* * Internal routine for unpacking UUID * @@ -33,31 +32,33 @@ * %End-Header% */ +#include "config.h" #include #include "uuidP.h" void uuid_unpack(const uuid_t in, struct uuid *uu) { - const uint8_t *ptr = in; - uint32_t tmp; + const uint8_t *ptr = in; + uint32_t tmp; - tmp = *ptr++; - tmp = (tmp << 8) | *ptr++; - tmp = (tmp << 8) | *ptr++; - tmp = (tmp << 8) | *ptr++; - uu->time_low = tmp; + tmp = *ptr++; + tmp = (tmp << 8) | *ptr++; + tmp = (tmp << 8) | *ptr++; + tmp = (tmp << 8) | *ptr++; + uu->time_low = tmp; - tmp = *ptr++; - tmp = (tmp << 8) | *ptr++; - uu->time_mid = tmp; + tmp = *ptr++; + tmp = (tmp << 8) | *ptr++; + uu->time_mid = tmp; - tmp = *ptr++; - tmp = (tmp << 8) | *ptr++; - uu->time_hi_and_version = tmp; + tmp = *ptr++; + tmp = (tmp << 8) | *ptr++; + uu->time_hi_and_version = tmp; - tmp = *ptr++; - tmp = (tmp << 8) | *ptr++; - uu->clock_seq = tmp; + tmp = *ptr++; + tmp = (tmp << 8) | *ptr++; + uu->clock_seq = tmp; - memcpy(uu->node, ptr, 6); + memcpy(uu->node, ptr, 6); } + diff --git a/Utilities/gdcmuuid/unparse.c b/Utilities/gdcmuuid/unparse.c index 5685c51e962..c556ae63c2f 100644 --- a/Utilities/gdcmuuid/unparse.c +++ b/Utilities/gdcmuuid/unparse.c @@ -1,4 +1,3 @@ -/* vi: set sw=4 ts=4: */ /* * unparse.c -- convert a UUID to string * @@ -33,15 +32,16 @@ * %End-Header% */ +#include "config.h" #include #include "uuidP.h" static const char *fmt_lower = - "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"; + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x"; static const char *fmt_upper = - "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X"; + "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X"; #ifdef UUID_UNPARSE_DEFAULT_UPPER #define FMT_DEFAULT fmt_upper @@ -51,27 +51,27 @@ static const char *fmt_upper = static void uuid_unparse_x(const uuid_t uu, char *out, const char *fmt) { - struct uuid uuid; + struct uuid uuid; - uuid_unpack(uu, &uuid); - sprintf(out, fmt, - uuid.time_low, uuid.time_mid, uuid.time_hi_and_version, - uuid.clock_seq >> 8, uuid.clock_seq & 0xFF, - uuid.node[0], uuid.node[1], uuid.node[2], - uuid.node[3], uuid.node[4], uuid.node[5]); + uuid_unpack(uu, &uuid); + sprintf(out, fmt, + uuid.time_low, uuid.time_mid, uuid.time_hi_and_version, + uuid.clock_seq >> 8, uuid.clock_seq & 0xFF, + uuid.node[0], uuid.node[1], uuid.node[2], + uuid.node[3], uuid.node[4], uuid.node[5]); } void uuid_unparse_lower(const uuid_t uu, char *out) { - uuid_unparse_x(uu, out, fmt_lower); + uuid_unparse_x(uu, out, fmt_lower); } void uuid_unparse_upper(const uuid_t uu, char *out) { - uuid_unparse_x(uu, out, fmt_upper); + uuid_unparse_x(uu, out, fmt_upper); } void uuid_unparse(const uuid_t uu, char *out) { - uuid_unparse_x(uu, out, FMT_DEFAULT); + uuid_unparse_x(uu, out, FMT_DEFAULT); } diff --git a/Utilities/gdcmuuid/uuid.h b/Utilities/gdcmuuid/uuid.h index a8aa09f5e2c..1c332743201 100644 --- a/Utilities/gdcmuuid/uuid.h +++ b/Utilities/gdcmuuid/uuid.h @@ -1,4 +1,3 @@ -/* vi: set sw=4 ts=4: */ /* * Public include file for the UUID library * @@ -38,38 +37,19 @@ #include "uuid_mangle.h" -#if defined(_WIN32) && defined(UUID_DLL) - #if defined(uuid_EXPORTS) - #define UUID_EXPORT __declspec( dllexport ) - #else - #define UUID_EXPORT __declspec( dllimport ) - #endif -#else -#if __GNUC__ >= 4 && defined(UUID_DLL) -#define UUID_EXPORT __attribute__ ((visibility ("default"))) -#else - #define UUID_EXPORT -#endif -#endif /*defined(WIN32)*/ - - #include -#include -#ifdef HAVE_SYS_TIME_H -#include /* timeval CYGWIN is important */ +#ifndef _WIN32 +#include #endif +#include -/* apparently types.h or time.h is polluting our namespace on Win32... */ -#if defined(uuid_t) -#undef uuid_t -#endif typedef unsigned char uuid_t[16]; /* UUID Variant definitions */ -#define UUID_VARIANT_NCS 0 -#define UUID_VARIANT_DCE 1 -#define UUID_VARIANT_MICROSOFT 2 -#define UUID_VARIANT_OTHER 3 +#define UUID_VARIANT_NCS 0 +#define UUID_VARIANT_DCE 1 +#define UUID_VARIANT_MICROSOFT 2 +#define UUID_VARIANT_OTHER 3 /* UUID Type definitions */ #define UUID_TYPE_DCE_TIME 1 @@ -78,10 +58,10 @@ typedef unsigned char uuid_t[16]; /* Allow UUID constants to be defined */ #ifdef __GNUC__ #define UUID_DEFINE(name,u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15) \ - static const uuid_t name ATTRIBUTE_UNUSED = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15} + static const uuid_t name __attribute__ ((unused)) = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15} #else #define UUID_DEFINE(name,u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15) \ - static const uuid_t name = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15} + static const uuid_t name = {u0,u1,u2,u3,u4,u5,u6,u7,u8,u9,u10,u11,u12,u13,u14,u15} #endif #ifdef __cplusplus @@ -89,31 +69,27 @@ extern "C" { #endif /* clear.c */ -/*void uuid_clear(uuid_t uu);*/ -#define uuid_clear(uu) memset(uu, 0, sizeof(uu)) +void uuid_clear(uuid_t uu); /* compare.c */ int uuid_compare(const uuid_t uu1, const uuid_t uu2); /* copy.c */ -/*void uuid_copy(uuid_t dst, const uuid_t src);*/ -#define uuid_copy(dst,src) memcpy(dst, src, sizeof(dst)) +void uuid_copy(uuid_t dst, const uuid_t src); /* gen_uuid.c */ -UUID_EXPORT void uuid_generate(uuid_t out); +void uuid_generate(uuid_t out); void uuid_generate_random(uuid_t out); -UUID_EXPORT int uuid_get_node_id(unsigned char *node_id); void uuid_generate_time(uuid_t out); /* isnull.c */ -/*int uuid_is_null(const uuid_t uu);*/ -#define uuid_is_null(uu) (!memcmp(uu, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", sizeof(uu))) +int uuid_is_null(const uuid_t uu); /* parse.c */ -UUID_EXPORT int uuid_parse(const char *in, uuid_t uu); +int uuid_parse(const char *in, uuid_t uu); /* unparse.c */ -UUID_EXPORT void uuid_unparse(const uuid_t uu, char *out); +void uuid_unparse(const uuid_t uu, char *out); void uuid_unparse_lower(const uuid_t uu, char *out); void uuid_unparse_upper(const uuid_t uu, char *out); diff --git a/Utilities/gdcmuuid/uuidP.h b/Utilities/gdcmuuid/uuidP.h index 10900650e87..ef4bacb7066 100644 --- a/Utilities/gdcmuuid/uuidP.h +++ b/Utilities/gdcmuuid/uuidP.h @@ -1,4 +1,3 @@ -/* vi: set sw=4 ts=4: */ /* * uuid.h -- private header file for uuids * @@ -33,18 +32,10 @@ * %End-Header% */ -#if HAVE_INTTYPES_H +#ifdef HAVE_INTTYPES_H #include -#endif -#if defined(_MSC_VER) || defined(__BORLANDC__) -typedef signed __int8 int8_t; -typedef signed __int16 int16_t; -typedef signed __int32 int32_t; -typedef signed __int64 int64_t; -typedef unsigned __int8 uint8_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int32 uint32_t; -typedef unsigned __int64 uint64_t; +#else +#include #endif #include @@ -57,13 +48,21 @@ typedef unsigned __int64 uint64_t; #define TIME_OFFSET_LOW 0x13814000 struct uuid { - uint32_t time_low; - uint16_t time_mid; - uint16_t time_hi_and_version; - uint16_t clock_seq; - uint8_t node[6]; + uint32_t time_low; + uint16_t time_mid; + uint16_t time_hi_and_version; + uint16_t clock_seq; + uint8_t node[6]; }; +#ifndef __GNUC_PREREQ +#if defined(__GNUC__) && defined(__GNUC_MINOR__) +#define __GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +#else +#define __GNUC_PREREQ(maj, min) 0 +#endif +#endif /* * prototypes diff --git a/Utilities/gdcmuuid/uuid_mangle.h.in b/Utilities/gdcmuuid/uuid_mangle.h.in index 5c23aebd269..b0c03fc9fcb 100644 --- a/Utilities/gdcmuuid/uuid_mangle.h.in +++ b/Utilities/gdcmuuid/uuid_mangle.h.in @@ -14,20 +14,24 @@ * nm lib@MANGLE_PREFIX@.a | grep " [TR] " */ -#define uuid_compare @MANGLE_PREFIX@_uuid_compare -#define uuid_generate @MANGLE_PREFIX@_uuid_generate -#define uuid_generate_random @MANGLE_PREFIX@_uuid_generate_random -#define uuid_generate_time @MANGLE_PREFIX@_uuid_generate_time -#define uuid_get_node_id @MANGLE_PREFIX@_uuid_get_node_id -#define uuid_pack @MANGLE_PREFIX@_uuid_pack -#define uuid_parse @MANGLE_PREFIX@_uuid_parse -#define uuid_time @MANGLE_PREFIX@_uuid_time -#define uuid_type @MANGLE_PREFIX@_uuid_type -#define uuid_unpack @MANGLE_PREFIX@_uuid_unpack -#define uuid_unparse @MANGLE_PREFIX@_uuid_unparse -#define uuid_unparse_lower @MANGLE_PREFIX@_uuid_unparse_lower -#define uuid_unparse_upper @MANGLE_PREFIX@_uuid_unparse_upper -#define uuid_variant @MANGLE_PREFIX@_uuid_variant +#define uuid_compare @MANGLE_PREFIX@_uuid_compare +#define uuid_copy @MANGLE_PREFIX@_uuid_copy +#define uuid__generate_random @MANGLE_PREFIX@_uuid__generate_random +#define uuid__generate_time @MANGLE_PREFIX@_uuid__generate_time +#define uuid_generate @MANGLE_PREFIX@_uuid_generate +#define uuid_generate_random @MANGLE_PREFIX@_uuid_generate_random +#define uuid_generate_time @MANGLE_PREFIX@_uuid_generate_time +#define uuid_is_null @MANGLE_PREFIX@_uuid_is_null +#define uuid_get_node_id @MANGLE_PREFIX@_uuid_get_node_id +#define uuid_pack @MANGLE_PREFIX@_uuid_pack +#define uuid_parse @MANGLE_PREFIX@_uuid_parse +#define uuid_time @MANGLE_PREFIX@_uuid_time +#define uuid_type @MANGLE_PREFIX@_uuid_type +#define uuid_unpack @MANGLE_PREFIX@_uuid_unpack +#define uuid_unparse @MANGLE_PREFIX@_uuid_unparse +#define uuid_unparse_lower @MANGLE_PREFIX@_uuid_unparse_lower +#define uuid_unparse_upper @MANGLE_PREFIX@_uuid_unparse_upper +#define uuid_variant @MANGLE_PREFIX@_uuid_variant #define uuid_EXPORTS @MANGLE_PREFIX@uuid_EXPORTS diff --git a/Utilities/gdcmuuid/uuid_time.c b/Utilities/gdcmuuid/uuid_time.c index 8e509ba7ef6..af837a2ca37 100644 --- a/Utilities/gdcmuuid/uuid_time.c +++ b/Utilities/gdcmuuid/uuid_time.c @@ -1,8 +1,7 @@ -/* vi: set sw=4 ts=4: */ /* * uuid_time.c --- Interpret the time field from a uuid. This program - * violates the UUID abstraction barrier by reaching into the guts - * of a UUID and interpreting it. + * violates the UUID abstraction barrier by reaching into the guts + * of a UUID and interpreting it. * * Copyright (C) 1998, 1999 Theodore Ts'o. * @@ -35,132 +34,140 @@ * %End-Header% */ +#include "config.h" + +#ifdef _WIN32 +#define _WIN32_WINNT 0x0500 +#include +#define UUID MYUUID +#endif + #include #ifdef HAVE_UNISTD_H #include #endif #include #include -#include -#ifdef HAVE_WINSOCK_H -#include /* timeval */ +#ifdef HAVE_SYS_TIME_H +#include #endif +#include #include "uuidP.h" time_t uuid_time(const uuid_t uu, struct timeval *ret_tv) { - struct uuid uuid; - uint32_t high; - struct timeval tv; - uint64_t clock_reg; + struct timeval tv; + struct uuid uuid; + uint32_t high; + uint64_t clock_reg; - uuid_unpack(uu, &uuid); + uuid_unpack(uu, &uuid); - high = uuid.time_mid | ((uuid.time_hi_and_version & 0xFFF) << 16); - clock_reg = uuid.time_low | ((uint64_t) high << 32); + high = uuid.time_mid | ((uuid.time_hi_and_version & 0xFFF) << 16); + clock_reg = uuid.time_low | ((uint64_t) high << 32); - clock_reg -= (((uint64_t) 0x01B21DD2) << 32) + 0x13814000; - tv.tv_sec = clock_reg / 10000000; - tv.tv_usec = (clock_reg % 10000000) / 10; + clock_reg -= (((uint64_t) 0x01B21DD2) << 32) + 0x13814000; + tv.tv_sec = clock_reg / 10000000; + tv.tv_usec = (clock_reg % 10000000) / 10; - if (ret_tv) - *ret_tv = tv; + if (ret_tv) + *ret_tv = tv; - return tv.tv_sec; + return tv.tv_sec; } int uuid_type(const uuid_t uu) { - struct uuid uuid; + struct uuid uuid; - uuid_unpack(uu, &uuid); - return ((uuid.time_hi_and_version >> 12) & 0xF); + uuid_unpack(uu, &uuid); + return ((uuid.time_hi_and_version >> 12) & 0xF); } int uuid_variant(const uuid_t uu) { - struct uuid uuid; - int var; - - uuid_unpack(uu, &uuid); - var = uuid.clock_seq; - - if ((var & 0x8000) == 0) - return UUID_VARIANT_NCS; - if ((var & 0x4000) == 0) - return UUID_VARIANT_DCE; - if ((var & 0x2000) == 0) - return UUID_VARIANT_MICROSOFT; - return UUID_VARIANT_OTHER; + struct uuid uuid; + int var; + + uuid_unpack(uu, &uuid); + var = uuid.clock_seq; + + if ((var & 0x8000) == 0) + return UUID_VARIANT_NCS; + if ((var & 0x4000) == 0) + return UUID_VARIANT_DCE; + if ((var & 0x2000) == 0) + return UUID_VARIANT_MICROSOFT; + return UUID_VARIANT_OTHER; } #ifdef DEBUG static const char *variant_string(int variant) { - switch (variant) { - case UUID_VARIANT_NCS: - return "NCS"; - case UUID_VARIANT_DCE: - return "DCE"; - case UUID_VARIANT_MICROSOFT: - return "Microsoft"; - default: - return "Other"; - } + switch (variant) { + case UUID_VARIANT_NCS: + return "NCS"; + case UUID_VARIANT_DCE: + return "DCE"; + case UUID_VARIANT_MICROSOFT: + return "Microsoft"; + default: + return "Other"; + } } int main(int argc, char **argv) { - uuid_t buf; - time_t time_reg; - struct timeval tv; - int type, variant; - - if (argc != 2) { - fprintf(stderr, "Usage: %s uuid\n", argv[0]); - exit(1); - } - if (uuid_parse(argv[1], buf)) { - fprintf(stderr, "Invalid UUID: %s\n", argv[1]); - exit(1); - } - variant = uuid_variant(buf); - type = uuid_type(buf); - time_reg = uuid_time(buf, &tv); - - printf("UUID variant is %d (%s)\n", variant, variant_string(variant)); - if (variant != UUID_VARIANT_DCE) { - printf("Warning: This program only knows how to interpret " - "DCE UUIDs.\n\tThe rest of the output is likely " - "to be incorrect!!\n"); - } - printf("UUID type is %d", type); - switch (type) { - case 1: - printf(" (time based)\n"); - break; - case 2: - printf(" (DCE)\n"); - break; - case 3: - printf(" (name-based)\n"); - break; - case 4: - printf(" (random)\n"); - break; - default: - bb_putchar('\n'); - } - if (type != 1) { - printf("Warning: not a time-based UUID, so UUID time " - "decoding will likely not work!\n"); - } - printf("UUID time is: (%ld, %ld): %s\n", tv.tv_sec, tv.tv_usec, - ctime(&time_reg)); - - return 0; + uuid_t buf; + time_t time_reg; + struct timeval tv; + int type, variant; + + if (argc != 2) { + fprintf(stderr, "Usage: %s uuid\n", argv[0]); + exit(1); + } + if (uuid_parse(argv[1], buf)) { + fprintf(stderr, "Invalid UUID: %s\n", argv[1]); + exit(1); + } + variant = uuid_variant(buf); + type = uuid_type(buf); + time_reg = uuid_time(buf, &tv); + + printf("UUID variant is %d (%s)\n", variant, variant_string(variant)); + if (variant != UUID_VARIANT_DCE) { + printf("Warning: This program only knows how to interpret " + "DCE UUIDs.\n\tThe rest of the output is likely " + "to be incorrect!!\n"); + } + printf("UUID type is %d", type); + switch (type) { + case 1: + printf(" (time based)\n"); + break; + case 2: + printf(" (DCE)\n"); + break; + case 3: + printf(" (name-based)\n"); + break; + case 4: + printf(" (random)\n"); + break; + default: + printf("\n"); + } + if (type != 1) { + printf("Warning: not a time-based UUID, so UUID time " + "decoding will likely not work!\n"); + } + printf("UUID time is: (%ld, %ld): %s\n", (long)tv.tv_sec, (long)tv.tv_usec, + ctime(&time_reg)); + + return 0; } #endif diff --git a/Utilities/gdcmuuid/uuidd.h b/Utilities/gdcmuuid/uuidd.h new file mode 100644 index 00000000000..c71f4b78835 --- /dev/null +++ b/Utilities/gdcmuuid/uuidd.h @@ -0,0 +1,54 @@ +/* + * Definitions used by the uuidd daemon + * + * Copyright (C) 2007 Theodore Ts'o. + * + * %Begin-Header% + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, and the entire permission notice in its entirety, + * including the disclaimer of warranties. + * 2. 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. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF + * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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 NOT ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * %End-Header% + */ + +#ifndef _UUID_UUIDD_H +#define _UUID_UUIDD_H + +#define UUIDD_DIR "/var/lib/libuuid" +#define UUIDD_SOCKET_PATH UUIDD_DIR "/request" +#define UUIDD_PIDFILE_PATH UUIDD_DIR "/uuidd.pid" +#define UUIDD_PATH "/usr/sbin/uuidd" + +#define UUIDD_OP_GETPID 0 +#define UUIDD_OP_GET_MAXOP 1 +#define UUIDD_OP_TIME_UUID 2 +#define UUIDD_OP_RANDOM_UUID 3 +#define UUIDD_OP_BULK_TIME_UUID 4 +#define UUIDD_OP_BULK_RANDOM_UUID 5 +#define UUIDD_MAX_OP UUIDD_OP_BULK_RANDOM_UUID + +extern void uuid__generate_time(uuid_t out, int *num); +extern void uuid__generate_random(uuid_t out, int *num); + +#endif /* _UUID_UUID_H */ diff --git a/Utilities/socketxx/socket++/sockinet.cpp b/Utilities/socketxx/socket++/sockinet.cpp index cd46cbde551..07a3e3a61fd 100644 --- a/Utilities/socketxx/socket++/sockinet.cpp +++ b/Utilities/socketxx/socket++/sockinet.cpp @@ -125,7 +125,15 @@ void sockinetaddr::setaddr(const char* host_name) if ( (sin_addr.s_addr = inet_addr(host_name)) == INADDR_NONE) { hostent* hp = gethostbyname(host_name); if (hp == nullptr) throw sockerr (EADDRNOTAVAIL, "sockinetaddr::setaddr"); - memcpy(&sin_addr, hp->h_addr, hp->h_length); + char** h_addr_list = hp->h_addr_list; + + // Conceptually, we want `char* first_addr = *h_addr_list;` but, on some OSes at least, + // h_addr_list is not actually aligned as a char* should be (8 bytes typically), and so + // we use memcpy() which can do unaligned reads. + void* first_addr; + memcpy(&first_addr, h_addr_list, sizeof(void*)); + + memcpy(&sin_addr, first_addr, hp->h_length); sin_family = hp->h_addrtype; } else sin_family = sockinetbuf::af_inet; diff --git a/Utilities/socketxx/socket++/sockstream.cpp b/Utilities/socketxx/socket++/sockstream.cpp index 02d59ad1f4f..f53d39642f9 100644 --- a/Utilities/socketxx/socket++/sockstream.cpp +++ b/Utilities/socketxx/socket++/sockstream.cpp @@ -272,7 +272,7 @@ bool sockerr::op () const case EHOSTDOWN: case EHOSTUNREACH: case ENOTEMPTY: -# if !defined(__linux__) && !defined(__sun) && !defined(__hpux) && !defined(__EMSCRIPTEN__) // LN +# if !defined(__linux__) && !defined(__sun) && !defined(__hpux) && !defined(__EMSCRIPTEN__) && !defined(__wasi__) // LN case EPROCLIM: # endif case EUSERS: diff --git a/Utilities/socketxx/socket++/sockstream.h b/Utilities/socketxx/socket++/sockstream.h index b4e3ef68b37..0a3fb667f44 100644 --- a/Utilities/socketxx/socket++/sockstream.h +++ b/Utilities/socketxx/socket++/sockstream.h @@ -90,7 +90,7 @@ class MY_API sockerr : public std::exception err = O.err; text = O.text; } - ~sockerr() throw() override {}; + ~sockerr() throw() override {} const char* what () const throw() override { return "sockerr"; } const char* operation () const { return text.text.c_str(); }